Skip to content

Dependency reputation: deps.dev and Scorecard gate for added dependencies (#111) - #163

Open
ms280690 wants to merge 6 commits into
issue-83-egress-blockfrom
issue-111-dependency-reputation
Open

ms280690 wants to merge 6 commits into
issue-83-egress-blockfrom
issue-111-dependency-reputation

Conversation

@ms280690

Copy link
Copy Markdown
Collaborator

Closes #111. Stacked on #139 (issue-83-egress-block) for docs/egress-allowlist.md and the block-mode CI pattern; retarget to main once that merges.

What

  • .github/actions/dependency-reputation: stdlib-only reputation.py. Diffs every changed lockfile between base-sha and HEAD (git show for the base side) and takes the package@version pairs only on the head side, so version bumps count and removals do not. Parsers for package-lock.json, pnpm-lock.yaml, yarn.lock (v1 and berry), requirements*.txt (== pins), poetry.lock, uv.lock, Cargo.lock (via tomllib) and go.sum. For each added package the deps.dev v3 client fetches the version (OSV advisory ids, related projects), the source project (OpenSSF Scorecard overall score and the Maintained, Dangerous-Workflow, Binary-Artifacts, Signed-Releases checks) and the package (latest publishedAt). Responses are cached one JSON per system/package@version; --offline never fetches.
  • Gates: MAL-* advisory blocks when fail-on-malicious (default true); Scorecard score below min-scorecard blocks (0 disables); latest release older than max-age-days (730), unknown package (404) and no Scorecard only warn. Annotations at the lockfile line, step summary and markdown report (<!-- dependency-reputation --> marker, one row per package), findings.json, outputs added-count, blocking-count, report-path. Exit 1 blocking, 2 unsupported ecosystem. No base-sha (push runs) passes with a notice. Lockfiles under **/tests/**, **/test/**, **/fixtures/** are skipped by default (exclude).
  • dependency-reputation.yml reusable workflow with the inputs from the issue plus exclude, comment, actions-ref; actions/cache on the deps.dev cache (deps-dev- restore prefix), dependency-reputation artefact, one PR comment edited in place (fork PRs skipped). Caller grants pull-requests: write for the comment.
  • CI: new Dependency Reputation job (egress github.com, api.github.com, api.deps.dev): offline fixtures, the composite on this repo's own PR diff, then a live lookup from a throwaway repo that adds requests==2.34.2 and asserts one added package with a Scorecard and a written cache entry.
  • README rows and "Dependency Reputation (deps.dev and Scorecard)" section; docs/egress-allowlist.md row.

Tests

tests/dependency-reputation/run.sh builds a throwaway git repo from fixtures/base and fixtures/head (every lockfile format, each with an added package, plus a version bump, a removal and a scoped pnpm package that must not count) and runs the script offline against a seeded cache: healthy, low-score, MAL-*, stale, 404 and no-Scorecard packages. Asserts the exact added set with file and line, the per-gate outcomes and exit codes, annotation placement, report rows, ecosystem filter, exclude globs, offline cache miss, and the no-base and bad-ecosystem paths.

The Vulnerabilities Scorecard column from the issue is omitted: deps.dev does not carry that check, so the advisories column covers it. Maven and NuGet have no lockfile parser (documented).

Deferred

  • Run on a real Sparkgeo PR after merge.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NPH9145e4gFo6bmXvMgBoF

Answer "should we trust this package at all?" for every dependency a pull
request adds. reputation.py diffs each changed lockfile (npm, pnpm, yarn,
requirements*.txt, poetry, uv, go.sum, Cargo.lock) against the base
commit and asks deps.dev about every package@version only on the head
side: OSV advisories (MAL-* means malicious), the source repository and
its OpenSSF Scorecard, and the latest release date. Responses are cached
one JSON per package@version and carried between runs with actions/cache.

Gates: a MAL-* advisory blocks when fail-on-malicious is set, a Scorecard
score below min-scorecard blocks (0 disables); a stale latest release, an
unknown package and a missing Scorecard only warn. The reusable workflow
runs the composite on the PR diff, uploads the findings and keeps one PR
comment edited in place.

CI runs the differ and gate fixtures offline, the composite on this
repo's own diff, and one live deps.dev lookup from a throwaway repo that
adds requests, so the client and cache are proven against the real API.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPH9145e4gFo6bmXvMgBoF
@ms280690 ms280690 self-assigned this Oct 12, 2026
Comment thread tests/dependency-reputation/run.sh Fixed
ms280690 and others added 2 commits October 11, 2026 18:28
A lockfile version string is pull-request input. Unencoded it could carry
path separators into the cache file name and, through the mkdir on the
write side, land a response JSON outside the cache directory. Encode the
version like the name and refuse any resolved path outside cache-dir.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPH9145e4gFo6bmXvMgBoF
… for Dependency Review

The test script tripped shellcheck SC2016 on a backticked grep pattern.
MegaLinter on this base still lints recorded fixtures, so exclude them the
same way the threat-feeds change does. Dependency Review needs
api.deps.dev and api.securityscorecards.dev once a PR adds a dependency
GitHub has no repository URL for, as the fixture lockfiles here do.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPH9145e4gFo6bmXvMgBoF
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ❌ 1 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 12 package(s) with unknown licenses.
See the Details below.

License Issues

tests/dependency-reputation/fixtures/head/package-lock.json

PackageVersionLicenseIssue Type
left-pad1.3.0WTFPLIncompatible License
kept-lib4.17.21NullUnknown License

tests/dependency-reputation/fixtures/base/package-lock.json

PackageVersionLicenseIssue Type
kept-lib4.17.20NullUnknown License
removed-lib2.29.4NullUnknown License

tests/dependency-reputation/fixtures/base/pnpm-lock.yaml

PackageVersionLicenseIssue Type
@scope/kept2.0.0NullUnknown License
kept-lib4.17.21NullUnknown License

tests/dependency-reputation/fixtures/base/yarn.lock

PackageVersionLicenseIssue Type
kept-lib4.17.21NullUnknown License

tests/dependency-reputation/fixtures/head/pnpm-lock.yaml

PackageVersionLicenseIssue Type
@scope/kept2.0.0NullUnknown License
evil-stream0.1.1NullUnknown License
kept-lib4.17.21NullUnknown License

tests/dependency-reputation/fixtures/head/poetry.lock

PackageVersionLicenseIssue Type
lowscore1.0.0NullUnknown License

tests/dependency-reputation/fixtures/head/yarn.lock

PackageVersionLicenseIssue Type
kept-lib4.17.21NullUnknown License
old-lib2.0.0NullUnknown License
Allowed Licenses: MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, Unlicense, CC0-1.0

OpenSSF Scorecard

Scorecard details
PackageVersionScoreDetails
actions/actions/checkout 3d3c42e5aac5ba805825da76410c181273ba90b1 🟢 6.3
Details
CheckScoreReason
Maintained🟢 45 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4
Code-Review🟢 10all changesets reviewed
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies🟢 3dependency not pinned by hash detected -- score normalized to 3
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Packaging⚠️ -1packaging workflow not detected
SAST🟢 10SAST tool is run on all commits
Branch-Protection🟢 6branch protection is not maximal on development and all release branches
actions/actions/upload-artifact 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a 🟢 5.2
Details
CheckScoreReason
Code-Review🟢 10all changesets reviewed
Maintained⚠️ 00 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Packaging⚠️ -1packaging workflow not detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 1dependency not pinned by hash detected -- score normalized to 1
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
SAST🟢 10SAST tool is run on all commits
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
npm/kept-lib 4.17.20 UnknownUnknown
npm/removed-lib 2.29.4 UnknownUnknown
npm/@scope/kept 2.0.0 UnknownUnknown
npm/kept-lib 4.17.21 UnknownUnknown
pip/urllib3 2.8.0 UnknownUnknown
pip/urllib3 2.8.0 UnknownUnknown
pip/urllib3 2.8.0 UnknownUnknown
npm/kept-lib 4.17.21 UnknownUnknown
npm/kept-lib 4.17.21 UnknownUnknown
npm/left-pad 1.3.0 UnknownUnknown
npm/@scope/kept 2.0.0 UnknownUnknown
npm/evil-stream 0.1.1 UnknownUnknown
npm/kept-lib 4.17.21 UnknownUnknown
pip/lowscore 1.0.0 UnknownUnknown
pip/urllib3 2.8.0 UnknownUnknown
pip/requests 2.34.2 UnknownUnknown
pip/urllib3 2.8.0 UnknownUnknown
pip/ghost 9.9.9 UnknownUnknown
pip/urllib3 2.8.0 UnknownUnknown
npm/kept-lib 4.17.21 UnknownUnknown
npm/old-lib 2.0.0 UnknownUnknown

Scanned Files

  • .github/workflows/dependency-reputation.yml
  • tests/dependency-reputation/fixtures/base/package-lock.json
  • tests/dependency-reputation/fixtures/base/pnpm-lock.yaml
  • tests/dependency-reputation/fixtures/base/poetry.lock
  • tests/dependency-reputation/fixtures/base/requirements.txt
  • tests/dependency-reputation/fixtures/base/uv.lock
  • tests/dependency-reputation/fixtures/base/yarn.lock
  • tests/dependency-reputation/fixtures/head/package-lock.json
  • tests/dependency-reputation/fixtures/head/pnpm-lock.yaml
  • tests/dependency-reputation/fixtures/head/poetry.lock
  • tests/dependency-reputation/fixtures/head/requirements.txt
  • tests/dependency-reputation/fixtures/head/uv.lock
  • tests/dependency-reputation/fixtures/head/yarn.lock

ms280690 and others added 3 commits October 11, 2026 18:33
Dependency Review resolved lodash and moment in the recorded lockfiles and
blocked on their advisories. The differ only needs names and versions, so
use names no registry has, as the syft fixture already does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPH9145e4gFo6bmXvMgBoF
Dependency Review resolved left-pad to its WTFPL licence, which the
allow-list rejects. The fixture only needs a name and a version.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPH9145e4gFo6bmXvMgBoF
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