Skip to content

ci: enterprise-required dependency review and Semgrep workflows - #95

Merged
bryanfawcett merged 4 commits into
stagingfrom
claude/enterprise-dependency-review
Oct 7, 2026
Merged

bryanfawcett merged 4 commits into
stagingfrom
claude/enterprise-dependency-review

Conversation

@bryanfawcett

Copy link
Copy Markdown
Member

What

Two workflows for the enterprise rulesets in #94. Each runs on every pull request into the default branch and staging, in every repo in the enterprise.

  • dependency-review.yml
    • review: actions/dependency-review-action v5.0.0, pinned. It fails on a newly added dependency with a high or critical advisory (runtime and development scopes). It doesn't comment on the PR, so it also works on forks.
    • audit: each ecosystem's own auditor, run only on the lockfiles the change touches.
      • npm audit and pnpm audit fail on high and above.
      • cargo audit fails on any advisory.
      • pip-audit runs on uv.lock (via uv export) and requirements*.txt, with --no-deps --disable-pip so nothing is installed, and fails on any advisory.
      • yarn.lock, bun.lock and poetry.lock are left to review and named in the job summary.
  • reusable-semgrep.yml
    • Uses the open-source Semgrep CLI in the official image, pinned by digest. No token, metrics off.
    • Rule packs: p/typescript p/javascript p/react p/python p/rust p/secrets p/owasp-top-ten, plus the repo's own .semgrep.yml or .semgrep/ if it has one.
    • Fails with --error on findings. On PRs and merge queue groups it runs --baseline-commit against the base, so only new findings count. Other events get a full scan.
    • .astro files: the frontmatter and <script> blocks are extracted to .ts files (line numbers kept) and scanned with the same rules. p/secrets reads .astro directly.
    • It has workflow_call and pull_request/merge_group triggers, so the ruleset can name it directly and repos can also call it.

A ruleset-run workflow ignores on: filters, so both workflows check the event themselves.

How it is enforced

Two new enterprise rulesets, in evaluate mode only, will name these files at refs/heads/main, targeting ~DEFAULT_BRANCH and staging (same conditions as enterprise-release-version-check). They get switched to active only after the evaluate numbers have been reviewed (#94).

Verification

This repo runs both workflows on its own PRs, so this PR dogfoods them (see the checks below). Locally:

  • actionlint, prettier and yamllint (repo config) pass.
  • npm audit --package-lock-only, pnpm@10.34.6 audit (with manage-package-manager-versions=false) and pip-audit --no-deps --disable-pip were run against real lockfiles from mzizi-dev/packages-npm and shamwari-ai/shamwari.
  • The Astro extraction was run on bundu-labs/marketing files, and line counts are preserved.

Refs #94

🤖 Generated with Claude Code

https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq

Two workflows for the enterprise rulesets in #94, each run
on every pull request into the default branch and staging:

- dependency-review.yml: actions/dependency-review-action (fails on new
  high or critical advisories) plus npm, pnpm, cargo and pip-audit runs
  on the lockfiles a change touches. Passes when nothing changed.
- reusable-semgrep.yml: the open-source Semgrep CLI (image pinned by
  digest, no token, metrics off), community packs for TypeScript,
  JavaScript, React, Python, Rust, secrets and the OWASP Top 10,
  diff-aware against the base commit, with Astro frontmatter and scripts
  extracted so the TypeScript rules read them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
Signed-off-by: Bryan Fawcett <bryan@nyuchi.com>
bryanfawcett and others added 3 commits October 7, 2026 21:15
Review findings on #95:
- run npm, pnpm and cargo audit on copies of the lockfile in an empty
  directory, with the registry on the command line, so a pull request's
  .npmrc, .pnpmfile.cjs or .cargo/audit.toml can neither run code nor
  silence the audit;
- resolve ranged requirements files with uv pip compile --no-build, fall
  back to the exact pins, and warn rather than fail when nothing can be
  pinned; drop git and URL references before pip-audit;
- scan Astro extracts in a scratch git repo holding the base and head
  versions, with Semgrep's baseline, so only new findings count;
- show Semgrep's scan summary in the log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
Signed-off-by: Bryan Fawcett <bryan@nyuchi.com>
Re-review findings on #95: strip the pnpm, packageManager and devEngines
fields from package.json before pnpm audit, so a pull request cannot add
auditConfig ignores or switch the pinned pnpm, and turn off pnpm's
version switching. Drop `name@url` requirements however the `@` is
spaced.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
Signed-off-by: Bryan Fawcett <bryan@nyuchi.com>
Review finding on #95: a wildcard pin such as `six==1.*` crashed
pip-audit and turned the whole file into "not audited". The fallback now
keeps only exact `==` versions (markers allowed, indentation allowed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
Signed-off-by: Bryan Fawcett <bryan@nyuchi.com>
@bryanfawcett

Copy link
Copy Markdown
Member Author

Merge gate record

Code review (/code-review, run inside an isolated clone): four rounds.

  • Round 1 (high): 6 findings.
    • Fixed in f2ec0ac:
      • pnpm could load a PR's .pnpmfile.cjs;
      • a PR's .npmrc or .cargo/audit.toml could silence the auditors;
      • ranged requirements.txt files hard-failed;
      • git/URL deps in the uv export broke pip-audit;
      • the Astro scan was not diff-aware.
    • Answered: GHAS and the dependency graph are on for every private repo, all 32 non-archived, under the enforced enterprise config 281854.
  • Round 2 (high): 2 findings, fixed in 42eeb19.
    • A PR's package.json pnpm.auditConfig / packageManager could silence pnpm or swap its version.
    • name@url requirements without spaces got through.
  • Round 3 (medium): 1 finding, fixed in 3c5f4f9. A wildcard ==1.* pin crashed pip-audit's exact-pin fallback.
  • Round 4 (medium): clean, no findings.

Runtime verification: draft PR #96 planted findings on top of this branch. All three jobs failed as intended:

  • review: PyYAML 5.3 and lodash 4.17.4 flagged.
  • audit:
    • npm found a critical lodash advisory, even though the PR added an .npmrc pointing at an invalid registry, so the isolation holds;
    • pip-audit flagged PyYAML 5.3;
    • cargo audit flagged RUSTSEC-2021-0003 (smallvec 1.6.0).
  • scan: Semgrep flagged the planted TypeScript (code-string-concat, direct-response-write), Python (subprocess-shell-true) and Astro frontmatter (hardcoded-jwt-secret, found through the extraction).

Locally I also confirmed:

  • The Astro baseline: an unchanged old finding passes, and a new one fails.
  • pnpm audit with the stripped package.json still reports the advisories.
  • The uv.lock path works on nyuchi/mcp-ynab.

On this PR itself, with nothing to review, all checks are green.

Note for rollout: the community rule npm-missing-minimum-release-age flags any .npmrc that a PR touches if it doesn't set minimum-release-age. The evaluate-mode numbers will show whether that's noisy.

@bryanfawcett
bryanfawcett merged commit 2172582 into staging Oct 7, 2026
22 checks passed
@bryanfawcett
bryanfawcett deleted the claude/enterprise-dependency-review branch October 7, 2026 13:26
bryanfawcett added a commit that referenced this pull request Oct 7, 2026
Release staging to main: #95 adds dependency-review.yml and
reusable-semgrep.yml, which the enterprise rulesets read from
refs/heads/main. The tree is staging's exact tree.


Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq

Signed-off-by: Bryan Fawcett <bryan@nyuchi.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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