You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
You are remediating Critical/High Trivy findings in this repository and producing a
security-reviewable PR in collaboration with the developer on this session. Read this
whole prompt before editing anything.
How this works: remediate now → open PR → optionally refine with the dev
This is auto-remediation: your job is to do the work now, not to wait for the developer.
You apply every fix you can and open a complete, releasable PR on your own. The developer
loop is an optional refinement that can upgrade a few verdicts later — it is never a
precondition for doing the work or opening the PR. Concretely:
Remediate (alone, now). Parse findings, orient (§2), and resolve everything you can
from the repo and prior docs — apply fixes, build-stage proofs, CVE-database research,
carried-forward verdicts. Never defer a fix you are able to make. This is the bulk of
the work and it requires no developer input.
Open the PR — always, immediately after step 1. Every finding gets a final,
shippable verdict. Findings you fixed → Fixed. Findings you proved don't apply → Not applicable. Findings you cannot prove false on your own → Residual risk –
required, not reachable under current controls, which is itself a complete, releasable
verdict that needs nothing further. The PR is ready for security review as it stands.
Flag (don't block) the upgrade candidates. Some Residual-risk findings could become
Not applicable if the developer supplies live (Tier-2) evidence you can't produce (§3).
Mark these ⏳ EVIDENCE WOULD UPGRADE in the triage table and post the exact commands
(§11). This is an invitation, not a hold — the PR does not wait on it and the verdict is
already valid without it.
Refine if/when the dev responds. If the developer pastes output under ### Pod verification output (§11), cross-reference it, and where it proves a precondition
absent, upgrade Residual risk → Not applicable, regenerating the affected artifacts.
If they never respond, the PR stays valid as-is. The developer may also correct a verdict
directly; treat that as authoritative.
Bottom line: do not park findings waiting for the developer. Every finding leaves your
solo pass with a final verdict. The only thing the loop changes is whether a small number of
Residual-risk items later become false positives — work is never gated on it.
The developer is an optional partner — primarily a runner of specific checks you request,
occasionally a reviewer who corrects a verdict. Keep requests minimal, exact, and tied to a
named precondition.
0. Output contract — the three machine-parsed artifacts
A batch job parses three things literally. If their shape is wrong, the finding is silently dropped — no error is raised. Get these exactly right; everything else in
this prompt serves them.
Artifact
Where
Parsed for
Failure mode
## SWA Exception Justifications
docs/security/trivy-remediation.mdand PR body
per-CVE verdict + prose → SSC comment
wrong heading level or bold/heading mix-up
Triage + finding inventory
PR body + doc
audit trail
missing HIGH/CRITICAL rows
Four hard rules that override everything below:
The verdict string is byte-exact and uses an EN-DASH (–, U+2013), not a hyphen (-).
The parser matches the literal string. Markdown editors and autoformatters silently
convert – to -; if that happens the finding is dropped. After writing, confirm the
verdict lines still contain –. The only two parsed verdicts are:
Not applicable / false positive
Residual risk – required, not reachable under current controls ← note the en-dash
docs/security/trivy-remediation.md is the system of record, not the PR body. It is
appended (never overwritten) every run and feeds the next scan's carry-forward.
Single source of truth for each FP. Write the justification prose once per CVE in
the doc's SWA section. The PR body's SWA section reuses that same text verbatim.
Every ## SWA Exception Justifications entry must have a **Summary:** field —
no exceptions, no "I'll add it later". It is parsed exactly like the other artifacts
above and silently dropped if missing. Before opening or updating the PR, run awk '/^## Scan:/{c++} c==1' docs/security/trivy-remediation.md | grep -c '^\*\*Summary:\*\*'
(scoped to the most recent ## Scan: block only — a plain whole-file grep -c can be
satisfied by Summary fields from older, preserved scans) and confirm the count is at
least the number of ### <package> / <CVE> entries you wrote in this run. If it's
short, go back and add the missing field(s) — do not open the PR and fix it after.
1. Default stance & burden of proof
Every finding is a true positive unless you prove otherwise. The burden is always on
the FP / not-applicable verdict. When in doubt, fix it.
Before writing any FP or not-applicable verdict, the PR must show, for that specific
finding:
A verification step and its literal output proving the package/binary/attack surface
is absent — OR, if you cannot run it (see §3), the exact command handed off for a human
to run.
A named architectural control, build-stage exclusion, or CVE-database citation
(Red Hat / NVD / MITRE / OSV) that breaks the exploit path. Generic claims
("not exploitable", "package unused", "vendor wont-fix") are not evidence.
Evidence unique to this finding (see self-containment rule, §9).
Self-containment rule (applies to every table cell, blurb, and reason): these phrases
are forbidden — same as above, same evidence, see previous, ditto, per row above, per finding above. Two CVEs sharing a package or control still restate
full evidence each. Reviewers read entries out of order.
2. Orient before editing
Read these if they exist and apply their guidance (later entries override earlier):
Conventions:README, CONTRIBUTING, ARCHITECTURE, docs/ overviews.
Repo-specific guidance overrides this prompt on style, tests, and commit format.
BMAD / product context (BMAD): look for bmad-agent/, .bmad/, BMAD.md, or independently docs/prd.md and docs/architecture.md. If found, read before analyzing findings and use them to:
calibrate exploit severity by data sensitivity (PHI/PII/creds raise risk); validate or
refute platform FP arguments (network isolation, runtime controls); scope residual-risk
verdicts to active vs. dead code paths; and enrich SWA blurbs with the app's stated
purpose.
Prior remediation: read docs/security/trivy-remediation.md if present. Use its
recorded verdicts and exploit research as a starting point — re-verify each against the
current findings JSON. Carry a verdict forward only when the same CVE + package +
target reappears with unchanged installed version and the prior evidence still holds; note Carried from prior scan — evidence unchanged. If absent, start from scratch.
3. Your environment & what counts as evidence
You have: the repo (code, Dockerfiles, manifests, lockfiles), context/BMAD files, and prior trivy-remediation.md. You do not have image rebuild or pod (oc rsh) access.
Evidence therefore falls in two tiers:
Tier 1 — you can produce it now (repo-static):
Dockerfile / build-stage proof with line ranges (e.g. package present only in a builder
stage not copied to the final stage).
Repository search showing a package is/isn't referenced by app code/config/scripts.
Lockfile / dependency-tree analysis.
CVE-database research from the allowlist (§5).
Carried-forward pod output already recorded in trivy-remediation.md (cite the prior
date).
Tier 2 — you must hand off (live checks you cannot run):
oc rsh package/binary/linkage checks, id -u, image inspection, Trivy rescan.
Do not fabricate this output. Instead, write the exact commands into the verification
section / a comment for a human to run, and keep the verdict at Residual risk until
the output exists (or carry forward documented prior output).
Never invent pod output, rebuild results, or environment controls. A verdict that requires Tier-2 proof you don't have stays Residual risk – required, not reachable
under current controls with the verification commands attached — it does not become
a false positive on speculation.
4. Findings JSON
Attached as an issue comment under ### Machine-readable findings (findings.json);
Critical/High only. Fields: id, severity, package, version, fixedIn (may be
empty — empty ≠ false positive), status (affected / will_not_fix / fix_deferred / under_investigation / end_of_life), description, primaryURL, target.
Atomic key:target | package | id. Same CVE on a different package/target is a
separate finding. If split across parts ("part 1 of N"), read all parts first. If the
comment is missing or malformed, comment asking for valid JSON before proceeding.
All statuses still require action — none is an automatic FP. For end_of_life, prioritize
upgrading to a supported base image/dependency.
5. Verdicts
Every finding ends in exactly one:
Verdict
Meaning
Pending — base image update
OS-level; resolved by the base-image update in the issue body. Confirm via rebuild + rescan (handoff).
Fixed
A code/build/image change removes or upgrades the package.
Already remediated
Same-scope rebuild/rescan proves it's gone with no new change.
Not applicable / false positive
Concrete evidence proves it doesn't apply.
Residual risk – no fix available
Package remains; no safe repo-only fix.
Residual risk – fix deferred
Package remains; vendor/base-image fix deferred.
Residual risk – required, not reachable under current controls
Package required; exploitability reduced by proven controls.
Needs security exception before release
Unresolved risk lacks compensating evidence.
CVE-database research (required before any residual-risk/not-applicable exploit-precondition
prose). Query the allowlist and cite specifics — paraphrase findings, don't quote vendor
text at length:
Red Hat — access.redhat.com/security/cve/<CVE> (component scope, "Not Affected" statements for UBI/RHEL)
Write specific preconditions (e.g. "NVD shows AV:N/AC:H; Red Hat states the vulnerable
path needs module X not present in this image"), never generic ones.
Constraints: "package unused" is not an FP while it's still installed — try removal
first, else document residual risk. "Requires shell/elevated/not-internet-facing" supports
residual risk only with proven control. Don't invent cluster-level controls you can't
see — name them and hand off verification.
6. Remediation order (smallest safe change that affects the scanned artifact)
Apply the base-image update from the issue body (update FROM + pinned digest).
Update vulnerable OS packages with the correct package manager.
Remove unnecessary runtime packages.
Move build-only tools to non-final stages.
Update app dependencies + lockfiles together.
Replace a dependency/image only when upgrade/removal isn't viable.
Do not suppress instead of fixing: no disabling Trivy, lowering thresholds, expanding .trivyignore, adding VEX/Rego/ignore policy as a substitute, --ignore-unfixed / --ignore-status / new exclude paths, retargeting the scan, removing lockfiles, pinning
vulnerable versions, switching to latest, or unrelated refactors. Compensating controls
justify residual risk; they never make an installed package "Fixed".
7. Acceptable vs unacceptable not-applicable evidence
Acceptable: target/path no longer produced here; package absent from final image
(proven via build-stage analysis or carried-forward pod output); finding applies only to an
intermediate stage not copied forward; same-scope rescan no longer reports it (handoff if
you can't rescan).
Unacceptable: low severity; vendor will_not_fix; no known exploit; "probably unused";
"dev dependency / not reachable / requires elevated perms" without evidence.
8. Required PR body & document structure
Override: This section defines the complete PR body. Ignore any repository PULL_REQUEST_TEMPLATE file — do not answer its questions. Construct the PR body
entirely from the structure below.
PR body must contain
Triage summary — totals before/after + table: | Severity | Original | Fixed | Pending image update | Residual | Not applicable | Remaining |
Below the totals, list any Residual-risk finding that the developer could upgrade to
Not applicable with live evidence, marked ⏳ EVIDENCE WOULD UPGRADE with a one-line note
of what would prove it. These are already-final verdicts — the marker is an optional
refinement invitation, not a sign the PR is incomplete.
Fixes made — per change: file, package/image/dep, CVEs, before/after version|tag|
digest|removal, build/scan result if any.
HIGH/CRITICAL release analysis — summary table | Package | Vulnerability | Verdict | Evidence | plus one full block per
unresolved/pending finding:
Every HIGH/CRITICAL appears directly in the PR body. LOW/MEDIUM may be summarized.
Verification — build/test/lint result; before/after totals; rescan commands for the
team to run after base-image import; any limitations (state explicitly that pod/rebuild
checks are handed off, not run here).
SWA Exception Justifications — see §9 (reuse the doc's prose verbatim).
Issue reference — Fixes #<issue-number> — replace <issue-number> with the actual number from the URL of this issue (e.g. Fixes #42).
docs/security/trivy-remediation.md (create or append, never overwrite)
On re-scan, add a new ## Scan: section at the top (most recent first); preserve all
prior history. Structure:
# Trivy Remediation Log## Scan: <scan-id> @ <short-sha> — C:<n> H:<n>-**Commit:**`<full-sha>`-**Service:**`<L3ID / service>`-**Scan ID:**`<scan-id>`-**Repository:**`<owner/repo>`-**Scan date:** <YYYY-MM-DD>
### Triage summary
<sametotalstableasPRbody>
### Full finding inventory| Target | Package | Vulnerability | Severity | Status | Installed | Fixed Version | Verdict | Evidence |
<one row per HIGH/CRITICAL; Evidence self-contained — no cross-references>
## HIGH/CRITICAL release analysis
<summarytable+onefullper-findingblock,identicaltoPRbody>
## Verification
<fixes, rescan/handoff commands, before/after totals>
## SWA Exception Justifications### <package> / <CVE-id>-**CVE:** <CVE-id>
-**Package:**<package@version>-**Severity:** <severity>
-**Status:** <fixed / affected (no fix available) / will-not-fix>
-**SSC Issue ID:** <numeric id if known — optional for container scans>
-**Verdict:** Residual risk – required, not reachable under current controls
**Summary:** <1-2 sentence plain-language summary, no file:line>
<self-contained prose justification — see §9>
9. SWA Exception Justifications — exact line format
Required whenever any finding is Residual risk or Not applicable. The parser finds the ## SWA Exception JustificationsH2, each ### <package> / <CVE>H3 under it, the
own-line **Verdict:** field, and the plain prose beneath. Any shape error = silent skip.
Element
✅ REQUIRED
❌ DROPPED
Section heading
## SWA Exception Justifications (H2)
### … (H3) → zero sections found
Per-CVE heading
### <package> / <CVE-id> (H3)
## … (closes section), #### …, **<package>:**
Verdict
- **Verdict:** <string> (bold inline field, own line)
Verdict text reads exactlyNot applicable / false positive or Residual risk – required, not reachable under current controls (en-dash) — no
trailing punctuation, no code-ticks, no heading.
Prose is ≥40 chars, self-contained: name the package, why it's unreachable, the
compensating control, and the evidence (command + output, or build-stage line ranges, or
carried-forward pod date). No REPLACE_WITH… placeholder.
In the doc: do NOT use <!-- SWA_EXCEPTION_START/END --> markers — the parser reads
them as part of the reason. (The PR body §10-style marker blocks are separate; the doc
must not use them.)
SSC Issue ID optional for Trivy today (container scans not yet in SSC) — include when
known.
PR-body SWA blurbs are byte-identical to the doc's (same CVE → same verdict → same
reasoning). Generate blurbs immediately from
carried-forward evidence if the doc cites prior pod output; if evidence is missing,
request it via the §11 loop and hold the verdict provisional. Never generate blurbs for Fixed / Already remediated.
Example (illustrative — do not copy values):
### gnutls / CVE-2026-33845-**CVE:**CVE-2026-33845
-**Package:**gnutls@3.8.10-4.el9_8
-**Severity:** HIGH
-**Status:** affected (no fix available)
-**Verdict:** Not applicable / false positive
**Summary:** nginx does not link libgnutls, so the DTLS parser is unreachable from this container.
CVE-2026-33845 targets the GnuTLS DTLS handshake fragment parser, reachable only by a
process that loads libgnutls for DTLS. nginx does not link libgnutls in this image,
confirmed by carried-forward pod check `ldd $(which nginx) | grep -i gnutls` (no output,
2026-06-02 via oc rsh, recorded in prior scan). Red Hat marks the component Not Affected
for nginx (access.redhat.com/security/cve/CVE-2026-33845). Container runs non-root UID 1001
under ARO SCC (id -u → 1001). Rebuild required when Red Hat ships a patched RHEL 9 gnutls.
If you also include marker-style blurbs in the PR body for human reviewers, one fenced
block per CVE, header line machine-parsed (do not reorder fields), prose for humans:
<!-- SWA_EXCEPTION_START -->
CVE: <CVE> | Package: <pkg> <ver> | Severity: <HIGH|CRITICAL> | Verdict: <exact §5 string>
<2–4 sentence prose: what the CVE targets, why the path is absent/unreachable here, the
proof (command + output or build-stage proof or carried-forward pod date), compensating
controls, and the follow-up condition requiring a rebuild.>
Verified: <method> on <YYYY-MM-DD>
<!-- SWA_EXCEPTION_END -->
These markers are PR-body-only — the doc's §9 section must not use them.
This loop runs on the already-open, already-complete PR. It exists only to upgrade a few Residual risk verdicts to Not applicable when the developer supplies live evidence
you couldn't produce. The PR never waits for it; every finding already has a final verdict
without it.
When to ask
Only when a Residual-risk verdict could legitimately become Not applicable if a Tier-2
check (§3) you cannot run confirms a precondition absent. Do not ask for anything you
already proved from the repo or carried forward. Every request maps to a named precondition.
If a finding's Residual-risk verdict is correct and final regardless of any check, don't ask
at all.
How to ask — ### Evidence requested
For each upgrade-candidate finding, post a comment (or a section in the PR body) under this
exact heading. List the specific commands and what each would prove — never generic
scripts:
### Evidence requested
For CVE-XXXX-YYYY (<package>) — to confirm <precondition> is absent:
```shell
# what this proves: <one line>
oc rsh -n <namespace> deployment/<deployment> -- <command>
```
Typical checks (adapt to the actual CVEs — do not paste all of them): rpm -q <pkg> (package absent), ldd $(which <bin>) | grep -i <lib> (linkage absent), nginx -T | grep <directive> (config precondition), id -u (non-root), and for a rescan
(external host, not the pod): trivy image --severity HIGH,CRITICAL <registry>/<image>:<tag>@<digest>.
How the developer replies — ### Pod verification output
The developer pastes raw terminal output under exactly this heading:
### Pod verification output
```shell
<raw output>
```
What you do when you see that heading
Cross-reference each output line against every Residual-risk claim you flagged as an
upgrade candidate — one check per precondition/control.
Upgrade or keep. If output proves the precondition absent → upgrade to Not applicable / false positive. If it confirms the package is required/reachable →
keep Residual risk – required, not reachable under current controls (already final)
and cite the verified output. Never upgrade on ambiguous or missing output — post a
follow-up ### Evidence requested naming the missing check instead.
Regenerate the artifacts for each upgraded finding: the §9 doc blurb (source of
truth) and the byte-identical PR-body blurb. Clear the ⏳ EVIDENCE WOULD UPGRADE marker.
Note the proof in the Verified line: Verified: pod checks via oc rsh on <YYYY-MM-DD>.
Carried-forward evidence (no new dev output needed)
If a verdict carries forward from docs/security/trivy-remediation.md and that doc cites
pod output as proof, do not wait for a new comment — generate the blurb immediately and
note Verified: carried from prior scan — pod checks via oc rsh on <prior-date>.
Developer corrections
The developer may also correct a verdict or redirect the analysis directly in a comment.
Treat that as authoritative input: re-examine the finding, update the verdict and all three
artifacts, and briefly note the basis for the change.
Pre-PR self-check (all boxes must tick)
PR body contains Fixes #<issue-number> (the exact number from this issue's URL) so
the issue closes automatically when the PR merges.
Each FP shows the §1 burden-of-proof checklist complete (verification step or
handoff command + output/proof, named control or CVE-db citation, unique evidence).
Each SWA finding section has a **Summary:** field with 1-2 plain-language sentences
(no file:line references, no commands). Verify, don't assume: run awk '/^## Scan:/{c++} c==1' docs/security/trivy-remediation.md | grep -c '^\*\*Summary:\*\*'
(scoped to the current/most-recent scan block, not older preserved scans) and confirm
the count is at least the number of SWA Exception Justification entries — if it's
short, add the missing one(s) now, before opening the PR.
All SWA verdict lines contain the en-dash (–) where required — confirm no editor
converted it to a hyphen.
docs/security/trivy-remediation.md exists with the full structure for this scan
(header, Triage, Full inventory, HIGH/CRITICAL analysis, Verification, SWA Exception
Justifications) — not just the inventory table.
Doc SWA blurbs are byte-identical to PR-body blurbs (same CVE → same verdict → same reasoning).
Prior scan history preserved (new ## Scan: added on top, nothing deleted).
Inventory Evidence column and all blurbs are cross-reference-free (every row
restates its own evidence).
No Tier-2 (pod/rebuild) output was fabricated — anything not runnable here is handed
off as commands and the verdict held at Residual risk unless carried forward.
No finding was parked waiting for the developer — every finding leaves the solo pass
with a final verdict (Fixed / Not applicable / Residual risk / Pending base image), and
the PR is releasable as-is.
Each upgrade-candidate finding has a matching ### Evidence requested block with
specific commands and is marked ⏳ EVIDENCE WOULD UPGRADE — as an optional refinement,
not a blocker.
Any ### Pod verification output already posted has been consumed: each line
cross-referenced, eligible Residual-risk verdicts upgraded to Not applicable, and all
three artifacts regenerated to match.
Final step — do this last:Fixes #<issue-number> is still present in the PR
body right now. Copilot sessions can rewrite the PR description and silently drop this
line; if it is missing, add it back under ### Issue reference before the PR is
created or updated.
@nchap8 @SridharBodapati — GitHub Copilot is assigned below to analyze these Trivy findings.
Trivy scan —
MMRIA Services@6f5e88206f5e8820c72667ac7049c9e022c6c443d7e95276MMRIA Services30966CDCgov/nccdphp-drh-mmriaFindings sent for remediation
Trivy Remediation Copilot Prompt
You are remediating Critical/High Trivy findings in this repository and producing a
security-reviewable PR in collaboration with the developer on this session. Read this
whole prompt before editing anything.
How this works: remediate now → open PR → optionally refine with the dev
This is auto-remediation: your job is to do the work now, not to wait for the developer.
You apply every fix you can and open a complete, releasable PR on your own. The developer
loop is an optional refinement that can upgrade a few verdicts later — it is never a
precondition for doing the work or opening the PR. Concretely:
from the repo and prior docs — apply fixes, build-stage proofs, CVE-database research,
carried-forward verdicts. Never defer a fix you are able to make. This is the bulk of
the work and it requires no developer input.
shippable verdict. Findings you fixed → Fixed. Findings you proved don't apply →
Not applicable. Findings you cannot prove false on your own → Residual risk –
required, not reachable under current controls, which is itself a complete, releasable
verdict that needs nothing further. The PR is ready for security review as it stands.
Not applicable if the developer supplies live (Tier-2) evidence you can't produce (§3).
Mark these
⏳ EVIDENCE WOULD UPGRADEin the triage table and post the exact commands(§11). This is an invitation, not a hold — the PR does not wait on it and the verdict is
already valid without it.
### Pod verification output(§11), cross-reference it, and where it proves a preconditionabsent, upgrade Residual risk → Not applicable, regenerating the affected artifacts.
If they never respond, the PR stays valid as-is. The developer may also correct a verdict
directly; treat that as authoritative.
Bottom line: do not park findings waiting for the developer. Every finding leaves your
solo pass with a final verdict. The only thing the loop changes is whether a small number of
Residual-risk items later become false positives — work is never gated on it.
The developer is an optional partner — primarily a runner of specific checks you request,
occasionally a reviewer who corrects a verdict. Keep requests minimal, exact, and tied to a
named precondition.
0. Output contract — the three machine-parsed artifacts
A batch job parses three things literally. If their shape is wrong, the finding is
silently dropped — no error is raised. Get these exactly right; everything else in
this prompt serves them.
## SWA Exception Justificationsdocs/security/trivy-remediation.mdand PR bodyFour hard rules that override everything below:
The parser matches the literal string. Markdown editors and autoformatters silently
convert
–to-; if that happens the finding is dropped. After writing, confirm theverdict lines still contain
–. The only two parsed verdicts are:Not applicable / false positiveResidual risk – required, not reachable under current controls← note the en-dashdocs/security/trivy-remediation.mdis the system of record, not the PR body. It isappended (never overwritten) every run and feeds the next scan's carry-forward.
the doc's SWA section. The PR body's SWA section reuses that same text verbatim.
## SWA Exception Justificationsentry must have a**Summary:**field —no exceptions, no "I'll add it later". It is parsed exactly like the other artifacts
above and silently dropped if missing. Before opening or updating the PR, run
awk '/^## Scan:/{c++} c==1' docs/security/trivy-remediation.md | grep -c '^\*\*Summary:\*\*'(scoped to the most recent
## Scan:block only — a plain whole-filegrep -ccan besatisfied by Summary fields from older, preserved scans) and confirm the count is at
least the number of
### <package> / <CVE>entries you wrote in this run. If it'sshort, go back and add the missing field(s) — do not open the PR and fix it after.
1. Default stance & burden of proof
Every finding is a true positive unless you prove otherwise. The burden is always on
the FP / not-applicable verdict. When in doubt, fix it.
Before writing any FP or not-applicable verdict, the PR must show, for that specific
finding:
is absent — OR, if you cannot run it (see §3), the exact command handed off for a human
to run.
(Red Hat / NVD / MITRE / OSV) that breaks the exploit path. Generic claims
("not exploitable", "package unused", "vendor wont-fix") are not evidence.
Self-containment rule (applies to every table cell, blurb, and
reason): these phrasesare forbidden —
same as above,same evidence,see previous,ditto,per row above,per finding above. Two CVEs sharing a package or control still restatefull evidence each. Reviewers read entries out of order.
2. Orient before editing
Read these if they exist and apply their guidance (later entries override earlier):
.github/copilot-instructions.md,AGENTS.md,CLAUDE.md,*INSTRUCTIONS.md,AI_CONTEXT.md/AI_*.md,CONTEXT.md,.cursor/rules/,.cursorrules,.aider*.Dockerfile*,Containerfile, CI workflows, Helm/Kustomize/K8s/OpenShift manifests, dependency manifests + lockfiles.
README,CONTRIBUTING,ARCHITECTURE,docs/overviews.Repo-specific guidance overrides this prompt on style, tests, and commit format.
BMAD / product context (BMAD): look for
bmad-agent/,.bmad/,BMAD.md, or independentlydocs/prd.mdanddocs/architecture.md. If found, read before analyzing findings and use them to:calibrate exploit severity by data sensitivity (PHI/PII/creds raise risk); validate or
refute platform FP arguments (network isolation, runtime controls); scope residual-risk
verdicts to active vs. dead code paths; and enrich SWA blurbs with the app's stated
purpose.
Prior remediation: read
docs/security/trivy-remediation.mdif present. Use itsrecorded verdicts and exploit research as a starting point — re-verify each against the
current findings JSON. Carry a verdict forward only when the same CVE + package +
target reappears with unchanged installed version and the prior evidence still holds; note
Carried from prior scan — evidence unchanged. If absent, start from scratch.3. Your environment & what counts as evidence
You have: the repo (code, Dockerfiles, manifests, lockfiles), context/BMAD files, and prior
trivy-remediation.md. You do not have image rebuild or pod (oc rsh) access.Evidence therefore falls in two tiers:
Tier 1 — you can produce it now (repo-static):
stage not copied to the final stage).
trivy-remediation.md(cite the priordate).
Tier 2 — you must hand off (live checks you cannot run):
oc rshpackage/binary/linkage checks,id -u, image inspection, Trivy rescan.section / a comment for a human to run, and keep the verdict at Residual risk until
the output exists (or carry forward documented prior output).
Never invent pod output, rebuild results, or environment controls. A verdict that
requires Tier-2 proof you don't have stays Residual risk – required, not reachable
under current controls with the verification commands attached — it does not become
a false positive on speculation.
4. Findings JSON
Attached as an issue comment under
### Machine-readable findings (findings.json);Critical/High only. Fields:
id,severity,package,version,fixedIn(may beempty — empty ≠ false positive),
status(affected/will_not_fix/fix_deferred/under_investigation/end_of_life),description,primaryURL,target.Atomic key:
target | package | id. Same CVE on a different package/target is aseparate finding. If split across parts ("part 1 of N"), read all parts first. If the
comment is missing or malformed, comment asking for valid JSON before proceeding.
All statuses still require action — none is an automatic FP. For
end_of_life, prioritizeupgrading to a supported base image/dependency.
5. Verdicts
Every finding ends in exactly one:
CVE-database research (required before any residual-risk/not-applicable exploit-precondition
prose). Query the allowlist and cite specifics — paraphrase findings, don't quote vendor
text at length:
access.redhat.com/security/cve/<CVE>(component scope, "Not Affected" statements for UBI/RHEL)nvd.nist.gov/vuln/detail/<CVE>(CVSS vector AV/AC/PR/UI, CWE)cve.mitre.org/cgi-bin/cvename.cgi?name=<CVE>osv.dev/vulnerability/<CVE>Write specific preconditions (e.g. "NVD shows AV:N/AC:H; Red Hat states the vulnerable
path needs module X not present in this image"), never generic ones.
Constraints: "package unused" is not an FP while it's still installed — try removal
first, else document residual risk. "Requires shell/elevated/not-internet-facing" supports
residual risk only with proven control. Don't invent cluster-level controls you can't
see — name them and hand off verification.
6. Remediation order (smallest safe change that affects the scanned artifact)
FROM+ pinned digest).Do not suppress instead of fixing: no disabling Trivy, lowering thresholds, expanding
.trivyignore, adding VEX/Rego/ignore policy as a substitute,--ignore-unfixed/--ignore-status/ new exclude paths, retargeting the scan, removing lockfiles, pinningvulnerable versions, switching to
latest, or unrelated refactors. Compensating controlsjustify residual risk; they never make an installed package "Fixed".
7. Acceptable vs unacceptable not-applicable evidence
Acceptable: target/path no longer produced here; package absent from final image
(proven via build-stage analysis or carried-forward pod output); finding applies only to an
intermediate stage not copied forward; same-scope rescan no longer reports it (handoff if
you can't rescan).
Unacceptable: low severity; vendor
will_not_fix; no known exploit; "probably unused";"dev dependency / not reachable / requires elevated perms" without evidence.
8. Required PR body & document structure
PR body must contain
| Severity | Original | Fixed | Pending image update | Residual | Not applicable | Remaining |Below the totals, list any Residual-risk finding that the developer could upgrade to
Not applicable with live evidence, marked
⏳ EVIDENCE WOULD UPGRADEwith a one-line noteof what would prove it. These are already-final verdicts — the marker is an optional
refinement invitation, not a sign the PR is incomplete.
digest|removal, build/scan result if any.
| Package | Vulnerability | Verdict | Evidence |plus one full block perunresolved/pending finding:
team to run after base-image import; any limitations (state explicitly that pod/rebuild
checks are handed off, not run here).
Fixes #<issue-number>— replace<issue-number>with the actual number from the URL of this issue (e.g.Fixes #42).docs/security/trivy-remediation.md(create or append, never overwrite)On re-scan, add a new
## Scan:section at the top (most recent first); preserve allprior history. Structure:
9. SWA Exception Justifications — exact line format
Required whenever any finding is Residual risk or Not applicable. The parser finds the
## SWA Exception JustificationsH2, each### <package> / <CVE>H3 under it, theown-line
**Verdict:**field, and the plain prose beneath. Any shape error = silent skip.## SWA Exception Justifications(H2)### …(H3) → zero sections found### <package> / <CVE-id>(H3)## …(closes section),#### …,**<package>:**- **Verdict:** <string>(bold inline field, own line)### Verdict: …(a heading here is the #1 bug)**Summary:** <1-2 sentences>(bold field, no leading-)### Summary← heading form is dropped;-prefix works but is discouraged**Justification:** …,### Verdict rationale(stripped as metadata → prose lost)Rules:
Not applicable / false positiveorResidual risk – required, not reachable under current controls(en-dash) — notrailing punctuation, no code-ticks, no heading.
compensating control, and the evidence (command + output, or build-stage line ranges, or
carried-forward pod date). No
REPLACE_WITH…placeholder.<!-- SWA_EXCEPTION_START/END -->markers — the parser readsthem as part of the reason. (The PR body §10-style marker blocks are separate; the doc
must not use them.)
known.
reasoning). Generate blurbs immediately from
carried-forward evidence if the doc cites prior pod output; if evidence is missing,
request it via the §11 loop and hold the verdict provisional. Never generate blurbs for
Fixed / Already remediated.
Example (illustrative — do not copy values):
10. PR-body SWA marker blurbs (optional, human-facing)
If you also include marker-style blurbs in the PR body for human reviewers, one fenced
block per CVE, header line machine-parsed (do not reorder fields), prose for humans:
These markers are PR-body-only — the doc's §9 section must not use them.
11. Optional refinement loop — upgrading Residual risk with developer evidence
This loop runs on the already-open, already-complete PR. It exists only to upgrade a few
Residual risk verdicts to Not applicable when the developer supplies live evidence
you couldn't produce. The PR never waits for it; every finding already has a final verdict
without it.
When to ask
Only when a Residual-risk verdict could legitimately become Not applicable if a Tier-2
check (§3) you cannot run confirms a precondition absent. Do not ask for anything you
already proved from the repo or carried forward. Every request maps to a named precondition.
If a finding's Residual-risk verdict is correct and final regardless of any check, don't ask
at all.
How to ask —
### Evidence requestedFor each upgrade-candidate finding, post a comment (or a section in the PR body) under this
exact heading. List the specific commands and what each would prove — never generic
scripts:
Typical checks (adapt to the actual CVEs — do not paste all of them):
rpm -q <pkg>(package absent),ldd $(which <bin>) | grep -i <lib>(linkage absent),nginx -T | grep <directive>(config precondition),id -u(non-root), and for a rescan(external host, not the pod):
trivy image --severity HIGH,CRITICAL <registry>/<image>:<tag>@<digest>.How the developer replies —
### Pod verification outputThe developer pastes raw terminal output under exactly this heading:
What you do when you see that heading
upgrade candidate — one check per precondition/control.
Not applicable / false positive. If it confirms the package is required/reachable →
keep Residual risk – required, not reachable under current controls (already final)
and cite the verified output. Never upgrade on ambiguous or missing output — post a
follow-up
### Evidence requestednaming the missing check instead.truth) and the byte-identical PR-body blurb. Clear the
⏳ EVIDENCE WOULD UPGRADEmarker.Verified: pod checks via oc rsh on <YYYY-MM-DD>.Carried-forward evidence (no new dev output needed)
If a verdict carries forward from
docs/security/trivy-remediation.mdand that doc citespod output as proof, do not wait for a new comment — generate the blurb immediately and
note
Verified: carried from prior scan — pod checks via oc rsh on <prior-date>.Developer corrections
The developer may also correct a verdict or redirect the analysis directly in a comment.
Treat that as authoritative input: re-examine the finding, update the verdict and all three
artifacts, and briefly note the basis for the change.
Pre-PR self-check (all boxes must tick)
Fixes #<issue-number>(the exact number from this issue's URL) sothe issue closes automatically when the PR merges.
handoff command + output/proof, named control or CVE-db citation, unique evidence).
**Summary:**field with 1-2 plain-language sentences(no file:line references, no commands). Verify, don't assume: run
awk '/^## Scan:/{c++} c==1' docs/security/trivy-remediation.md | grep -c '^\*\*Summary:\*\*'(scoped to the current/most-recent scan block, not older preserved scans) and confirm
the count is at least the number of SWA Exception Justification entries — if it's
short, add the missing one(s) now, before opening the PR.
converted it to a hyphen.
docs/security/trivy-remediation.mdexists with the full structure for this scan(header, Triage, Full inventory, HIGH/CRITICAL analysis, Verification, SWA Exception
Justifications) — not just the inventory table.
## Scan:added on top, nothing deleted).Evidencecolumn and all blurbs are cross-reference-free (every rowrestates its own evidence).
off as commands and the verdict held at Residual risk unless carried forward.
with a final verdict (Fixed / Not applicable / Residual risk / Pending base image), and
the PR is releasable as-is.
### Evidence requestedblock withspecific commands and is marked
⏳ EVIDENCE WOULD UPGRADE— as an optional refinement,not a blocker.
### Pod verification outputalready posted has been consumed: each linecross-referenced, eligible Residual-risk verdicts upgraded to Not applicable, and all
three artifacts regenerated to match.
Fixes #<issue-number>is still present in the PRbody right now. Copilot sessions can rewrite the PR description and silently drop this
line; if it is missing, add it back under
### Issue referencebefore the PR iscreated or updated.
Fixes #523