Skip to content

feat(security): continuously ingest Kubescape findings — SARIF→Code Scanning gate + CRD→issue bridge #2451

Open
12 of 14 issues completed

Description

@devantler

🤖 Generated by the Daily AI Assistant

Part of #2447.

Problem

Even once the scanners are fixed, live Kubescape findings (posture regressions, new reachable CVEs, runtime detections) never enter the work backlog — the daily engineer's survey is GitHub-only, so findings only get worked if a human files them. This is the structural reason the whole stack rotted unnoticed. We need continuous, idempotent ingestion so findings become tracked issues the engineer drains oldest-first, and a pre-merge gate so regressions never land.

Proposed direction (full loop — settled with the maintainer)

Two complementary paths (repo is public, so GitHub Code Scanning is available and already in use — CodeQL, zizmor):

  1. Prevention gate (repo-scannable posture): add a Kubescape SARIF scan step that uploads to GitHub Code Scanning on PRs (native dedup via partialFingerprints, auto-close-when-gone, Security tab). This complements the existing ksail workload scan compliance-threshold gate. Model the workflow on .github/workflows/todos.yaml (App-token + a reusable workflow targeting devantler-tech/actions, never reusable-workflows).
  2. Backlog bridge (live-only findings): a scheduled job that reads the live Kubescape CRDs a static repo scan can't produce — vulnerabilitymanifestsummaries, runtime node_agent_alert_counter state, and any residual configurationscansummaries regressions — and opens/updates/closes fingerprint-deduped, themed security issues under roadmap: Kubescape security stack → 100% and hold (posture · CVE · runtime) #2447 (one issue per control/theme, not per resource; search-before-create; close-when-gone). This is what makes findings drainable oldest-first.

Anti-spam is the hard part: get idempotency + fingerprinting right or it floods. Start the bridge in report-only/dry-run, then enable issue writes.

Rough size

L — decompose into: (a) SARIF→Code-Scanning PR gate; (b) the CRD→issue bridge (dedup/fingerprint/close-when-gone); (c) Kyverno-Enforce graduation of controls driven to zero.

Acceptance criteria

Activity

  1. devantler commented on Jul 5, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Daily AI Assistant

    Residual noted while closing #2450 (2026-07-05): one oversized VEX document fails to store with HTTP 413 — storing VEX ... status code 413 (post openvulnerabilityexchangecontainers) for ghcr.io-cloudnative-pg-postgresql-18.3-system-trixie (a large postgres image whose statement set exceeds the kubescape storage API's request-size limit). Impact: that single image has no VEX doc; all other 328 store fine. When this lane wires VEX into a consumer gate, treat a missing VEX doc as 'no suppression data' (fail open to the raw CVE list), and consider an upstream report if the 413 recurs on other large images.

  2. moved this to 📥 Backlog in 🌊 Project Boardon Jul 18, 2026
  3. self-assigned this
    on Jul 27, 2026
  4. 3 remaining items

  5. removed their assignment
    on Jul 29, 2026
  6. devantler commented on Aug 3, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Status: part (b) is delivered; (a) and (c) are not

    Recording this because it was being carried the other way. Several run notes stated that #2917 "closes #2451" — it does not. #2917's body reads Part of #2854, it was never linked to close this issue, and this issue correctly remains open.

    Delivered — (b) the CRD→issue bridge, merged in #2917 (11a5651, 2026-08-03). Verified on main rather than inferred from the merge: the fingerprint-collision guard and the raw-key title digest are both present in scripts/kubescape-backlog-bridge/issues.go.

    It covers the hard part this issue flagged — idempotency and anti-spam: fingerprint-deduped themed issues, search-before-create, close-when-gone, and a refusal when two derived themes claim one fingerprint rather than a silent merge.

    Still open:

    • (a) SARIF → Code Scanning PR gate — posture regressions surfacing pre-merge in the Security tab.
    • (c) Kyverno Enforce graduation for controls driven to zero.

    Both are independently shippable and neither is blocked by the other, so this is a good candidate for two children rather than one more pass on the parent.

    Nothing here changes the acceptance criteria; it only records which of the three are met, so the next run does not re-derive it or assume the issue should already have closed.

  7. devantler commented on Aug 3, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Status of the three children, verified against the code rather than re-derived

    This is the oldest open Security issue, so it heads the rung-2 queue every run and its remaining scope keeps getting re-derived. Recording it once.

    (a) SARIF→Code-Scanning PR gate — DELIVERED. Verified in .github/workflows/ci.yaml at main, not inferred:

    • the scan writes SARIF (ksail workload scan --framework nsa --exceptions … --format sarif -o …),
    • scripts/normalize-sarif-paths.sh makes paths repo-root-relative and gates the upload on its own sarif=ready output,
    • github/codeql-action/upload-sarif publishes under category: kubescape-nsa, with security-events: write and a fork-PR carve-out,
    • scripts/summarize-sarif-findings.sh reports the same findings into the log so the console and the Security tab cannot disagree.

    Both of this issue's first two acceptance criteria are met by that path.

    (b) CRD→issue bridge — DELIVERED by #2917 (merged 11a56515). ⚠️ Note it is staged, not active: nothing schedules scripts/kubescape-backlog-bridge yet — CI only runs go test against it — so live findings are not yet flowing into the backlog. Activation is still outstanding work under this epic.

    (c) Kyverno Enforce graduation — BLOCKED by #2933, and this is the important part. The in-cluster configuration scan is aborting on every run (live: 4 attempts, 0 successes since the pod started 2026-08-01), so every control currently reads as zeroed. A graduation candidate list built now would promote controls that were never evaluated. #2933 must land first.

    Net

    This issue is not startable as "implement (a)" — (a) is done. Its live remaining scope is activating (b) and (c) behind #2933. Marking that explicitly so it is skipped for the right reason instead of being repeatedly re-analysed, or worse, worked on the assumption that the SARIF gate is missing.

  8. changed the issue type fromtoon Aug 3, 2026
  9. devantler commented on Aug 3, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Revalidated against the codebase — the body above is stale

    This issue surfaced as the oldest actionable type:"Security" issue portfolio-wide, so I revalidated it before starting rather than implementing the plan as written. Two findings.

    1. Retyped Security → Epic

    It has 7 sub-issues (4 closed, 57%) and is a strategic parent that closes when its children do — it is not implementable directly. Typed Security, it sat at the head of the security queue as the oldest actionable item, so a run draining that queue would repeatedly select a parent it cannot implement. Security visibility is unaffected: the live security work is typed on the children (#2933 is Security).

    2. Part (a) is already DONE — more thoroughly than the plan asks

    Part Status
    (a) Kubescape SARIF → Code Scanning DONE. ci.yaml job validate scans and uploads (category: kubescape-nsa), path-gated to PRs and skipped on forks; validate-main.yaml publishes a main-branch baseline so PR alerts dedupe and auto-close. Both hardened beyond the plan by normalize-sarif-paths.sh (repo-root-relative URIs, fail-closed) and summarize-sarif-findings.sh.
    (b) Live-only findings → deduped issues PARTIAL (#2854). The derive+fingerprint half is built and unit-tested: two surfaces (posture, CVE), a fingerprint deliberately excluding counts/timestamps/UIDs so unchanged state is byte-identical across runs, exception suppression, fail-closed structural guards. Missing: the entire GitHub write path (search-before-create, open/update, close-when-gone, labels) — -mode=write hard-errors by design — plus the runtime node_agent_alert_counter surface, live CRD reading, and any schedule. It reads files, not the cluster.
    (c) Kyverno Enforce graduation PARTIAL (#2855). Enforce policies mapped to Kubescape controls exist (validate-host-restrictions.yaml covers C-0045/C-0048/C-0041/C-0038 and carries an explicit ratchet rule). What does not exist is graduation driven by a control reaching zero; the one policy flagged for the flip, disallow-latest-tag.yaml, is still Audit.

    Consequence for whoever picks this up

    Do not implement this issue. The startable work is its open children — and note #2933 ("the Kubescape config scan aborts every run, so posture silently reads as all-zero") is the one that most undermines the rest: a broken scanner and a compliant cluster read identically, which is the exact trap this epic exists to close.

    Also worth correcting in the plan text: (a) is framed as PR-only, but the main-branch baseline in validate-main.yaml is what actually makes Code Scanning dedupe and auto-close PR alerts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Fields

    No fields configured for Epic.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions