Conversation
`sscsb init` on the repo behind grc.engineering, then fix every gap the first
`sscsb verify` reported. Verify went 5 FAIL / 2 DEGRADED -> 1 FAIL / 1 DEGRADED
(the remaining two are remote-GitHub and account-level, handled separately).
Policy set before the first verify:
- Credential detection is TruffleHog ONLY. It verifies a candidate against the
issuing provider, so a finding is a live credential rather than a regex
match; gitleaks-action also needs a paid licence for org-owned repos.
[controls.secrets] gitleaks = false, and the gitleaks job and .gitleaks.toml
are removed by hand because the init template does not render from that key.
- SAST is CodeQL + OpenGrep, both enabled, plus the pre-existing Semgrep Cloud.
Existing workflows hardened (actions-audit, workflow-audit-extended,
harden-runner, dependency-pinning all FAIL -> PASS):
- ci.yml: top-level `contents: write` -> `contents: read` with a job-scoped
write grant; harden-runner added; checkout/setup-python/cache pinned to
full commit SHAs; the four `pip install` steps version-pinned. checkout
keeps its credential deliberately and says why -- `mkdocs gh-deploy` pushes
to gh-pages over the origin remote.
- semgrep.yml: moved off the mutable `semgrep/semgrep` container onto the
runner host so harden-runner can attach (it cannot monitor a container job),
Semgrep version pinned, actions SHA-pinned, persist-credentials: false.
CodeQL was analysing `actions` only -- it had never read this site's
JavaScript. The matrix now covers actions + javascript-typescript with
security-extended. That requires GitHub's code-scanning *default setup* to be
turned off, which is done on the repo alongside this change.
Also: SECURITY.md written (security-insights.yml referenced a file that did not
exist); security-insights placeholders filled; the owner's signing key recorded
in .sscsb/policy/signers.toml with hardware_backed = false, which is the honest
value and leaves commit-signing's advisory note standing rather than asserting
a secure-element key that does not exist; protected_branches narrowed to the
one branch this repo actually has.
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
|
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:
For more information about GitHub Code Scanning, check out the documentation. |
`sscsb scan --local` at 361c9d3, after the branch ruleset on `main` was brought up to standard (required PRs, required signed commits, required status checks, strict up-to-date, on top of the deletion + force-push rules that were already there). Result: 0 failed, 1 degraded, 29 of 47 controls passing. The one degraded control is `signing-model`, whose remaining lanes are account- and machine-level rather than repository-level; see PR description. 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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First-time SSCS Bootstrapper bootstrap for the repository behind grc.engineering, then every gap the first
sscsb verifyreported, fixed.sscsb verifywent 5 FAIL / 2 DEGRADED → 1 FAIL / 1 DEGRADED (22 → 28 PASS of 47 controls). The two that remain are not code in this repo, and are described at the bottom.Policy set before the first verify
Credential detection is TruffleHog only. TruffleHog verifies a candidate against the issuing provider, so a finding is a live credential rather than a regex match. Gitleaks is regex-only, and
gitleaks-actionadditionally requires a paidGITLEAKS_LICENSEfor organisation-owned repositories — this one is owned bygrcengineering— so the second job would have been licence-gated noise, not added detection. GitHub secret scanning with push protection is separately enabled on the repo.SAST is CodeQL + OpenGrep, both enabled, alongside the pre-existing Semgrep Cloud job (a third, genuinely different rule set — the org's own semgrep.dev policy).
Gaps found and fixed
actions-auditactions/checkout,actions/setup-python,actions/cacheinci.ymlandsemgrep.ymlwere on mutable tags — all pinned to full commit SHAs (staying within their current major; Renovate now proposes the bumps)workflow-audit-extendedpermissionsnarrowed andpersist-credentials: falseonsemgrep.ymlharden-runnerci.ymlandsemgrep.yml.semgrep.ymlhad to come off itscontainer: semgrep/semgrep(a mutable image) and onto the runner host, because Harden-Runner cannot monitor a container job; Semgrep is now pip-installed at a pinned versiondependency-pinningpip installsteps inci.ymltook whatever PyPI served at build time — now version-pinnedcodeqlactionsonly and had never read this site's JavaScript. Nowactions+javascript-typescriptwithsecurity-extendedsecurity-insightsREPLACE-MEadministrator placeholder filled;SECURITY.mdwritten — the generated file pointed at a policy file that did not exist anywhere in the repo or the org.githubrepocommit-signing.sscsb/policy/signers.tomlbranch-protectionmasterremoved fromprotected_branches(this repo has no such branch, so it was reporting on nothing); the remote ruleset is handled separately, belowci.ymlkeeps its checkout credential deliberately, and says so in a comment:mkdocs gh-deploypushes the built site togh-pagesover the origin remote and needs it. It is the only job in the repo that does; every other workflow setspersist-credentials: false. Thecontents: writegrant moved from the top level (where all jobs inherited it) down to that one job.CodeQL default setup is being switched off
GitHub's code-scanning default setup was configured for
actionsonly, on a weekly schedule. Default setup and an advanced configuration cannot both be enabled, so it was set tonot-configuredimmediately before this branch was pushed and.github/workflows/codeql.ymltakes over: both languages,security-extended, on every push and PR, with pinned actions and Harden-Runner.Honest values, not green checkmarks
hardware_backed = falseis recorded for the owner's signing key. It is an ed25519 key held in a 1Password vault and used through the 1Password SSH agent with device authentication on every signature — strong custody, but not a secure-elementssh-ed25519-skcredential.require_hardware_backedis left on rather than lowered to force a pass, sosscsb verifykeeps reporting the advisory note. Closing it means provisioning a YubiKey-resident signing key, which is an owner decision.Dormant by design: the
release-*workflows anddeploy-gate.ymltrigger onrelease, and this repo cuts none. They are inert until it does.Observation, not changed here
docs/projects/nthpartyfinder/index.htmlloads a stylesheet fromfonts.googleapis.comat page-render time. That is a live third-party dependency on a public site with no SRI possible (the response varies by user agent). It is left alone on purpose — that page is in-flight design work and this is a security-baseline PR, not a design change.AI Provenance Declaration
AI tool(s)/model(s) used (if any): Claude Code (claude-opus-5)
Human review performed on AI-generated parts (what/how): every workflow change verified by running the tools that gate them —
actionlintclean across all 14 workflows,sscsb verifybefore and after,sscsb sast(0 findings),sscsb scan(0 findings), andopengrepagainst thep/javascript,p/secrets,p/github-actions,p/ciandp/xssregistry packs. Action SHAs resolved from the GitHub API against their tags, not written from memory. Pending owner review of the two open items below.Dependency Changes
No package-manager dependencies are added. The pinned
pip installversions inci.ymlare the same packages that were already being installed unpinned; pinning them is the fix.Merge Policy Reminder
Merges to protected branches must be signed by an approved human key, and AI involvement is declared above, so the merge wants a
Reviewed-by:trailer.Still open — deliberately
signing-modelstays DEGRADED. Its four open lanes are account- and machine-level, not repository-level, and two of them would contradict a standing owner directive:agent-claude-codewants a distinct AI signing identity, which this account retired on purpose in favour of one signer everywhere, andcloud-claudewants a repo-level.claude/settings.jsoncarrying that same separate identity.github-web(vigilant mode, phishing-resistant MFA) andcodespaces(GPG verification) have no read API —sscsb signing setup … --confirmonly records a dated human attestation, and attesting facts about the owner's account that cannot be verified is exactly the shortcut this baseline exists to prevent. These are the owner's to close.sscsb hardencannot see this repo's ruleset. The existing "Protect" ruleset targets~DEFAULT_BRANCH;sscsb hardenlooks for a literal branch name and reportsno ruleset targets this branch — skipped. The ruleset is updated directly through the API instead, as a separate step on this PR.🤖 Generated with Claude Code
https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm