feat(security): fail-closed secret-scan gate for the public docs site#50
Merged
Conversation
Adds a gitleaks secret-scan gate so no sensitive value can reach docs.jacobpevans.com: - scripts/secret-scan.sh installs pinned, checksum-verified gitleaks and scans the committed tree (git archive HEAD), fail-closed. - .github/workflows/secret-scan.yml runs it on PRs (incl. drafts) + push to main. - .gitleaks.toml is the public-safe generic baseline (credential rules + placeholder allowlist). The org-specific ruleset stays private in docs-starlight and reaches CI as the redacted GITLEAKS_PRIVATE_CONFIG secret; fork PRs fall back to the baseline. Mirrors the change into the docs: documents the gate in security/scrubbed-values.mdx and registers the new Docs Sync routine in automation/scheduled-routines/claude-code-routines.mdx. The gitleaks Action requires a license for org accounts, so the Apache-2.0 binary is installed directly instead. Assisted-by: Claude:claude-opus-4-8
…cript Replaces scripts/secret-scan.sh with two declarative workflow steps: select the ruleset (private secret, else committed example) via shell parameter expansion, then scan with the official gitleaks OSS Docker image — no GitHub Action license (required for org accounts) and no custom install logic. - Renames .gitleaks.toml -> .gitleaks.toml.example: it is a template + fork fallback, not the active config. The active ruleset is injected from the GITLEAKS_PRIVATE_CONFIG secret. - Adds a .git path allowlist so VCS metadata is not scanned. Validated: config parses; a planted .git secret is ignored; the gate still flags the pre-existing client-term references in the docs tree. Assisted-by: Claude:claude-opus-4-8
Switches the gate from the raw gitleaks Docker image to gitleaks-action@v2, now that the dryvist org provides GITLEAKS_LICENSE_KEY. The ruleset is injected from the org-wide GITLEAKS_PRIVATE_CONFIG secret (never committed — the sensitive list stays private), materialized to a config file at run time. The action runs gitleaks with --redact; PR comments, SARIF artifact, and job summary are disabled so the rule taxonomy / file locations are not exposed on this public repo. Removes the now-unused .gitleaks.toml.example. Updates the security doc to match. Assisted-by: Claude:claude-opus-4-8
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.
Secret-scan gate for the public docs site
What
Adds a fail-closed gitleaks gate so no
sensitive value can reach
docs.jacobpevans.com, and mirrors the change into thedocs themselves.
.github/workflows/secret-scan.yml— runs on PRs (incl. drafts) and push tomain. No script: two declarative steps — select the ruleset via shellparameter expansion, then scan with the official gitleaks OSS Docker image
(
ghcr.io/gitleaks/gitleaks:v8.30.1). The gitleaks GitHub Action requires apaid license for org accounts; the image does not.
.gitleaks.toml.example— the public-safe generic baseline (built-incredential rules + placeholder allowlist +
.gitskip). It is a template /fork fallback, not the active config.
security/scrubbed-values.mdx— documents the gate (the implementation ofgolden law 1).
automation/scheduled-routines/claude-code-routines.mdx— registers the newDocs Sync routine (six → seven).
Two-layer design (list stays private)
The full org-specific ruleset lives only in the private
docs-starlightrepoand reaches CI as the encrypted
GITLEAKS_PRIVATE_CONFIGsecret, run with--redact(patterns and matches never appear in public logs). When the secret isabsent (fork PRs), the workflow falls back to the committed
.gitleaks.toml.examplevia${GITLEAKS_PRIVATE_CONFIG:-$(cat …)}— so forksstill get credential detection, and full org-specific coverage runs on push to
main.Validation
gitleaksreports no leaks foundon the docs tree (using the example fallback, since the secret isn't set yet).
dirty fixture, passes clean content, no false positives on
CLAUDE.local.md,svc.cluster.local,192.168.0.x,example.com.Running the full ruleset against the existing docs surfaces 3 pre-existing
visicorereferences (inobservability/overview.mdxand a.claude/skill).The
GITLEAKS_PRIVATE_CONFIGsecret is therefore not set yet — doing so wouldmake the gate fail-closed on existing content. Decide: strip the refs, allowlist
visicoreas intentionally public, or adjust the client-terms rule. Until then,the gate runs the safe generic baseline (this PR is green on it).
Operator setup (after the decision above)
Then make Secret Scan a required check on
main.Related
dryvist/docs-starlight#17(merged) — the private ruleset this consumes.dryvist/docs-starlight#18—.gitscan-skip follow-up.dryvist/claude-code-routines#36(merged) — the Docs Sync routine.🤖 Generated with Claude Code