Skip to content

feat(governance): add secret-scanner-reusable.yml — propagate shell-secrets to 281 repos#190

Merged
hyperpolymath merged 1 commit into
mainfrom
feat/secret-scanner-reusable
May 26, 2026
Merged

feat(governance): add secret-scanner-reusable.yml — propagate shell-secrets to 281 repos#190
hyperpolymath merged 1 commit into
mainfrom
feat/secret-scanner-reusable

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Extends the reusable-workflow pattern from #168 / #174 / #187 to secret-scanner.yml. Same shape as #187 (no per-call inputs except runs-on; caller uses secrets: inherit).

Why secret-scanner is the next foundational reusable

Estate drift survey (gh api /search/code paginated against org:hyperpolymath, blob-SHA grouped over all 281 deployments):

Metric Value
Total deployments 281
Unique blob SHAs 54
Structural drift 19% (top 4 SHAs cover 69%, top 6 cover 79%)
Feature variance near-zero — all sampled variants carry the same 3 jobs (trufflehog + gitleaks + rust-secrets) at 75-81 lines
True drift source action-SHA pin churn + whitespace

The 100-sample drift estimate (55%) initially ranked secret-scanner third behind mirror; the full pagination reveals the actual figure is 19%. The variance was a sampling artefact.

Security debt this PR force-fixes

The shell-secrets job was added to the canonical 2026-05-21 (commit 080c394) in direct response to the live Cloudflare API token leak via avow-protocol/deploy-repos.sh (commit 5f2f8b2) — a leak that both trufflehog --only-verified and default gitleaks missed.

Of 16 estate secret-scanner.yml blobs sampled across the top + long-tail SHAs, 0 carry the shell-secrets job.

The post-incident guardrail intended to catch the next such leak has propagated to nothing. Consolidating the workflow behind this reusable means the wrapper sweep that follows this PR force-promotes shell-secrets to all 281 repos in one batch.

Design

  • No per-call inputs other than runs-on — each job self-conditions internally:
    • rust-secrets exits early on no Cargo.toml (safe on every repo)
    • shell-secrets no-ops without .sh/.bash files
    • trufflehog + gitleaks always-on (intended)
  • secrets: inherit required at the call site — so the inner secrets.GITHUB_TOKEN reference in the gitleaks-action step resolves. Without inherit it falls back to anonymous mode (rate-limited; misses some PRs).
  • Caller keeps on: + concurrency: — so the read-only cancel-superseded guardrail stays in the wrapper.
  • SPDX header, top-level permissions: contents: read, all actions SHA-pinned — passes the workflow-lint job in governance-reusable.yml.

Caller wrapper shape (post-merge)

# SPDX-License-Identifier: PMPL-1.0-or-later
name: Secret Scanner
on:
  pull_request:
  push:
    branches: [main]
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
permissions:
  contents: read
jobs:
  scan:
    uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@<sha>
    secrets: inherit

~12 lines per repo, replacing ~75-116 lines.

Rollout plan

NOT started in this PR — owner-gated, same as #187 / #174 sweeps.

Wave Repos Action
1: bulk-mechanical ~275 Canonical 3-job match. Fan-out single-commit wrapper PR per repo, pinned to this PR HEAD; rebase to merged-main SHA before batch firing.
2: slim variants ~6 Repos with 2-job (missing rust-secrets) or 1-job (trufflehog only) older copies. Standardize-up safely since the missing job self-skips on non-applicable repos.

Total expected sweep: ~281 PRs (well above the 82-PR rust-ci precedent — recommend batching by wave; user gates each wave start).

Pattern hardening

🤖 Generated with Claude Code

…ecrets to 281 repos

Extends the #168/#174/#187 reusable-workflow pattern to secret-scanner.yml.

Drift survey (gh api /search/code paginated over org:hyperpolymath,
blob-SHA grouped):
- 281 deployments
- 54 unique blob SHAs (19% structural drift — well below the 100-sample
  estimate of 55% that earlier candidate ranking used)
- Top 4 SHAs cover 69% of repos; top 6 cover 79%
- All sampled top + long-tail variants carry the same 3 jobs
  (trufflehog + gitleaks + rust-secrets) at 75-81 lines — drift is
  action-SHA / whitespace churn only

Security debt this PR addresses: the `shell-secrets` job (added to
canonical 2026-05-21 after the live Cloudflare token leak via
`avow-protocol/deploy-repos.sh`, which both `trufflehog --only-verified`
and default gitleaks missed) is currently present in 0 of 16 sampled
estate repos. The post-incident guardrail intended to catch the next
leak has propagated to nothing; the wrapper sweep that follows this PR
gets it estate-wide in one batch.

Design (same shape as #187 mirror-reusable):
- No per-call inputs other than `runs-on`. Each job self-conditions
  internally (rust-secrets exits early without Cargo.toml; shell-secrets
  no-ops without .sh/.bash files).
- Caller uses `secrets: inherit` so gitleaks-action's `GITHUB_TOKEN`
  resolves; caller keeps its own `on:` triggers + `concurrency:` group.
- SPDX, top-level `permissions: contents: read`, SHA-pinned actions.

After merge, ~98% of 281 wrappers are mechanical (canonical 3-job
match); ~2% slim variants (2-job, missing rust-secrets) standardize-up
safely since the missing job self-skips on no-Rust repos.
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 118 issues detected

Severity Count
🔴 Critical 64
🟠 High 43
🟡 Medium 11

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/deno-ci-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "deno-ci-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Python file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml-templates/state-scm-to-v2.py",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/lol/test/vitest.config.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/k9-svc/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "Agda postulate assumes without proof -- potential soundness hole (4 occurrences, CWE-704)",
    "type": "agda_postulate",
    "file": "/home/runner/work/standards/standards/lol/proofs/theories/information_theory.agda",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "critical"
  },
  {
    "reason": "believe_me undermines formal verification (1 occurrences, CWE-704)",
    "type": "believe_me",
    "file": "/home/runner/work/standards/standards/lol/src/abi/Locale.idr",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "critical"
  },
  {
    "reason": "Wildcard CORS -- restrict to specific origins or use env var (1 occurrences, CWE-942)",
    "type": "js_wildcard_cors",
    "file": "/home/runner/work/standards/standards/consent-aware-http/examples/reference-implementations/deno/aibdp_middleware.js",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "high"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath enabled auto-merge (squash) May 26, 2026 10:47
@hyperpolymath hyperpolymath merged commit 3e4bd4c into main May 26, 2026
18 checks passed
@hyperpolymath hyperpolymath deleted the feat/secret-scanner-reusable branch May 26, 2026 14:41
hyperpolymath added a commit to hyperpolymath/presswerk that referenced this pull request May 26, 2026
Pins to hyperpolymath/standards#190 merge SHA 3e4bd4c93911750727e2e4c66dff859e00079da0. Force-propagates
the shell-secrets job (added post-Cloudflare-leak 2026-05-21) to this
repo's secret-scanning gate. Replaces ~75-116 lines with a ~14-line wrapper.

Part of estate-wide convergence campaign 2026-05-26
(standards#199 / #190).
hyperpolymath added a commit that referenced this pull request May 26, 2026
…ergence set (#205)

## Summary

5th and final reusable in the workflow convergence campaign (see #199
for the meta-doc). Consolidates the per-repo `scorecard.yml` workflow.

## Drift signal (full pagination + per-repo verified)

- **258** top-level estate deployments
- **626** nested copies in monorepos (asdf-tool-plugins,
developer-ecosystem, ssg-collection, standards, ambientops,
julia-ecosystem, etc. — Layer-2 truncation discovery via #204's helper)
- **46** unique blob SHAs / 17.8% structural drift
- Top SHA covers **100/258 (38.8%)** — highest dominant-cluster of the 5
campaigns
- Top 7 SHAs cover ~80%
- **100% mechanical drift, ZERO feature variance** — SPDX header
(PMPL-1.0 / PMPL-1.0-or-later / MPL-2.0), `upload-sarif` SHA-pin churn,
`permissions: read-all` vs `contents: read` wording

## Design

- One input: `runs-on` (default ubuntu-latest)
- No `secrets: inherit` — Scorecard uses `GITHUB_TOKEN` directly
- Caller MUST grant `security-events: write` + `id-token: write` on the
calling job (called-workflow permissions are capped by caller)
- Caller keeps own `on:` triggers + `concurrency:` group

## Per Layer-3 caveat from the campaign meta-doc

Nested workflows are inert — GitHub Actions only runs
`.github/workflows/` at the repo root. Sweeping the 626 nested copies is
single-source-of-truth cleanup, not security hardening.

## Campaign convergence set (closes with this PR)

| PR | Template |
|---|---|
| #187 | mirror-reusable.yml |
| #190 | secret-scanner-reusable.yml |
| #192 | codeql-reusable.yml |
| #193 | hypatia-scan-reusable.yml |
| #194 | sweep-classifier scripts |
| #199 | campaign meta-doc |
| #204 | list-workflow-paths.sh (bypass /search/code undercount) |
| **this** | **scorecard-reusable.yml** |

## Test plan

- [ ] Wrapper sweep (~258 top-level + ~626 nested) — owner-gated; not
part of this PR
- [ ] Update classify-* scripts to consume helper TSV — follow-up

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

1 participant