Skip to content

checks/sast: detect Semgrep, Bandit, and gosec SAST workflows - #5103

Closed
DevamShah wants to merge 1 commit into
ossf:mainfrom
DevamShah:feat/sast-detect-semgrep-bandit-gosec
Closed

checks/sast: detect Semgrep, Bandit, and gosec SAST workflows#5103
DevamShah wants to merge 1 commit into
ossf:mainfrom
DevamShah:feat/sast-detect-semgrep-bandit-gosec

Conversation

@DevamShah

Copy link
Copy Markdown

What kind of change does this PR introduce?

Feature — expands SAST tool detection in the SAST check.

What is the current behavior?

The SAST check detects CodeQL, Sonar, Snyk, Pysa, Qodana, and Hadolint. Three
widely deployed open-source SAST tools are not recognized:

  • Semgrep (semgrep/semgrep, legacy returntocorp/semgrep-action)
  • Bandit (PyCQA/bandit-action) — the de facto Python SAST
  • gosec (securego/gosec, securecodewarrior/github-action-gosec) — the de facto Go SAST

Repositories that run these tools in CI are currently scored as if they have no
SAST configured. This is a false negative: a project with real static analysis
coverage receives a lower SAST score than its security posture warrants.

What is the new behavior (if this is a feature change)?

The SAST check now also detects Semgrep, Bandit, and gosec when invoked as a
GitHub Action. Detection follows the exact existing getSastUsesWorkflows
pattern used for CodeQL/Snyk/Qodana/Hadolint — each tool gets an anchored
uses: regex and a matching SASTWorkflowType constant. The
sastToolConfigured probe consumes the new workflow types automatically (it
maps SASTWorkflow.Type straight to a finding value, so no probe change is
required).

Changes:

  • checker/raw_result.go: add SemgrepWorkflow, BanditWorkflow, GosecWorkflow constants after HadolintWorkflow.

  • checks/raw/sast.go: add three getSastUsesWorkflows calls with anchored regexes.

  • checks/raw/sast_test.go: add Has Semgrep / Has Bandit / Has gosec table cases.

  • checks/raw/testdata/.github/workflows/: add three workflow fixtures using the real action references.

  • docs/checks/sast/README.md: list the three newly supported tools.

  • Tests for the changes have been added (for bug fixes/features)

Security rationale

SAST is a primary control against the introduction of injection, deserialization,
path-traversal, and hardcoded-secret defects (CWE-79, CWE-89, CWE-22, CWE-502,
CWE-798). Scorecard's SAST signal feeds downstream supply-chain risk decisions; a
false negative here understates the real assurance level of a dependency and can
nudge consumers toward unwarranted manual review or, worse, away from a project
that is in fact well-instrumented.

Semgrep, Bandit, and gosec are among the most commonly adopted open-source SAST
tools across the JavaScript/Python/Go ecosystems, so closing this gap materially
improves the accuracy of the SAST score for a large slice of the OSS population.

The detection regexes are fully anchored (^...$) on the action repository
reference, so they match the canonical tool actions and their documented legacy
aliases while rejecting look-alike forks and typosquats
(semgrep/semgrep-app-action, securego/gosec-installer, PyCQA/bandit-action-fork
do not match). This keeps false-positive risk minimal, consistent with the
existing CodeQL/Qodana matchers.

Which issue(s) this PR fixes

NONE

Special notes for your reviewer

  • The matcher for Semgrep covers both the current semgrep/semgrep action and
    the legacy returntocorp/semgrep-action, since both are still in active use
    across repositories.
  • gosec covers the maintained securego/gosec action and the older
    securecodewarrior/github-action-gosec wrapper.
  • I deliberately scoped this to GitHub Action (uses:) detection to mirror the
    existing pattern exactly and keep false-positive risk low. Config-file
    detection (e.g. .semgrep.yml, .bandit) is a reasonable follow-up but is
    noisier (these files are frequently present without CI enforcement), so I left
    it out of this PR; happy to add it in a follow-up if maintainers want it.

Does this PR introduce a user-facing change?

Yes — repositories that run Semgrep, Bandit, or gosec via GitHub Actions will now
have those tools recognized by the SAST check.

