Container image scanning
Container image scanning answers the what’s vulnerable in this image question — complementing the SBOM’s what’s in this image. fremforge ingests scan results produced by Trivy (the standard runner-image tool) and surfaces them next to the image + commit they describe.
How it works
The fremforge runner image ships Trivy. Your workflow runs the scan and POSTs the findings:
- name: Scan + push findings
run: |
trivy image --format json --output trivy.json my-registry/my-image:${{ github.sha }}
curl -sS --fail \
-H "Authorization: Bearer ${{ secrets.FREMFORGE_FINDINGS_TOKEN }}" \
-H 'Content-Type: application/json' \
-d @<(jq -c '{
image_ref: "my-registry/my-image:'"${GITHUB_SHA}"'",
commit_sha: "'"${GITHUB_SHA}"'",
repo_full_name: "'"${GITHUB_REPOSITORY}"'",
findings: [.Results[].Vulnerabilities[] | {
cve_id: .VulnerabilityID,
severity: (.Severity|ascii_downcase),
package_name: .PkgName,
installed_version: .InstalledVersion,
fixed_version: .FixedVersion,
title: .Title,
target: .PkgPath
}]
}' trivy.json) \
"https://frem.sh/_app/api/v1/orgs/${ORG}/image-scans/findings"The PAT needs the findings:write scope.
Policy toggles
Admin → Code security → Image scanning carries three settings:
- Enabled — when off, ingest returns
202 {accepted: 0, status: 'disabled'}(still parsed, just dropped). Useful for pre-launch teams that want the scan to run but not gate. - Block action —
none|warn|block_pull:none— store findings, post no commit status. Build-side detection only.warn— store findings, post commit statussuccesswith description noting the count. PR merge unblocked.block_pull— store findings, post commit statusfailurewhen ≥1 high or critical finding exists. Branch protection with requiredfremforge/image-scanstatus check then blocks merge.
- Require signed images — when on, the ingest also accepts a
signature_statusfield (signed/unsigned/unknown). Unsigned images (or signed images from an issuer not on the allowlist) get a synthetic critical finding so the same block-pull path enforces the signing policy. See Cosign for the signing side.
Where findings surface
Admin → Code security → Image scanning lists scans by image-ref + commit + PR. Each row shows:
- Severity counts (critical / high / medium / low)
- Fixable counts (findings with a non-null
fixed_version) - Status (
success/failure/skipped) + the commit status posted - Links to the upstream advisories (CVE, GHSA when present)
What a finding looks like in the DB
Stored fields per finding: cve_id, severity, package, installed_version, fixed_version, target (the in-image file path), and the scan_run_id that ties findings produced by the same run. The full Trivy output is NOT stored — just the per-finding rows, which is the queryable shape.
Retention
Findings follow the per-tenant audit retention policy. Aged-out findings keep their hash in the chain (tamper-evidence) but lose the per-row payload.
See also
- Cosign — image signing + signed-images policy.
- SBOMs — package inventory in the image (independent of vulnerability state).
- OSV recommendations — the source-side complement (vulnerabilities in your dependencies before they ship).
- API reference —
POST /api/v1/orgs/{slug}/image-scans/findingsingest endpoint.