fix(security): explain scan findings and handle image locations #22

Merged
gitchegumi merged 4 commits from kiyi/image-config-occurrences into main 2026-09-06 08:33:03 -05:00
Member

Actual run 32 fails because Trivy image Dockerfile absence checks can omit source lines. Its decision artifact also strips the explanation needed to distinguish CVEs from configuration checks and assess remediation.

This PR fixes image finding normalization and publishes actionable scan artifacts:

  • Retain whole-target image Dockerfile absence findings while keeping source-manifest location validation strict. No findings are waived.
  • Add advisory titles/descriptions, package paths, installed/fixed versions, vendor status, severity source, remediation guidance and reference URLs to normalized CVE/configuration findings. Descriptive fields are outside fingerprint identity.
  • Generate summary.md and findings.csv alongside enriched decision.json (report_version 1), with categories, occurrence versus distinct-CVE counts, scanner errors, dispositions, policy reasons and accepted mitigation controls/expiry.
  • Upload these reports on success/rejection across source scans, bundle build/deploy, container build and PV provisioning. Raw scanner directories/snippets are not uploaded; secret details are replaced with generic remediation, Markdown evidence is escaped and CSV formula prefixes neutralized.
  • Document interpretation and compatibility. Refresh one existing Semgrep fingerprint for a one-line source shift without changing its mitigation controls or expiry.

Validation: 16 security, six reporting, 12 delivery and nine Forgejo contract tests pass locally. Tests cover exact fingerprint/mitigation stability, real Trivy image findings, missing/malformed locations, each disposition, scanner-error-only artifacts, secret/snippet omission, output escaping and all five upload workflows. A full Actual-image preview produces 252 explained findings with the same 79 policy blockers, including UNKNOWN severities. Hosted checks must pass.

The image findings still require applicability assessment; this PR does not certify the image safe. No budget data accessed or deployment performed. Intended patch release: v1.3.3.

Actual run 32 fails because Trivy image Dockerfile absence checks can omit source lines. Its decision artifact also strips the explanation needed to distinguish CVEs from configuration checks and assess remediation. This PR fixes image finding normalization and publishes actionable scan artifacts: - Retain whole-target image Dockerfile absence findings while keeping source-manifest location validation strict. No findings are waived. - Add advisory titles/descriptions, package paths, installed/fixed versions, vendor status, severity source, remediation guidance and reference URLs to normalized CVE/configuration findings. Descriptive fields are outside fingerprint identity. - Generate summary.md and findings.csv alongside enriched decision.json (report_version 1), with categories, occurrence versus distinct-CVE counts, scanner errors, dispositions, policy reasons and accepted mitigation controls/expiry. - Upload these reports on success/rejection across source scans, bundle build/deploy, container build and PV provisioning. Raw scanner directories/snippets are not uploaded; secret details are replaced with generic remediation, Markdown evidence is escaped and CSV formula prefixes neutralized. - Document interpretation and compatibility. Refresh one existing Semgrep fingerprint for a one-line source shift without changing its mitigation controls or expiry. Validation: 16 security, six reporting, 12 delivery and nine Forgejo contract tests pass locally. Tests cover exact fingerprint/mitigation stability, real Trivy image findings, missing/malformed locations, each disposition, scanner-error-only artifacts, secret/snippet omission, output escaping and all five upload workflows. A full Actual-image preview produces 252 explained findings with the same 79 policy blockers, including UNKNOWN severities. Hosted checks must pass. The image findings still require applicability assessment; this PR does not certify the image safe. No budget data accessed or deployment performed. Intended patch release: v1.3.3.
fix(security): retain image findings without source lines
All checks were successful
Workflow acceptance / acceptance (pull_request) Successful in 54s
Repository security / security-1 (pull_request) Successful in 1m19s
Repository security / security (pull_request) Successful in 0s
Library checks / tests (pull_request) Successful in 1m51s
a6f9d6d311
Author
Member

Additional reproduction: a full local Trivy 0.74.0 scan (vuln,misconfig,secret plus image-config misconfig/secret) of the same pinned Actual amd64 image normalizes successfully with this fix: 252 findings total, including 59 HIGH and 4 CRITICAL vulnerability occurrences and 10 HIGH Dockerfile findings; zero secret findings. Counts use the locally refreshed DB and are not a replacement for the hosted gate or exploitability assessment. No mitigation was added. This confirms the parser failure concealed subsequent image findings that require separate review before release/deployment.

Additional reproduction: a full local Trivy 0.74.0 scan (vuln,misconfig,secret plus image-config misconfig/secret) of the same pinned Actual amd64 image normalizes successfully with this fix: 252 findings total, including 59 HIGH and 4 CRITICAL vulnerability occurrences and 10 HIGH Dockerfile findings; zero secret findings. Counts use the locally refreshed DB and are not a replacement for the hosted gate or exploitability assessment. No mitigation was added. This confirms the parser failure concealed subsequent image findings that require separate review before release/deployment.
fix(security): publish actionable scan reports and advisory details
Some checks failed
Workflow acceptance / acceptance (pull_request) Successful in 49s
Repository security / security-1 (pull_request) Successful in 1m25s
Repository security / security (pull_request) Successful in 0s
Library checks / tests (pull_request) Has been cancelled
9ba76eca32
kiyi changed title from fix(security): retain image findings without source lines to fix(security): explain scan findings and handle image locations 2026-09-06 01:39:40 -05:00
fix(reports): show blocking findings before informational results
All checks were successful
Workflow acceptance / acceptance (pull_request) Successful in 48s
Repository security / security-1 (pull_request) Successful in 1m18s
Repository security / security (pull_request) Successful in 0s
Library checks / tests (pull_request) Successful in 1m52s
d3752abafb
Author
Member

Expanded this PR to address the owner’s request for useful future scan artifacts. summary.md and findings.csv now accompany enriched decision.json, with blockers first, descriptions, affected/fixed package versions, advisory links, scanner errors and exact mitigation controls. All five scan upload workflows include these files without adding raw scanner directories.

Local validation: 16 security + 6 reporting + 12 delivery + 9 Forgejo contract tests pass. The full reproduced Actual scan renders 252 findings with the same 79 blockers; no exceptions added. Description/fix metadata changes preserve fingerprints. Secret-match omission, Markdown escaping, CSV formula neutralization, error-only reports, and upload wiring are covered. The one shifted Semgrep fingerprint retains its original control/expiry. Hosted checks are rerunning on the final report-ordering revision.

Expanded this PR to address the owner’s request for useful future scan artifacts. summary.md and findings.csv now accompany enriched decision.json, with blockers first, descriptions, affected/fixed package versions, advisory links, scanner errors and exact mitigation controls. All five scan upload workflows include these files without adding raw scanner directories. Local validation: 16 security + 6 reporting + 12 delivery + 9 Forgejo contract tests pass. The full reproduced Actual scan renders 252 findings with the same 79 blockers; no exceptions added. Description/fix metadata changes preserve fingerprints. Secret-match omission, Markdown escaping, CSV formula neutralization, error-only reports, and upload wiring are covered. The one shifted Semgrep fingerprint retains its original control/expiry. Hosted checks are rerunning on the final report-ordering revision.
portegumi requested changes 2026-09-06 01:57:17 -05:00
Dismissed
portegumi left a comment

Two blockers remain in the new report path.

  1. pipeline/security.py:334 — the production integration is not regression-tested. Replacing write_reports(output, decision) with the previous decision-only JSON write leaves all 61 unit tests and all 16 scaffold cases green. The reporting tests invoke write_reports() directly, and the upload contract test only checks YAML paths, so neither proves that scan() actually creates summary.md and findings.csv. The exact-head hosted security artifact does not close this gap: artifact 80 contains only decision.json, with no report_version or summary, because the repository self-scan still runs the older pinned reusable release. Add a scan-level regression using controlled/mocked scanner execution that calls the production scan() path and requires all three reports, including the scanner-error/rejection path.

  2. pipeline/reporting.py:161 — every finding heading contains literal mojibake: — rather than an em dash. A generated report currently renders ## 1. rule — HIGH — blocking, and no test notices it. Replace the double-encoded characters and assert the generated UTF-8 heading so this user-facing artifact remains readable.

Other adversarial checks passed: the image-Dockerfile missing-line fallback remains narrowly gated and preserves 15 unique fixture fingerprints; mutations removing that fallback, secret-detail scrubbing, CSV formula neutralization, or an upload path are killed by focused tests. The full 61-test suite, 16 scaffold cases, Kubernetes negative fixtures, compilation, and diff checks pass. All four hosted contexts are green. Exact-head artifact 80 reports the existing gate passed with zero blockers, five exact mitigations, and zero scanner errors, but—as noted above—it was produced by the older reporter and cannot validate this PR's new artifacts. Live, fetched, local, and payload SHAs matched before submission.

Two blockers remain in the new report path. 1. `pipeline/security.py:334` — the production integration is not regression-tested. Replacing `write_reports(output, decision)` with the previous decision-only JSON write leaves all 61 unit tests and all 16 scaffold cases green. The reporting tests invoke `write_reports()` directly, and the upload contract test only checks YAML paths, so neither proves that `scan()` actually creates `summary.md` and `findings.csv`. The exact-head hosted security artifact does not close this gap: artifact 80 contains only `decision.json`, with no `report_version` or summary, because the repository self-scan still runs the older pinned reusable release. Add a scan-level regression using controlled/mocked scanner execution that calls the production `scan()` path and requires all three reports, including the scanner-error/rejection path. 2. `pipeline/reporting.py:161` — every finding heading contains literal mojibake: `—` rather than an em dash. A generated report currently renders `## 1. rule — HIGH — blocking`, and no test notices it. Replace the double-encoded characters and assert the generated UTF-8 heading so this user-facing artifact remains readable. Other adversarial checks passed: the image-Dockerfile missing-line fallback remains narrowly gated and preserves 15 unique fixture fingerprints; mutations removing that fallback, secret-detail scrubbing, CSV formula neutralization, or an upload path are killed by focused tests. The full 61-test suite, 16 scaffold cases, Kubernetes negative fixtures, compilation, and diff checks pass. All four hosted contexts are green. Exact-head artifact 80 reports the existing gate passed with zero blockers, five exact mitigations, and zero scanner errors, but—as noted above—it was produced by the older reporter and cannot validate this PR's new artifacts. Live, fetched, local, and payload SHAs matched before submission.
fix(reports): verify scan artifacts and correct UTF-8 headings
All checks were successful
Workflow acceptance / acceptance (pull_request) Successful in 47s
Repository security / security-1 (pull_request) Successful in 1m18s
Repository security / security (pull_request) Successful in 0s
Library checks / tests (pull_request) Successful in 1m48s
9f84529283
Exercise the production scan path with controlled scanner execution for passing scans, policy rejection and scanner failure. Require enriched JSON, Markdown and CSV artifacts in every case.

Render proper em dashes and assert decoded UTF-8 headings. Regression mutations confirm both review findings are caught.
Author
Member

Addressed both blockers in 9f84529283.

  • Added a production scan() regression with mocked external scanner execution. Passing scans, HIGH-finding rejection, and scanner exit failure must each write enriched decision.json, summary.md and findings.csv. The scanner-error case asserts a failed gate despite an empty blocking list. Normalization, evaluation and reporting remain real.
  • Replaced the double-encoded heading separators with Unicode em dashes and asserted the decoded UTF-8 headings.

Validation: all 62 unit tests pass; Linux scaffold validation passes all 16 cases; git diff --check passes. A decision-only writer mutation fails all three scan scenarios, and reintroducing the garbled separators fails the heading assertion. Hosted checks are running. The pinned repository self-scan still uses the older release, so its artifact is not evidence of the new reporter; the scan integration regression now validates that wiring directly.

Addressed both blockers in 9f84529283150a668edea3bcddeb316439ded1b8. - Added a production scan() regression with mocked external scanner execution. Passing scans, HIGH-finding rejection, and scanner exit failure must each write enriched decision.json, summary.md and findings.csv. The scanner-error case asserts a failed gate despite an empty blocking list. Normalization, evaluation and reporting remain real. - Replaced the double-encoded heading separators with Unicode em dashes and asserted the decoded UTF-8 headings. Validation: all 62 unit tests pass; Linux scaffold validation passes all 16 cases; git diff --check passes. A decision-only writer mutation fails all three scan scenarios, and reintroducing the garbled separators fails the heading assertion. Hosted checks are running. The pinned repository self-scan still uses the older release, so its artifact is not evidence of the new reporter; the scan integration regression now validates that wiring directly.
kiyi requested review from portegumi 2026-09-06 02:10:56 -05:00
portegumi approved these changes 2026-09-06 08:22:42 -05:00
portegumi left a comment

The two blockers from review #440 are resolved at this head.

  • The production scan() path now has integration coverage for passing scans, policy-blocking findings, and scanner failures. Every case requires enriched decision.json, summary.md, and findings.csv; deleting the production write_reports() call causes the focused suite to fail.
  • Report headings now render proper UTF-8 em dashes, with an exact generated-text assertion. Reintroducing the mojibake causes the focused suite to fail.

Verification: 62 unit tests passed; 16 scaffold scenarios passed; Kubernetes negative fixtures, Python compilation, and diff checks passed; all four hosted contexts are green; worktree is clean. Exact-head security artifact 82 reports passed: true, zero blockers, and zero scanner errors. It still contains only the older pinned reporter's decision.json, so approval relies on the new production-path regression rather than misrepresenting that artifact as evidence of the new files. Live, fetched, local, and payload SHAs matched before submission.

The two blockers from review #440 are resolved at this head. - The production `scan()` path now has integration coverage for passing scans, policy-blocking findings, and scanner failures. Every case requires enriched `decision.json`, `summary.md`, and `findings.csv`; deleting the production `write_reports()` call causes the focused suite to fail. - Report headings now render proper UTF-8 em dashes, with an exact generated-text assertion. Reintroducing the mojibake causes the focused suite to fail. Verification: 62 unit tests passed; 16 scaffold scenarios passed; Kubernetes negative fixtures, Python compilation, and diff checks passed; all four hosted contexts are green; worktree is clean. Exact-head security artifact 82 reports `passed: true`, zero blockers, and zero scanner errors. It still contains only the older pinned reporter's `decision.json`, so approval relies on the new production-path regression rather than misrepresenting that artifact as evidence of the new files. Live, fetched, local, and payload SHAs matched before submission.
gitchegumi deleted branch kiyi/image-config-occurrences 2026-09-06 08:33:03 -05:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Homelab/workflows!22
No description provided.