checks/sast: detect Semgrep, Bandit, and gosec SAST tools when configured as GitHub Actions

Signed-off-by: Devam Shah <devamshah91@gmail.com>
@DevamShah
DevamShah requested a review from a team as a code owner June 23, 2026 01:36
@DevamShah
DevamShah requested review from AdamKorcz and spencerschrock and removed request for a team June 23, 2026 01:36
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jun 23, 2026
yves-vogl added a commit to yves-vogl/moneymoney-paypal-pos-extension that referenced this pull request Jun 23, 2026
- new .github/workflows/sast.yml runs Semgrep on push (main, phase-*) + PR (any)
- ruleset: p/security-audit + p/secrets (D-34); --error makes ERROR-severity blocking (D-33)
- SARIF upload via github/codeql-action/upload-sarif with if: always() so findings surface even on failure
- pip install semgrep==1.167.0 (NOT container, avoids Docker Hub rate-limit per RESEARCH Pitfall 7)
- SHA-pinned uses: actions/checkout@11bd719 (v4.2.2),
  actions/setup-python@a309ff8 (v6.2.0),
  github/codeql-action@8272c29 (v3.36.2)
- top-level permissions: read-all; job permissions: security-events:write + actions:read + contents:read
- checkout: persist-credentials: false + fetch-depth: 0
- job name 'Semgrep SAST' (load-bearing for Plan 06.1-04 branch-protection CHECKS array)
- --exclude spec avoids JWT-shaped test fixtures (RESEARCH §5)
- local dry-run (semgrep 1.167.0 against src/**) returned 0 findings, 0 suppressions needed

Closes SEC-08 (the security control). Scorecard SAST score reporting deferred
to upstream ossf/scorecard#5103 — ADR-0009 (Plan 06.1-08) documents the gap.
yves-vogl added a commit to yves-vogl/moneymoney-paypal-pos-extension that referenced this pull request Jun 23, 2026
Add SUMMARY.md documenting the .github/workflows/sast.yml landing:
- ruleset p/security-audit + p/secrets, ERROR-blocking, SARIF upload
- SHA-pinned actions (checkout v4.2.2, setup-python v6.2.0, upload-sarif v3.36.2)
- pip install semgrep==1.167.0 (not container)
- local dry-run on src/** returned 0 findings, 0 suppressions
- Scorecard SAST score gap documented (ossf/scorecard#5103 upstream pending)
- branch-protection CHECKS update deferred to Plan 06.1-04 (deadlock prevention)
yves-vogl added a commit to yves-vogl/moneymoney-paypal-pos-extension that referenced this pull request Jun 23, 2026
Documents the bewusst akzeptierten Gaps (Fuzzing 0/10, Code-Review 0/10,
Packaging -1, Contributors structural, Maintained heals-itself) with
compensating mitigations and Alternatives Considered (Option B 1-reviewer,
Option C bot-reviewer, Snyk Code, SBOM+cosign+SLSA deferred to v1.1.x,
G-09 awk shell-interpolation low-severity, Lua/CI Semgrep rulesets).

Revises the Phase-6.1 aggregate target: ≥ 7.5 short-term, ≥ 8.5 once
ossf/scorecard#5103 merges (SAST 0→10) AND repo age crosses 90 days
(Maintained 0→8+, ~2026-09-15).

Closes DOC-11 (in concert with this plan's SECURITY.md + REQUIREMENTS.md
+ ROADMAP.md edits).
yves-vogl added a commit to yves-vogl/moneymoney-paypal-pos-extension that referenced this pull request Jun 23, 2026
- SEC-05 modified in-place: expanded with SCORECARD_READ_TOKEN provisioning,
  branch-protection invariants (linear history, no force-push/delete, no admin
  bypass), 5 required status checks, Scorecard Branch-Protection.score >= 3
  (Tier 1; Option A locked per ADR-0009).
- SEC-06 new: SHA-pinned uses: refs in workflows + CI grep gate + Dependabot
  lockstep + Scorecard Pinned-Dependencies.score == 10.
- SEC-07 new: permissions: read-all top-level + job-local writes +
  persist-credentials: false + Scorecard Token-Permissions.score == 10.
- SEC-08 new: Semgrep SAST workflow ERROR-blocking + SARIF in code-scanning +
  required status check; backlog issue tracks ossf/scorecard#5103.
- BUILD-07 new: CII Best Practices passing badge in both READMEs + Scorecard
  CII-Best-Practices.score >= 5.
- DOC-11 new: ADR-0009 + SECURITY.md supply-chain section + REQUIREMENTS
  updates + backlog issues.
- Traceability table appended with 5 Phase-6.1 rows; total count 70 -> 75.
yves-vogl added a commit to yves-vogl/moneymoney-paypal-pos-extension that referenced this pull request Jun 23, 2026
* docs(06.1): land RESEARCH + PATTERNS + CONTEXT post-Phase-6 addendum

Phase 6.1 (Supply-chain & Scorecard hardening) planning input.

- 06.1-RESEARCH.md (71K): current-state vs CONTEXT D-30..D-36 reconciliation,
  pinning strategy, permissions hardening, branch protection deltas, Semgrep
  SAST design, CII Best Practices, SBOM/attestation scope recommendation,
  egress allowlist refactor, ADR numbering, sequencing recommendation,
  open items. Cites live gh API + ossf/scorecard checks.md + Dependabot
  changelog + actions/attest-build-provenance + bestpractices.dev.
- 06.1-PATTERNS.md (15K): 14 target files mapped to in-repo analogs.
  Calls out CHECKS-array drift in setup-branch-protection.sh and missing
  persist-credentials:false across 5 checkout invocations as the two
  most load-bearing anti-patterns to guard.
- 06.1-CONTEXT.md addendum: D-30..D-36 status table (D-31/D-32 partially
  delivered by Phase 6 CP-2 + ci.yml split; D-30 not delivered).
  New decisions D-37..D-41: MkDocs Material docs site (Yves request
  2026-06-23), SBOM/attestation deferred to v1.1.x, ADR number 0009
  (not 0004 — taken), CII badge in both READMEs, Phase-6 R1 findings
  disposition (G-04/05/06/09/10/14 in scope; G-13/15/16 out; S-R2-L-01
  in; S-R2-M-01 monitoring-only).

* ci(06.1-02): add explicit .gitleaks.toml inheriting defaults

Closes G-14. The default gitleaks ruleset already covers every secret
shape this repo currently emits; an explicit config file makes the
active ruleset auditable and provides a slot for future project-
specific [[rules]] blocks if a Zettle/PayPal API-key shape ever evades
the default ruleset.

- File is minimal (23 lines), declares [extend] useDefault = true
- No active [[rules]] blocks — only a commented example slot
- Pairs with .gitleaksignore (per-fingerprint allowlist, owned by Phase 6)
- gitleaks-action auto-discovers the config at repo root; no CI YAML change
- Local smoke test: zero findings (gitleaks 8.30.1)

* ci(06.1-01): SHA-pin all 17 action references across 4 workflows

Replace every floating tag (`@v4`, `@v13`, `@v2`, `@v3`, `@v2.4.0`, …)
with a 40-char commit SHA + `# vX.Y.Z` trailing comment per Dependabot
convention. Closes SEC-06 (Pinned-Dependencies) and G-05.

Per-action resolved targets (re-resolved 2026-06-23 via `gh api`):

- actions/checkout                v4.2.2  11bd7190
- leafo/gh-actions-lua            v13.0.0 6919171c
- leafo/gh-actions-luarocks       v6.1.0  35d062de
- gitleaks/gitleaks-action        v2.3.9  ff98106e
- actions/upload-artifact         v4.6.2  ea165f8d
- actions/download-artifact       v4.3.0  d3f86a10
- softprops/action-gh-release     v2.6.2  3bb12739
- ossf/scorecard-action           v2.4.3  99c09fe9
- github/codeql-action            v3.36.2 8272c299

All majors held at currently-pinned line per PLAN guidance
(minimise blast radius — defer v5+/v6+/v7+ bumps to Dependabot review).

Files: 4 workflow files; no src/, tools/, or spec/ changes.
Reproducible-build SHA invariant on dist/paypal-pos.lua preserved
(baseline 18bb7a6a…).

* ci(06.1-01): persist-credentials, top-level read-all, gates hardening

Task 2 of Plan 06.1-01 — surgical hardening across all four workflows:

- ci.yml: add top-level `permissions: read-all` (SEC-07 acceptance bar);
  add `persist-credentials: false` to both checkouts (test + secret-scan
  jobs) per G-06; extend the D-79 print-gate to also catch `io.write(`
  and obvious `local p = print` / `local w = io.write` aliasing (G-04);
  add a new permanent SEC-06 grep gate step that walks
  `.github/workflows/*.yml` and fails any future PR that introduces a
  floating-tag `uses:` reference; replace the brittle
  `awk '{print $NF}' | sed 's/%//' | cut -d. -f1` luacov-parser pipeline
  with a single awk invocation that emits both the full percentage and
  the integer floor (G-09 / PATTERNS §3 row 2).

- release.yml: add `persist-credentials: false` to both checkouts
  (verify-signed-tag + build-test-coverage-repro jobs) per G-06 —
  `git verify-tag` is local-object-only per RESEARCH §3 A8; replace
  the same `awk | sed | cut` anti-pattern at line 139 with the
  single-awk pattern (ci.yml and release.yml updated in the same
  commit so they cannot drift); tighten the publish job to depend
  on `[verify-signed-tag, build-test-coverage-repro]` explicitly
  (G-10 defense in depth — a future refactor that drops the chained
  needs: cannot silently let an unsigned tag publish).

- commit-lint.yml: add explicit per-job `permissions: { contents: read }`
  for SEC-07 textual posture; add `persist-credentials: false` to the
  checkout per G-06 (commit-subject lint reads local git objects only).

- scorecard.yml: untouched in this commit (its checkout already carried
  `persist-credentials: false` per Phase 6 hardening; Task 1 already
  pinned its action references).

Reproducible-build SHA on dist/paypal-pos.lua unchanged
(18bb7a6a…ed8e0c1) — zero src/, tools/, or spec/ modifications.

Closes SEC-07 (Token-Permissions → 10/10 expected), G-04, G-06, G-09,
G-10. SEC-06 closed by Task 1's SHA-pinning + this commit's grep gate
that prevents future regressions.

* ci(06.1-05): group Dependabot github-actions minor+patch updates

Add groups: clause to .github/dependabot.yml github-actions ecosystem
to coalesce minor + patch SHA bumps into one weekly PR. Major-version
bumps stay in separate PRs (breaking-change surface needs attention).

Post Plan 06.1-01, 17 action refs across 4 workflows are SHA-pinned;
without grouping Dependabot would emit one PR per outdated action per
week. The actions-minor-patch group reduces that to typically one
combined PR + zero or one major-version PR.

Also extends the top-of-file comment to document Dependabot's SHA +
trailing version-comment lockstep behaviour (GitHub changelog
2022-10-31; extended Oct 2025 to correct stale comments). Maintainers
must not manually edit the # vX.Y.Z comments — let Dependabot manage
them in lockstep with the SHA.

applies-to: version-updates is explicit so security updates remain
individual PRs (faster turnaround on vulnerabilities).

* ci(06.1-03): add semgrep SAST workflow

- new .github/workflows/sast.yml runs Semgrep on push (main, phase-*) + PR (any)
- ruleset: p/security-audit + p/secrets (D-34); --error makes ERROR-severity blocking (D-33)
- SARIF upload via github/codeql-action/upload-sarif with if: always() so findings surface even on failure
- pip install semgrep==1.167.0 (NOT container, avoids Docker Hub rate-limit per RESEARCH Pitfall 7)
- SHA-pinned uses: actions/checkout@11bd719 (v4.2.2),
  actions/setup-python@a309ff8 (v6.2.0),
  github/codeql-action@8272c29 (v3.36.2)
- top-level permissions: read-all; job permissions: security-events:write + actions:read + contents:read
- checkout: persist-credentials: false + fetch-depth: 0
- job name 'Semgrep SAST' (load-bearing for Plan 06.1-04 branch-protection CHECKS array)
- --exclude spec avoids JWT-shaped test fixtures (RESEARCH §5)
- local dry-run (semgrep 1.167.0 against src/**) returned 0 findings, 0 suppressions needed

Closes SEC-08 (the security control). Scorecard SAST score reporting deferred
to upstream ossf/scorecard#5103 — ADR-0009 (Plan 06.1-08) documents the gap.

* docs(06.1-03): complete semgrep SAST workflow plan

Add SUMMARY.md documenting the .github/workflows/sast.yml landing:
- ruleset p/security-audit + p/secrets, ERROR-blocking, SARIF upload
- SHA-pinned actions (checkout v4.2.2, setup-python v6.2.0, upload-sarif v3.36.2)
- pip install semgrep==1.167.0 (not container)
- local dry-run on src/** returned 0 findings, 0 suppressions
- Scorecard SAST score gap documented (ossf/scorecard#5103 upstream pending)
- branch-protection CHECKS update deferred to Plan 06.1-04 (deadlock prevention)

* fix(06.1-03): switch semgrep ci → semgrep scan (--error not supported by ci)

First push of sast.yml failed in CI (run 28026173380):
  'semgrep ci: unknown option --error'

The 'semgrep ci' subcommand is hard-wired to the Semgrep AppSec Platform
login flow and does not accept --error (per Semgrep CLI 1.167.0 `--help`).
'semgrep scan' is the offline-friendly equivalent that honors --error to
flip the exit code on ERROR-severity findings without requiring a token.

Same rules (p/security-audit + p/secrets), same SARIF output, same exclude
patterns. Adds --metrics=off for full offline determinism.

Local re-verification on src/** with the new invocation: 0 findings,
exit 0, SARIF file (514 KB) produced.

Rule 1 deviation — bug introduced by the plan text (Plan 06.1-03 Task 2
codified 'semgrep ci --error' which is not a valid invocation). Plan
intent (ERROR-severity blocking via SARIF upload) preserved byte-for-byte.

* docs(06.1-06): mkdocs material site config + bilingual landing pages

Closes D-37 (in part — workflow follows in the next commit).

Adds MkDocs Material site config and content pages that nav into existing
Markdown source-of-truth files (README.de.md, README.md, CONTRIBUTING.md,
SECURITY.md, CHANGELOG.md, ADRs 0001-0008) via mkdocs-include-markdown-plugin —
zero content duplication.

Files:
  - mkdocs.yml — site config, Material theme, mkdocs-static-i18n (de default,
    en fallback per D-70/D-71), include-markdown for nav-referenced root files,
    validation tolerance for cross-repo relative links inside included Markdown
  - docs/index.md — German landing
  - docs/en/index.md — English landing (i18n override)
  - docs/readme.md, docs/security.md, docs/contributing.md, docs/changelog.md —
    include-markdown wrappers for root Markdown
  - docs/en/readme.md — English README inlined (other docs fall back to default
    locale automatically)

Forward reference to ADR-0009 (Plan 06.1-08) is commented out in nav so
`mkdocs build --strict` passes; 06.1-08 will uncomment.

Local validation: `mkdocs build --strict` exits 0 against mkdocs 1.6.1,
mkdocs-material 9.5.41, mkdocs-static-i18n 1.2.3, mkdocs-include-markdown-plugin
7.0.0 (the versions pinned in the docs.yml workflow).

* ci(06.1-06): add docs build + GitHub Pages deploy workflow (SHA-pinned)

Closes D-37 (workflow track).

New workflow .github/workflows/docs.yml:
  - Triggers: push to main → build + deploy; PR → build-only validate;
    workflow_dispatch → manual rebuild
  - Top-level `permissions: read-all` (SEC-07); deploy job escalates to
    pages: write + id-token: write + contents: read (minimum required by
    actions/deploy-pages OIDC verification)
  - All actions SHA-pinned (SEC-06): checkout v4.2.2, setup-python v5.3.0,
    upload-pages-artifact v3.0.1, deploy-pages v4.0.5
  - persist-credentials: false on checkout (G-06)
  - concurrency: group=pages, cancel-in-progress=false (GitHub-recommended
    Pages pattern)
  - Pinned Python toolchain: mkdocs 1.6.1, mkdocs-material 9.5.41,
    mkdocs-static-i18n 1.2.3, mkdocs-include-markdown-plugin 7.0.0
    (deterministic builds; manual bump until Plan 06.1-05 follow-up extends
    Dependabot to the pip ecosystem — T-06.1-06-01/SC mitigation)
  - Build step: `mkdocs build --strict`
  - Deploy step gated on `github.event_name == 'push' && github.ref == 'refs/heads/main'`

Yves CP-6.1-C (one-time precondition before first deploy succeeds):
  Open https://github.com/yves-vogl/moneymoney-paypal-pos-extension/settings/pages
  Source: "GitHub Actions" (not "Deploy from a branch"), then Save.
  After this enablement, the workflow auto-deploys on push to main and the
  site renders at https://yves-vogl.github.io/moneymoney-paypal-pos-extension/.

* docs(06.1-06): add Documentation/Dokumentation badge to bilingual READMEs

Closes D-40 (bilingual badge cluster).

Single-line insertion in each README's badge cluster, between the OpenSSF
Scorecard badge and the GitHub Sponsors badge:
  - README.md     → "Documentation" (English label)
  - README.de.md  → "Dokumentation" (German label)

Both badges link to https://yves-vogl.github.io/moneymoney-paypal-pos-extension/
(the Pages site shipped by ci(06.1-06) workflow). No other content change in
either README — surgical edit only.

* docs(06.1-06): complete MkDocs Material site plan

* docs(06.1-03): update SUMMARY with Rule 1 fix + CI-green confirmation

- Document semgrep ci → semgrep scan Rule 1 fix (commit 27d7476)
- Record all three CI run IDs (28026173380 failed, 28026276896 failed,
  28026375102 GREEN)
- Add deferred-items.md entries for Node 20 + CodeQL Action v3 deprecations
  (both shared with Plan 06.1-01 SHAs; sync bump needed in Plan 06.1-05 or
  a dedicated follow-on)

* docs(06.1): land 8 plan files + PLAN-INDEX from planner

Plans 06.1-01 through 06.1-08 (Wave 1-5) + PLAN-INDEX (dependency graph
+ cumulative Scorecard delta). Authored by gsd-planner 2026-06-23 with
inputs from CONTEXT (D-30..D-41 incl. addendum) + RESEARCH (11 sections)
+ PATTERNS (14 file mappings).

Plans 01/02/03/05/06 already executed and on branch; this commit lands
the source-of-truth plan documents so the consolidator (06.1-08) and the
verifier have the canonical task lists available.

* ci(06.1-04): wire SCORECARD_READ_TOKEN into scorecard-action

Add `repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}` as a `with:` input
to the ossf/scorecard-action step so the Branch-Protection Scorecard
check can introspect main's protection state via a fine-grained PAT
(Administration: read). Without it scorecard-action falls back to the
default GITHUB_TOKEN, which cannot read branch-protection, and the
Branch-Protection check returns -1 (unreadable).

Closes SEC-05 expansion (Branch-Protection introspection).

Yves checkpoints (must run by hand — script run NOT included here):

  CP-6.1-A (BEFORE merge): Yves creates a fine-grained PAT
    - Resource owner: yves-vogl
    - Repository access: moneymoney-paypal-pos-extension only
    - Repository permissions: Administration -> Read-only (and nothing else)
    - Expiration: 1 year (rotation cadence captured in SECURITY.md by 06.1-08)
    Then:
      gh secret set SCORECARD_READ_TOKEN \
        --repo yves-vogl/moneymoney-paypal-pos-extension
    Verify:
      gh secret list --repo yves-vogl/moneymoney-paypal-pos-extension \
        | grep SCORECARD_READ_TOKEN
    If the secret is unset when scorecard.yml's next run fires (cron
    or push to main), the Branch-Protection check returns -1 for the
    next ~24 h of cached score.

  CP-6.1-B (AFTER merge): companion commit chore(06.1-04) updates
    tools/setup-branch-protection.sh; Yves runs the script post-merge
    to push the new 5-check CHECKS array into live protection on main.

SHA pinning (06.1-01) and top-level `permissions: read-all` preserved.

* chore(06.1-04): extend setup-branch-protection.sh CHECKS + S-R2-L-01 assertions

Three surgical edits to tools/setup-branch-protection.sh:

1. CHECKS array grows from 3 to 5 entries. Adds:
     - "Scorecard analysis"   (matches scorecard.yml job name byte-exact)
     - "Semgrep SAST"          (matches sast.yml job name byte-exact)
   Both strings verified against the workflow `name:` declarations
   in this same branch — string-drift here would silently deadlock
   every PR waiting for a non-existent check-run context.

2. Manual-UI fallback block (used when the running PAT lacks
   `Administration: write`) gains the same two bullet entries so a
   maintainer falling back to the GitHub UI configures all 5 required
   checks in lockstep.

3. Post-condition GET adds S-R2-L-01 hardening: two new jq assertions
   on the read-back protection JSON for
     `.allow_force_pushes.enabled == false`
     `.allow_deletions.enabled == false`
   The PUT payload already declares both as false; the assertions
   catch silent partial-apply by the GitHub API.

Final OK line updated to mention both new invariants.

`bash -n tools/setup-branch-protection.sh` passes cleanly.

The script is NOT run in this commit. Yves runs it post-merge as the
existing CP-2 pattern. Companion commit ci(06.1-04) wires the
SCORECARD_READ_TOKEN secret into scorecard.yml.

Closes S-R2-L-01 (branch-protection post-condition assertions for
allow_force_pushes + allow_deletions).

* docs(06.1-04): land SUMMARY + STATE bump for scorecard token + CHECKS extension

Records the two-commit execution of Plan 06.1-04:
  184b2f6  ci(06.1-04): wire SCORECARD_READ_TOKEN into scorecard-action
  93684aa  chore(06.1-04): extend setup-branch-protection.sh CHECKS + S-R2-L-01 assertions

SUMMARY captures:
  - byte-exact job-name audit trail (CHECKS entries vs workflow `name:` declarations)
  - both Yves CPs (CP-6.1-A pre-merge secret provisioning, CP-6.1-B post-merge script run)
  - threat-model coverage notes
  - self-check confirmation (file presence + commit GPG signatures)

STATE last_updated + Session Continuity bumped to reflect Phase 6.1 wave-3 progress.

Closes SEC-05 expansion + S-R2-L-01 (executor side; live protection update
gated on CP-6.1-B by Yves post-merge).

* docs(06.1-08): adr-0009 openssf scorecard stance

Documents the bewusst akzeptierten Gaps (Fuzzing 0/10, Code-Review 0/10,
Packaging -1, Contributors structural, Maintained heals-itself) with
compensating mitigations and Alternatives Considered (Option B 1-reviewer,
Option C bot-reviewer, Snyk Code, SBOM+cosign+SLSA deferred to v1.1.x,
G-09 awk shell-interpolation low-severity, Lua/CI Semgrep rulesets).

Revises the Phase-6.1 aggregate target: ≥ 7.5 short-term, ≥ 8.5 once
ossf/scorecard#5103 merges (SAST 0→10) AND repo age crosses 90 days
(Maintained 0→8+, ~2026-09-15).

Closes DOC-11 (in concert with this plan's SECURITY.md + REQUIREMENTS.md
+ ROADMAP.md edits).

* docs(06.1-08): security.md supply-chain controls section

Adds bilingual 'Lieferketten-Kontrollen / Supply-chain controls' sections
listing all 10 active controls (SHA-pinned actions, least-privilege tokens,
Semgrep SAST, branch protection, Scorecard introspection, gitleaks,
signed releases, reproducible build, redact-before-log, egress allowlist)
plus the SCORECARD_READ_TOKEN rotation runbook (≤1y expiry).

Cross-references ADR-0009 for the trade-off rationale. Mirrors the
existing DE-primary / EN-follows structure; no content above the
insertion points changed.

* chore(06.1-08): requirements bumps for SEC-05..08 BUILD-07 DOC-11

- SEC-05 modified in-place: expanded with SCORECARD_READ_TOKEN provisioning,
  branch-protection invariants (linear history, no force-push/delete, no admin
  bypass), 5 required status checks, Scorecard Branch-Protection.score >= 3
  (Tier 1; Option A locked per ADR-0009).
- SEC-06 new: SHA-pinned uses: refs in workflows + CI grep gate + Dependabot
  lockstep + Scorecard Pinned-Dependencies.score == 10.
- SEC-07 new: permissions: read-all top-level + job-local writes +
  persist-credentials: false + Scorecard Token-Permissions.score == 10.
- SEC-08 new: Semgrep SAST workflow ERROR-blocking + SARIF in code-scanning +
  required status check; backlog issue tracks ossf/scorecard#5103.
- BUILD-07 new: CII Best Practices passing badge in both READMEs + Scorecard
  CII-Best-Practices.score >= 5.
- DOC-11 new: ADR-0009 + SECURITY.md supply-chain section + REQUIREMENTS
  updates + backlog issues.
- Traceability table appended with 5 Phase-6.1 rows; total count 70 -> 75.

* docs(06.1-08): roadmap + state reconciliation + mkdocs adr-0009 nav

- ROADMAP.md: Phase 6.1 success criteria amended (aggregate >=7.5 short-term;
  Branch-Protection >=3 per Option A; SAST deferred-acceptance per ADR-0009;
  ADR file number 0009 not 0004; both READMEs for CII badge per D-40; new
  criterion #9 for MkDocs site per D-37). Phase 6.1 marked [x]. Progress
  Table appended with 'Phase 6.1 | 8/8 | Complete | 2026-06-23'.
- STATE.md: re-authoritatively rewritten with post-Phase-6.1 reality.
  status: v1.0.0-shipped-pending-tag-and-6.1-shipped; completed_phases: 7;
  Phase 6.1 ship summary documented; CP-6.1-A..D + CP-Post-08 surfaced as
  Yves tasks; CP-4/5 still pending; metrics row for Phase 6.1 added.
- mkdocs.yml: ADR-0009 nav entry un-commented (Plan 06.1-06 forward-reference
  resolved); nav_translations entry for EN locale added.

* docs(06.1-08): SUMMARY for plan 06.1-08 (consolidating docs batch)

Records: 4 commits (852cc88 ADR / 7f79a5f SECURITY / 3a42da8 REQUIREMENTS
/ 78dd7b4 ROADMAP+STATE+mkdocs), all gates green, META-03 walker 3/0/0/0,
reproducible-build SHA unchanged (no src/ edits), Yves post-merge tasks
(CP-6.1-A/B/C/Post-08) surfaced.

* fix(06.1-04): repair ci.yml YAML block-scalar in D-79 alias gate

The Plan-06.1-01 extension of the D-79 raw-print() gate concatenated
BAD and BAD_ALIAS with a literal mid-string newline at column 0:

    if [ -n "${BAD}" ]; then BAD="${BAD}
${BAD_ALIAS}"; else BAD="${BAD_ALIAS}"; fi

The unindented "${BAD_ALIAS}" line terminated the YAML literal block
scalar prematurely (block scalars are bounded by indent restoration),
and GitHub Actions rejected the workflow with a YAML parse error on
every push since 89f4ee4. Refactor to printf concatenation that stays
inside the indented block:

    BAD="${BAD_CALLS}"
    if [ -n "${BAD_ALIAS}" ]; then
      BAD="$(printf '%s\n%s' "${BAD}" "${BAD_ALIAS}")"
    fi

Semantically identical (same final BAD content); structurally valid YAML.
Verified via python -c "yaml.safe_load(...)" → OK.

* fix(06.1-r): bump mkdocs-include-markdown-plugin past CVE-2025-59940 (S-01)

* fix(06.1-r): extend branch-protection post-condition assertions (S-03 + P6.1-R-04)

* fix(06.1-r): add EN locale include wrappers for --strict build (P6.1-R-01)

* docs(06.1-r): list ADR-0009 in bilingual landing pages (P6.1-R-02)

* docs(06.1-r): ROADMAP coverage counter + Scorecard target reconciliation (P6.1-R-03)
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

This pull request has been marked stale because it has been open for 10 days with no activity

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

Labels

size:M This PR changes 30-99 lines, ignoring generated files. Stale

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant