Skip to content

Fix cosign + gh-attestation rules — line-anchor + shell-continuation aware#11

Merged
Cre-eD merged 1 commit into
mainfrom
fix/semgrep-cosign-rules-shell-continuation
May 16, 2026
Merged

Fix cosign + gh-attestation rules — line-anchor + shell-continuation aware#11
Cre-eD merged 1 commit into
mainfrom
fix/semgrep-cosign-rules-shell-continuation

Conversation

@Cre-eD
Copy link
Copy Markdown
Contributor

@Cre-eD Cre-eD commented May 16, 2026

Problem

After #10 merged, the api repo's Semgrep CI gate went red with 40 ERROR-severity findings — all false positives from three of the new rules:

  • gha-cosign-verify-without-identity-flag × 15
  • gha-cosign-verify-without-oidc-issuer-flag × 15
  • gha-gh-attestation-missing-scope × 10

Two failure modes, both rooted in pattern-not-regex being line-scoped:

  1. Shell line-continuation invisibility. Real cosign commands span multiple lines via trailing \:

    cosign verify "$img" \
        --certificate-identity-regexp "$IDENTITY_REGEX" \
        --certificate-oidc-issuer "$OIDC_ISSUER"

    The line-scoped not-regex only checked the cosign verify line itself, missing the required flags on continuation lines.

  2. Comment / error-string false matches. Patterns like echo "::warning title=cosign verify failed::$img" and comment text mentioning cosign verify-attestation contain the literal substring but are not real commands.

Fix

Rewrite each affected rule as a single multi-line regex with:

Tweak Regex fragment Effect
Command-start anchor (?:^[ \t]*|run:[ \t]+) Match must sit at the beginning of an (indented) line OR directly after run: (single-line step form). Filters out error strings, comments, and inline backtick mentions.
Shell-continuation-aware negative lookahead (?!(?:[^\n]*\\\s*\n)*?[^\n]*<flag>) Greedily walks any trailing-backslash continuation lines, checking the entire shell command body for the required flag.

Validation

Before After
verify-attestations.yml 14 FPs 0
push.yaml 4 FPs 0
build-staging.yml 8 FPs 0
branch-preview.yaml 4 FPs 0
semgrep-scan/run-tests.sh full-repo 0 0
sigstore-cases.yml fixture 9/9 9/9

Test plan

…tinuation

The line-scoped `pattern-not-regex` design (shipped in #10) misfired on
real consumer workflows in two ways:

1. **Shell line-continuation invisibility.** Real cosign commands span
   multiple lines via trailing backslash:
       cosign verify "$img" \
           --certificate-identity-regexp "$IDENTITY_REGEX" \
           --certificate-oidc-issuer "$OIDC_ISSUER"
   The line-scoped not-regex only checked the `cosign verify` line, not
   the continuation, so every multi-line invocation tripped both
   `gha-cosign-verify-without-identity-flag` and
   `gha-cosign-verify-without-oidc-issuer-flag`.

2. **Comment / error-string false matches.** Patterns like
       echo "::warning title=cosign verify failed::$img"
       # `cosign verify-attestation --type cyclonedx`
   contain the literal `cosign verify` substring but are not actual
   commands. The bare regex `\bcosign\s+verify\b` matched them.

Rewrite as a single multi-line regex per rule with:
  - command-start anchor: `(?:^[ \t]*|run:[ \t]+)cosign\s+verify…` so
    the match must sit at the beginning of an (indented) line or
    directly after `run:` (single-line step form).
  - shell-continuation-aware negative lookahead:
    `(?!(?:[^\n]*\\\s*\n)*?[^\n]*<required-flag>)`
    Greedily walks any trailing-backslash continuation lines and checks
    the entire shell command body for the flag.

Empirical validation on the api repo's 4 attestation-bearing workflows
(verify-attestations.yml, push.yaml, build-staging.yml,
branch-preview.yaml): 30 → 0 false positives. The api repo CI gate that
went red after #10 merged will go green on the next pull_request /
workflow_dispatch.

Fixtures already cover the command-start anchor path (`- run: cosign
verify …`) — semgrep-scan/run-tests.sh still 0 findings full-repo, 9/9
on sigstore-cases.yml.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
@github-actions
Copy link
Copy Markdown

Security Scan Results

Repository: actions | Commit: a7b4f1f

Check Status Details
✅ Secret Scan Pass No secrets detected
⏩ Dependencies Skipped -

Scanned at 2026-05-16 17:07 UTC

@github-actions
Copy link
Copy Markdown

Semgrep Scan Results

Repository: actions | Commit: a7b4f1f

Check Status Details
✅ Semgrep Pass 0 total findings (no error/warning)

Scanned at 2026-05-16 17:08 UTC

@Cre-eD Cre-eD merged commit bc4a81b into main May 16, 2026
11 checks passed
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.

1 participant