Skip to content

security: bootstrap sscsb supply-chain controls, and retire a Semgrep workflow that scanned nothing - #1

Open
p4gs wants to merge 3 commits into
mainfrom
security/sscsb-bootstrap
Open

p4gs wants to merge 3 commits into
mainfrom
security/sscsb-bootstrap

Conversation

@p4gs

@p4gs p4gs commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Update 2026-10-06: Gitleaks stays, alongside TruffleHog — owner decision. TruffleHog only finds credentials for providers it has a detector for, and with --results=verified,unknown it reports a match only when the provider confirms it live or the verification attempt errors; it drops matches it could not verify, including those from detectors that have no verifier. Gitleaks matches on shape, so it also catches generic secrets such as passwords, internal tokens and keys for services TruffleHog has no detector for. Restored in 2dfb7a6. The signed local scan record committed in b789505 (.sscsb/scan-record.local.json) was generated on 7841113, before this restore, and still records gitleaks: disabled in config — read it as historical, not current.

Summary

Bootstraps sscs-bootstrapper on ALCOVE: 47 controls installed, 32 enabled. sscsb verify went 4 failed / 3 degraded → 1 failed / 2 degraded (before vs. after the bootstrap commit 7841113, measured 2026-09-12, before Gitleaks was restored). Re-run on the current head 2dfb7a6: 1 failed / 1 degraded — scorecard now reports pass (see Open items #4 below).

Four things needed deciding rather than accepting as generated.

Both engines stay enabled as generated (trufflehog = true, gitleaks = true in .sscsb/config.toml). TruffleHog only finds credentials for providers it has a detector for, and with --results=verified,unknown it reports a match only when the provider confirms it live or the verification attempt errors; it drops matches it could not verify, including those from detectors that have no verifier. Gitleaks matches on shape, so it also catches generic secrets such as passwords, internal tokens and keys for services TruffleHog has no detector for. gitleaks = true turns Gitleaks on in the local sscsb pre-commit hook; the pre-push range scan already runs Gitleaks whenever a gitleaks binary is on PATH, whatever this flag says, and both hooks use whatever binary is on PATH. CI does not read this flag at all: the generated gitleaks job (gitleaks/gitleaks-action) runs unconditionally on every push to main and every pull request. That action is commercially licensed and hard-fails on an organization-owned repo without a GITLEAKS_LICENSE secret, so in CI specifically Gitleaks instead runs as a checksum-verified binary pulled straight from the GitHub release, scoped on pull_request and normal push events to the same commit range the licensed action scanned (--no-merges --first-parent BASE..HEAD), and falling back to the head commit alone when the push base cannot be resolved — e.g. after a force-push to main — with a committed .gitleaks.toml extending the default ruleset.

CodeQL now reads this repo's actual source. The generated matrix is ["actions"] — the only language sscsb can assume every repo has — and its own comment warns that CodeQL which does not read your source code is not analysing your source code. Added javascript-typescript for assets/js/site.js, the one executable file ALCOVE ships.

Removed .github/workflows/semgrep.yml, which had been green daily while analysing nothing. It passes SEMGREP_APP_TOKEN from a secret that does not exist on this repository (gh secret list is empty), so every run since 2026-08-23 logged:

run `semgrep login` before using `semgrep ci` or use `semgrep scan` and set `--config`
There were errors during analysis but Semgrep will succeed because there were no blocking findings

…and exited 0. 44 consecutive green runs (2026-08-23 to 2026-10-05), zero analysis. It was also the sole source of three sscsb verify failures (actions/checkout@v4 on a mutable ref, no persist-credentials: false, no harden-runner). Its replacement already runs here: OpenGrep (Semgrep-compatible, committed ruleset, no cloud token) plus CodeQL. Pinning it would have left a workflow that still scanned nothing — a green check that cannot fail is worse than no check, because people trust it.

Added SECURITY.md, which security-insights.yml referenced twice without it existing, and filled the generated REPLACE-ME placeholders.

Why this is a PR and not a push to main

The pre-push gate requires hardware_backed = true on protected branches. The approved signer is the 1Password-vaulted ed25519 key that signs every commit made outside the GitHub web UI here (the two web-UI commits on main, a9b3d5d and 9d739c5, carry GitHub's web-flow signature) — a vaulted software key, not a non-exportable secure element — so signers.toml records it as backend = "software" with no hardware assertion. All three commits here are signed and verify Good.

Relaxing that gate was deliberately not done. The honest options were a false hardware_backed = true attestation, --no-verify, or a documented require_hardware_backed = false — and the third was blocked by the agent permission classifier, correctly, as a weakening of a security control. It is left for a human decision. See "Open items".

Open items for the maintainer

  1. Branch protection — the one remaining verify failure. main has no ruleset: no required PRs, no force-push blocking, no required signed commits, no required status checks. sscsb harden branch-protection can only update an existing ruleset, not create one, and creating it is a repo-admin write. Needs a human.
  2. Signing posture. Either accept software-backed signing for this repo (set require_hardware_backed = false, documenting why), or provision a YubiKey ed25519-sk and record it with hardware_backed = true. Until one of those, direct pushes to main are blocked locally by design.
  3. signing-model degraded — github-web (vigilant mode, phishing-resistant MFA), codespaces (GPG verification) and cloud-claude (GitHub App installed) need attestations only a human can truthfully make (sscsb signing setup <lane> --confirm). Not fabricated here. Two of the causes behind that degradation are not attestations at all: cloud-claude's repo-side attribution is probeable and is not in place, and an attestation cannot stand in for it; and the agent-claude-code lane is simply incomplete (sscsb signing setup agent-claude-code).
  4. scorecard — no Scorecard results are published yet. On 2dfb7a6, sscsb verify reports pass only because the code-scanning API returns zero open Scorecard alerts, so that pass is vacuous until scorecard.yml actually runs on the default branch, which happens after this merges.

AI Provenance Declaration

  • AI generated or assisted with code in this PR
  • AI generated or assisted with tests in this PR
  • AI introduced or suggested new dependencies in this PR
  • AI generated or assisted with documentation in this PR

AI tool(s)/model(s) used (if any): Claude Code (claude-opus-5 for 7841113 and b789505; Sonnet 5 for 2dfb7a6), AI-Role: draft

Human review performed on AI-generated parts (what/how): Pending maintainer review. Every claim above is tool-verified rather than asserted: the Semgrep no-op is quoted from run 34686171235's own log, the empty secret list from gh secret list, and the verify counts from sscsb verify before and after the bootstrap commit 7841113.

Dependency Changes

  • No new dependencies

🤖 Generated with Claude Code

https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm

p4gs and others added 2 commits September 12, 2026 11:48
… that scanned nothing

`sscsb init` installs 47 controls (32 enabled) — signed-commit policy, secret
scanning at pre-commit/pre-push/CI, SBOM, vulnerability scanning, SAST, SLSA
provenance, Scorecard, Renovate and the OpenSSF posture files. Four things
needed deciding rather than accepting as generated.

TruffleHog is the only credential-detection engine. `gitleaks = false` in
.sscsb/config.toml, and the generated gitleaks CI job is removed so CI enforces
the policy the config declares instead of contradicting it. TruffleHog verifies
candidates against the issuing provider, so a finding is a live credential
rather than a high-entropy string; a second, unverifying engine beside it adds
false positives without adding detection.

CodeQL now analyses this repo's actual source. The generated matrix is
`["actions"]` — the only language sscsb can assume every repo has — and its own
comment says CodeQL that does not read your source code is not analysing your
source code. Added `javascript-typescript` for assets/js/site.js, the one
executable file ALCOVE ships. The rest of the tree is HTML, CSS, SVG and woff2.

Removed .github/workflows/semgrep.yml, which had been reporting success daily
while analysing nothing. The workflow passes `SEMGREP_APP_TOKEN` from a secret
that does not exist on this repository (`gh secret list` is empty), so every
run since 2026-08-23 logged `run 'semgrep login' before using 'semgrep ci'`
followed by "There were errors during analysis but Semgrep will succeed because
there were no blocking findings" — and exited 0. Roughly twenty consecutive
green runs, zero analysis. It was also the sole source of three sscsb verify
failures: `actions/checkout@v4` on a mutable ref, no `persist-credentials:
false`, and no harden-runner. Its replacement is already here and actually
runs: OpenGrep (Semgrep-compatible, committed ruleset, no cloud token) plus
CodeQL. Fixing the pinning would have left a workflow that still scanned
nothing; a green check that cannot fail is worse than no check, because people
trust it.

Added SECURITY.md, which security-insights.yml referenced twice without it
existing, and filled the generated REPLACE-ME placeholders.

Approved signer recorded in .sscsb/policy/signers.toml is the 1Password-vaulted
ed25519 key that already signs every commit here. It is declared
`backend = "software"` and NOT hardware-backed, because it is a vaulted
software key rather than a non-exportable secure element — sscsb keeps warning
about that, correctly, and the warning is left standing rather than silenced
with a false attestation.

sscsb verify: 4 failed / 3 degraded before, 1 failed / 2 degraded after. The
remaining failure is branch protection, which needs a repository ruleset that
does not exist yet; `sscsb harden` can only update one, not create it.

AI-Assisted: true
AI-Tool: Claude Code
AI-Model: claude-opus-5
AI-Role: draft
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm
`sscsb scan --local` at 91f0b0a, signed in the `sscsb-scan-record` namespace by
the approved signer this repository commits in .sscsb/policy/allowed_signers.
The record is a pointer the public directory reads from this repo, so both the
JSON and its detached signature have to be tracked.

It asserts the local result only. It is not evidence CI produced anything —
where a control is observable from the repository, the directory requires an
independent record to agree before the row counts.

AI-Assisted: true
AI-Tool: Claude Code
AI-Model: claude-opus-5
AI-Role: draft
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Owner decision: run Gitleaks alongside TruffleHog in CI rather than
TruffleHog alone. TruffleHog verifies candidate credentials against
the issuing provider, but Gitleaks catches generic secrets and
unverifiable keys that TruffleHog's --results=verified,unknown filter
drops, so the two engines cover different detection classes rather
than duplicating one.

AI-Assisted: true
AI-Tool: Claude Code
AI-Model: Sonnet 5
AI-Role: draft
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012hwWMsTiv9Uf2gNbMh75uk
@p4gs p4gs changed the title security: bootstrap sscsb supply-chain controls, and retire a scanner that scanned nothing security: bootstrap sscsb supply-chain controls, and retire a Semgrep workflow that scanned nothing Oct 6, 2026

This branch has not been deployed

No deployments
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