Skip to content

feat(UP-0): diff-vs-main PR comment (introduced/resolved + total, vs base branch) - #40

Open
amitaboudi wants to merge 14 commits into
mainfrom
feat/diff-vs-main-comment
Open

feat(UP-0): diff-vs-main PR comment (introduced/resolved + total, vs base branch)#40
amitaboudi wants to merge 14 commits into
mainfrom
feat/diff-vs-main-comment

Conversation

@amitaboudi

Copy link
Copy Markdown
Contributor

Produces the diff-focused PR comment:

N newly introduced vulnerabilities · R resolved · T total in this PR vs main
🔴 c Critical | 🔶 h High | 🟡 m Medium | 🟢 l Low

▶ 🔶 High · k findings (table: CVE → NVD link | Package | Version | Fix)
▶ ✅ Resolved · j findings (table: CVE | Package | Version)

What it does

  • Adds main_branch (+ optional pr_id/pr_link) inputs and passes --main-branch so the backend diffs the image against the base branch's latest scanned image.
  • Rewrites the comment to the diff view: counts for introduced/resolved/total, detail tables only for introduced (by severity) + resolved; already-present CVEs are counted in the total but not listed. CVE ids link to NVD.
  • Skips the comment when scan output is empty (backend not ready) instead of posting unknown:unknown.
  • Body sent via file (no OS arg-length limit); hard cap keeps it under GitHub's 65536-char limit.

Supersedes

This replaces/combines the earlier #37 (full-image renderer) and #38 (main_branch wiring) — both can be closed in favor of this single PR.

Depends on

upwindsecurity/shiftleft#243 (adds --main-branch and forwards RepositoryScanDetails for image scans). Merge + release a new stable binary before consumers set main_branch. Flags are passed only when the inputs are set, so this PR is safe to merge ahead of the release (no-op until used). Base branch must be scanned (e.g. on: push: [main]) so a baseline exists.

🤖 Generated with Claude Code

amitaboudi and others added 14 commits June 7, 2026 17:52
The PR comment was built only from `introducedCves` (CVEs newly introduced
vs the previously-scanned image). On a re-scan where no NEW CVEs appear, the
comment collapsed to "all clear ✅" even though the image still contained
hundreds of CVEs — making a vulnerable PR look clean.

The scan JSON already carries the full picture (`introducedCves`,
`noChangeCves`, `resolvedCves`). Build the comment from the whole image
(`introducedCves + noChangeCves`) and report absolute totals:

  Total CVEs in image: N (X new since last scan · Y already present · Z resolved)

"all clear ✅" now means the image truly has 0 CVEs. Severity tables are
capped at MAX_ROWS (80) per table with a "see Upwind Console" note so
vulnerability-heavy images stay under GitHub's 65536-char comment limit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Multi-arch, CVE-heavy images (e.g. ubuntu:22.04 → 7 platforms) made the
comment large enough that `jq -n --arg body "$COMMENT"` exceeded the OS
single-argument limit ("Argument list too long", exit 126), and could also
blow past GitHub's 65536-char comment limit.

- Send the body via a file (`jq -Rs` + `curl --data @file`), never as a
  shell argument.
- Add a COMMENT_BUDGET so detail tables stop once near the limit while every
  per-arch summary (the whole-image totals) is always kept; note truncation
  once. Lower MAX_ROWS to 60 and add a final hard 65000-char safety net.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build each severity table into a local buffer and append only if it fits
COMMENT_BUDGET (raised 44000->60000 now that the check is exact), so more
CVEs are shown while staying under GitHub's 65536-char comment limit. The
final hard cap now truncates at a newline boundary and closes any unclosed
<details> tags so the comment always renders valid markdown. Clean up the
payload temp file.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add optional `main_branch` (+ `pr_id`/`pr_link`) inputs. When `main_branch`
is set, pass `--main-branch` (etc.) to the shiftleft binary so introduced/
resolved CVEs are computed against the latest scanned image of the base
branch instead of the previous commit's image.

Flags are appended only when the inputs are non-empty (via EXTRA_ARGS), so
the action stays compatible with shiftleft binaries that predate the flags —
default behaviour is unchanged.

Depends on upwindsecurity/shiftleft#243 being merged and a new binary
released before `main_branch` is actually used. Also requires the base
branch to have been scanned (e.g. an on:push:[main] workflow) so a baseline
exists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…al count)

Combines the main_branch wiring with a diff-focused comment: 'N newly
introduced · R resolved · T total in this PR vs <base>', a severity breakdown
of the total, and collapsible tables listing ONLY introduced (by severity,
CVE/Package/Version/Fix) and resolved (CVE/Package/Version). Already-present
CVEs are counted in the total but not listed. CVE ids link to NVD.

Skips commenting when scan output is empty (backend not ready) instead of
posting an unknown:unknown placeholder. Body is sent via a file to avoid OS
arg-length limits; final hard cap keeps it under GitHub's 65536-char limit.
The SCA /code panel keyed by fingerprint is for the code scan; an image scan
must link to the vulnerabilities Shift-left panel keyed by imageVersion.
…gerprint

Confirmed against a real console URL: the scan-details deep link is
/code?...secondaryTab=SCA&sidePanel=scan-at-build&sidePanelItemId=<fingerprint>
(the 64-hex SBOM fingerprint), not imageVersion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant