Write uncertainty as a specific missing fact that could change the decision, not as a vague “low confidence” label. State what the reviewed evidence supports, what remains an assumption, how either answer would affect the claimed harm, who can obtain the missing evidence, and when the claim will be reconsidered. Keep the current disposition visible: supported for independent verification, unresolved, or rejected. A possible impact is not an observed impact.
The answer changes when a missing deployment setting, caller path, control or asset classification is verified. Until then, avoid turning the worst imaginable outcome into a confirmed finding or treating an absent alert as proof of safety. NIST SP 800-30 Rev. 1 explains that risk estimates carry uncertainty from incomplete knowledge of threats, controls and dependencies; its guidance is to communicate that uncertainty in the result. A good finding note makes the uncertainty useful to the person who can resolve it.
Use an uncertainty record, not an adjective
The following template is short enough to attach to an alert or review ticket. Give each missing fact its own row. If a fact would not change the verdict, priority or remediation decision, it probably belongs in background notes instead of the uncertainty section.
- Claim in one sentence: Given [actor and prerequisite], [input or action] may cross [security boundary] and cause [effect].
- Assessed scope: Repository, immutable revision, relevant components and deployment/environment actually examined.
- Observed evidence: Exact source/configuration references and the behavior they establish.
- Counterevidence: Controls or alternative explanations that could defeat the claim.
- Unknown fact: The smallest unanswered question that could change the conclusion.
- If yes / if no: The consequence of each answer for disposition and priority.
- Evidence owner and check: Who can answer, with what artifact or authorized observation, by when.
- Current disposition: Supported candidate awaiting independent review / unresolved investigation / rejected, with reason. Reopen trigger: A route, configuration, revision or policy change that invalidates today's answer.
Keep the observed and the inferred in different sentences. “The code calls an HTTP client with a request-derived URL” is an observation if the path is traced. “The client can reach an internal metadata endpoint” is an inference unless network policy and runtime behavior are known. A precise source citation establishes the code at a revision; it does not establish that the code is deployed or that an attacker can satisfy every prerequisite.
Filled example: a thumbnail fetcher
Consider a fictional marketplace in which a seller can submit an image URL for a product thumbnail. A scanner flags a server-side request forgery (SSRF) candidate at thumbnail.fetch(url). The source trace shows a seller-supplied URL reaching the fetcher. It also shows a URL allowlist helper, but the reviewer cannot see the deployed egress proxy's policy or whether redirects are rechecked. This is an illustrative source review, not a live test or a claim about any real service.
The OWASP SSRF Prevention Cheat Sheet describes both input validation and network controls because a server making requests on behalf of a user can reach resources unavailable to that user. That general risk identifies what to inspect; the actual path and effect remain case-specific.
| Record field | Filled example |
|---|---|
| Claim | A seller-supplied thumbnail URL may cause the fetcher to contact an internal service after a redirect. |
| Scope | Application revision abc123 (illustrative), thumbnail API and worker source. Production egress configuration was not available. |
| Observed | Seller URL is passed to fetch; the initial hostname is checked against an allowlist; redirect handling is enabled in the HTTP client. |
| Counterevidence | The application checks the first hostname; the platform design mentions an egress proxy. Neither fact establishes what happens after a redirect in the deployed environment. |
| Unknown 1 | Does the client or proxy revalidate the destination after every redirect and DNS resolution? |
| Unknown 2 | Can the worker reach an internal sensitive service from its actual network placement? |
| If validation fails and reach is confirmed | If a redirect or DNS change can select an internal destination and the worker can reach it, independently verify the actor-to-effect path and assess the exposed service. |
| If controls prevent reach | If destination validation or enforced network controls prevent internal traffic on every relevant path, reject this SSRF claim for the assessed deployment; retain any control improvement as a separate recommendation. |
| Owner and next check | Platform owner supplies the active egress policy and worker network placement; code owner confirms redirect behavior for the pinned dependency version. AppSec reviews both before publication. |
| Current disposition | Unresolved investigation. The code path is real, but destination reach and harmful effect are unverified. |
This record is actionable without pretending to know the answer. It also avoids sending a developer a ticket that says only “possible SSRF” and leaves them to discover the missing deployment fact. If controlled validation is needed, the owner should use an authorized test environment and harmless destinations. A source-only assessment must not be described as an executed exploit.
Update the record as evidence arrives
A useful uncertainty note changes. Continue the thumbnail exercise with the following supplied sequence; the artifacts and outcomes are synthetic, not an observation of a running worker.
| Update | New artifact | Decision change |
|---|---|---|
| Monday, initial review | Application checks the first hostname; redirect-following is enabled. | Internal destination and reach remain unresolved. Request the active egress policy and worker placement. |
| Tuesday, platform response | Design document says “all workers use the proxy.” | No verdict change: it describes intent, without binding the thumbnail worker's network route. |
| Wednesday, deployment packet | Selected worker's effective network policy permits outbound connections only through proxy P7; P7 rejects resolved destinations outside the approved image-provider addresses, including redirected requests. The client has no permitted direct fallback. | The proposed internal-destination path is defeated for this deployment, assuming these supplied controls are complete and mandatory. |
| Friday, planned migration | Replacement worker placement has not yet been mapped to P7. | Reopen deployment applicability for the replacement before rollout; Wednesday's decision remains scoped to the original placement. |
The completed Wednesday note is:
Disposition: reject the claimed internal-service SSRF path for worker build T12 under network policy N6 and proxy P7. The initial allowlist alone was insufficient evidence, but the supplied mandatory network/proxy control prevents the proposed destination. Residual recommendation: review application redirect handling to reduce reliance on P7. Excluded: the planned worker placement and any claim of actual data disclosure. Reopen: network route, proxy policy, redirect processing or direct-fallback changes.
This is not a general assurance that an egress proxy stops SSRF. The verdict depends on the specific destination enforcement and lack of bypass supplied by the exercise. OWASP's SSRF guidance treats redirect handling and network restrictions as separate controls; a proxy's mere presence establishes neither.
If Wednesday's packet instead allowed direct worker egress, it would remove the proposed counterevidence without proving the entire attack. The next missing facts would be destination selection, sensitive-service reach and effect. Write exactly those questions. Do not retain the obsolete question “is there a proxy?” once it has been answered.
Choose the next check by what it can decide
For each open fact, finish this sentence: If the answer is A, we will do X; if B, we will do Y. “Find the current proxy version” earns its place only because it selects the policy to inspect. “Collect more logs” is too broad unless the note states which request or denial would change the decision.
When an artifact cannot be obtained, give the engineering owner a concrete choice: keep the feature restricted pending evidence, accept a documented uncertainty through the team's decision process, or make a preventive change whose effect can be checked. None of those decisions transforms missing evidence into an observed vulnerability. A conditional impact statement is more useful than a precise score calculated for an imagined configuration.
Choose between waiting, restricting and repairing
An unresolved claim creates a work decision even when it cannot yet support a final security verdict. For the thumbnail fetcher, distinguish three questions: whether the redirect can select an internal destination, whether the deployed worker can connect to it, and whether the resulting interaction could cause the claimed harm. A team can act on one known weakness while leaving the other questions open.
Suppose the code owner can disable automatic redirects for this feature without breaking the approved image providers. That may be a reasonable precaution while platform retrieves the proxy policy. Record the intended functional consequence and a way to establish that supported thumbnails still work. The action does not prove that internal access was previously possible, and a later rejecting network policy does not erase the value of reducing reliance on that policy.
If disabling redirects would break a contractual workflow, the decision is different. The service owner needs the affected use, available alternatives and time needed to obtain evidence. Do not write “accept risk” as a substitute for those details. A bounded interim decision could keep the feature available only for a restricted set of approved providers while the owner confirms whether that restriction is enforceable on redirected requests. Its protective effect remains conditional until the relevant enforcement is checked.
Use a small decision record rather than a probability invented from confidence adjectives:
| Choice | What must be known | What remains open |
|---|---|---|
| Wait for deployment evidence | Named owner and a useful checkpoint; consequences of delay understood | Whether the original internal-destination path exists |
| Restrict the feature | Restriction is effective on the affected entry and its operational impact is understood | Original exploitability and excluded paths |
| Repair the known source behavior | The proposed change addresses the relevant behavior and ordinary use has an acceptance plan | Production exposure before the change and historical misuse |
A checkpoint is a decision time, not an instruction to switch protection off. If the evidence is still unavailable then, the owner can renew the restriction, pursue another artifact or escalate the unresolved business choice. Automatic removal would turn an administrative date into a security failure.
Keep confidence tied to individual claims
One overall confidence label can conceal uneven evidence. The reviewer may be highly confident that the initial hostname is checked, unsure whether the proxy is mandatory, and entirely unable to assess historical disclosure. Keep those statements separate. Strength in the first cannot compensate for absence in the third.
For this exercise, an evidence update should name the claim it changes: “P7 policy establishes destination rejection for the selected worker” is better than “confidence is now high.” If a later source change enables a direct fallback, the old policy artifact may remain correct while its ability to defeat the path disappears. The question becomes whether requests can bypass that policy, not whether its contents have changed.
This claim-by-claim approach also makes the final report shorter. Once a missing fact is resolved, remove it from the open-question list, retain its evidence in the history and state the remaining limitation directly. A long list of obsolete uncertainties makes readers unable to distinguish unresolved risk from completed investigation.
Next step: Copy the filled table's fields into one open investigation, replacing every illustrative value with a revision, evidence reference and named owner. If another reviewer reads the same evidence differently, use the disagreement protocol. If a developer has contrary evidence, use the dispute workflow to preserve it.