Skip to content

security: bind reusable SAST and security scans to the exact pull-request head #1222

Description

@seonghobae

Problem

Organization-required reusable security workflows currently produce synthetic-merge evidence for pull requests instead of scanning the exact submitted head.

Fresh reproduction on ContextualWisdomLab/g7#1 on 2026-08-22:

  • exact PR head: 4a1773f604b3971478f486557dac137d4202086c
  • GitHub synthetic merge: 8fb41406de757dd2c8edf7a7006c8bd4c68bb29f
  • Security Scan run 32558956134 checked out the synthetic merge ref;
  • SAST Semgrep run 32558956167 checked out the same synthetic merge ref;
  • the current central sast-semgrep.yml checkout has no explicit PR-head ref;
  • the current central security-scan.yml Trivy/dependency-review checkout paths likewise do not bind the scan to the submitted head.

This violates the organization merge-evidence contract: synthetic merge, predecessor-head, queued, skipped-required, or otherwise non-exact evidence must never be promoted to exact-current-head proof.

The g7 canary also shows why the distinction matters operationally: the reusable scans currently fail on broad repository/base findings (Trivy dependency findings and 234 Semgrep warning/error findings), so the leaf readiness PR must not absorb unrelated remediation simply to manufacture a passing gate.

Responsibility boundary

Fix this in the organization-central reusable workflow layer. Do not duplicate or weaken the gate in downstream repositories and do not change leaf application code to compensate for checkout semantics.

Required design

For pull-request runs, resolve and verify the immutable target repository plus pull_request.head.sha before scanning. Preserve the repository's normal default ref for protected-branch pushes and other explicitly supported events. Where a scanner legitimately compares base and head, materialize both immutable revisions and make the evidence labels unambiguous rather than treating a synthetic merge ref as the submitted head.

SARIF attribution, job summaries, logs, artifacts, and any machine-readable evidence should record the target repository, exact submitted head SHA, base SHA where relevant, and the actual checked-out commit. Fail closed if those identities disagree.

Acceptance criteria

  • SAST Semgrep pull-request jobs scan github.event.pull_request.head.sha from the correct target/head repository, not refs/pull/*/merge.
  • Trivy filesystem and other head-oriented Security Scan jobs scan the exact submitted PR head.
  • Base/head comparison jobs materialize and label both immutable revisions without conflating either with the synthetic merge commit.
  • A focused workflow contract test rejects a PR checkout without an exact-head ref.
  • A downstream canary proves git rev-parse HEAD == pull_request.head.sha in SAST and Security Scan evidence.
  • SARIF/check evidence remains associated with the intended pull request without weakening severity thresholds or suppressing valid findings.
  • Existing least-privilege permissions, immutable action/container pins, cancellation behavior, and fail-closed security gates remain intact.
  • No manual success status, stale evidence, or branch-protection bypass is introduced.

Downstream dependency

g7#1 must remain unmerged while its exact-current-head CI/security/review/protection contract is incomplete. Its broad pre-existing dependency/SAST baseline should be handled as separate security-owner work rather than mixed into the bounded readiness change.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: authAuthentication, authorization, identity, or tenant isolationarea: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: dependenciesDependency or lockfile maintenancearea: securitySecurity boundary, hardening, or vulnerability preventionpriority: highHigh-priority or P1 workstatus: triagedOpen issue has an organization taxonomy assignmenttype: securitySecurity vulnerability or security-specific remediation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions