Repository navigation
Conversation
Signed-off-by: Devam Shah <devamshah91@gmail.com>
- 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.
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)
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).
- 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): 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)
|
This pull request has been marked stale because it has been open for 10 days with no activity |
|
This PR was closed by the stale bot after 10 days; no maintainer ever looked at it. Before asking for any of your time I re-verified the premise on current The gap is still real on
So a repo running Semgrep, Bandit, or gosec in CI scores as having no SAST configured. #2318 asked for gosec and Bandit in its body and Semgrep in a comment, and was closed as completed; Snyk, Pysa, Qodana and Hadolint are in the check today, but those three are not. Three references in my original patch were wrong. I removed them. I checked each action reference against the GitHub API instead of assuming:
The matchers are now only the three tool-owned actions that resolve today, all anchored: semgrepWorkflows, err := getSastUsesWorkflows(c, "^semgrep/semgrep-action$", checker.SemgrepWorkflow)
banditWorkflows, err := getSastUsesWorkflows(c, "^PyCQA/bandit-action$", checker.BanditWorkflow)
gosecWorkflows, err := getSastUsesWorkflows(c, "^securego/gosec$", checker.GosecWorkflow)I added a negative fixture ( Known limitation I did not try to solve. The common modern Semgrep setup is a job What I ran, on the rebased branch (
I have not run the e2e suite (it needs credentials I do not have) and I have not run The branch is pushed and ready either way. @spencerschrock, you were the last maintainer to touch |
What kind of change does this PR introduce?
Feature — expands SAST tool detection in the
SASTcheck.What is the current behavior?
The
SASTcheck detects CodeQL, Sonar, Snyk, Pysa, Qodana, and Hadolint. Threewidely deployed open-source SAST tools are not recognized:
semgrep/semgrep, legacyreturntocorp/semgrep-action)PyCQA/bandit-action) — the de facto Python SASTsecurego/gosec,securecodewarrior/github-action-gosec) — the de facto Go SASTRepositories 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
SASTcheck now also detects Semgrep, Bandit, and gosec when invoked as aGitHub Action. Detection follows the exact existing
getSastUsesWorkflowspattern used for CodeQL/Snyk/Qodana/Hadolint — each tool gets an anchored
uses:regex and a matchingSASTWorkflowTypeconstant. ThesastToolConfiguredprobe consumes the new workflow types automatically (itmaps
SASTWorkflow.Typestraight to a finding value, so no probe change isrequired).
Changes:
checker/raw_result.go: addSemgrepWorkflow,BanditWorkflow,GosecWorkflowconstants afterHadolintWorkflow.checks/raw/sast.go: add threegetSastUsesWorkflowscalls with anchored regexes.checks/raw/sast_test.go: addHas Semgrep/Has Bandit/Has gosectable 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 repositoryreference, 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-forkdo 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
semgrep/semgrepaction andthe legacy
returntocorp/semgrep-action, since both are still in active useacross repositories.
securego/gosecaction and the oldersecurecodewarrior/github-action-gosecwrapper.uses:) detection to mirror theexisting pattern exactly and keep false-positive risk low. Config-file
detection (e.g.
.semgrep.yml,.bandit) is a reasonable follow-up but isnoisier (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.