Skip to content

ci(security): filter Scorecard SARIF to durably suppress decided-not-fixed findings - #316

Merged
Chris-Wolfgang merged 1 commit into
vNextfrom
claude/scorecard-sarif-filter
Aug 20, 2026
Merged

Chris-Wolfgang merged 1 commit into
vNextfrom
claude/scorecard-sarif-filter

Conversation

@Chris-Wolfgang

Copy link
Copy Markdown
Owner

Summary

Per-alert gh api ... -X PATCH /code-scanning/alerts/<n> dismissals do not persist across weekly Scorecard re-runs because SARIF fingerprints drift each run. #309 saw 7 DangerousWorkflowID alerts return with fresh alert numbers (194–188 vs the originally-dismissed 73–79) within hours of the dismissals.

This PR adds a jq step in scorecard.yml that filters the SARIF before upload to Code Scanning, so the categories we've decided not to fix never enter the alert list in the first place.

What's filtered (with rationale)

  • DangerousWorkflowID (7 alerts). pr.yaml intentionally uses pull_request_target with refs/pull/*/head. The untrusted checkout is safely contained by the trusted-config re-fetch from origin/main, persist-credentials: false, and top-level contents: read. Documented at pr.yaml's header.
  • PinnedDependenciesID / CLI (9 alerts). pipCommand, nugetCommand, and downloadThenRun findings for shell invocations like pip install semgrep==1.144.0, dotnet tool install … --version, and curl … | sha256sum -c — all pinned by version at the command line, which is where SHA-pinning is meaningful for CLIs. PinnedDependenciesID findings for actual GitHub Actions (which CAN be SHA-pinned, and which chore(security): SHA-pin actions, narrow permissions, triage InspectCode alerts #315 just cleaned up) still flow through — the filter matches on pipCommand|nugetCommand|downloadThenRun in the message text, not on the whole rule.

Audit trail

The raw unfiltered SARIF is still uploaded as the scorecard-results workflow artifact for 30 days. Only the Code Scanning ingest is filtered, so nothing is hidden — a maintainer can always download the raw results to see everything Scorecard emitted.

Test plan

  • Merge to vNext, then eventually to main.
  • After the next weekly Scorecard run (or a workflow_dispatch), verify gh api "repos/Chris-Wolfgang/Try-Pattern/code-scanning/alerts?state=open&tool_name=Scorecard" --paginate --jq 'length' = 0.
  • Verify the scorecard-results artifact still contains the unfiltered SARIF (i.e. a jq '.runs[].results | length' on the downloaded artifact should return the pre-filter count).

Refs: #309

🤖 Generated with Claude Code

…fixed findings

Per-alert `gh api ... -X PATCH /code-scanning/alerts/<n>` dismissals do
not persist across weekly Scorecard re-runs because SARIF fingerprints
drift each run. #309 saw 7 DangerousWorkflowID alerts return with fresh
alert numbers (194-188 vs the originally-dismissed 73-79) within hours
of the dismissals.

Filter the SARIF with `jq` BEFORE upload so these categories never
enter Code Scanning in the first place:

- **DangerousWorkflowID (7 alerts).** pr.yaml intentionally uses
  `pull_request_target` with `refs/pull/*/head`. The untrusted checkout
  is safely contained by the trusted-config re-fetch from origin/main,
  `persist-credentials: false`, and top-level `contents: read`. This is
  documented at pr.yaml's header and reviewed as intentional.

- **PinnedDependenciesID / CLI (9 alerts).** `pipCommand`,
  `nugetCommand`, and `downloadThenRun` findings for shell invocations
  like `pip install semgrep==1.144.0`, `dotnet tool install ... --version`,
  and `curl ... | sha256sum -c` — all pinned by version at the command
  line where SHA-pinning is meaningful. SHA-pinning is not applicable to
  arbitrary CLI subcommands. `PinnedDependenciesID` findings for actual
  GitHub Actions (which CAN be SHA-pinned and which #315 just cleaned up)
  still flow through — those are not filtered.

The raw unfiltered SARIF is still uploaded as the `scorecard-results`
workflow artifact for audit, so nothing is hidden — only the Code
Scanning ingest is filtered.

Expected effect on next Scorecard run:
- Scorecard open alerts: 16 → 0.

Refs: #309

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 20, 2026 01:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Chris-Wolfgang
Chris-Wolfgang merged commit 27ff3ed into vNext Aug 20, 2026
1 check passed
@Chris-Wolfgang
Chris-Wolfgang deleted the claude/scorecard-sarif-filter branch August 20, 2026 02:04
Chris-Wolfgang added a commit that referenced this pull request Aug 20, 2026
Security PATCH round. Zero runtime behaviour changes to
Wolfgang.TryPattern; every diff since v0.4.0 is workflow YAML,
analyzer packages, or test-only files.

Highlights (full detail in CHANGELOG):

- SHA-pin all workflow actions to fleet-standard commit SHAs (+61
  Scorecard PinnedDependenciesID alerts resolved).
- Narrow semgrep-sast.yaml SARIF-upload permission to job-level
  (+1 TokenPermissionsID resolved).
- Add durable jq SARIF filter in scorecard.yml for DangerousWorkflowID
  and CLI PinnedDependenciesID; raw SARIF still uploaded as workflow
  artifact (16 residual alerts drop to 0 on next weekly run).
- InspectCode triage: 11 real findings fixed, 5 suppressed with
  justification at tests/.editorconfig.
- Dependency bumps: SonarAnalyzer.CSharp 10.31→10.32,
  Microsoft.SourceLink.GitHub 10.0.301→10.0.400,
  Meziantou.Analyzer 3.0.125→3.0.156.

Closes the fleet-wide 2026-08-13 code-scanning audit umbrella (#309)
for this repo.

Refs: #309, #311, #312, #314, #315, #316, #318

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants