feat(cli): nullify deps analyze — CI-aware dependency malware-analysis workflow#142
Open
tim-thacker-nullify wants to merge 4 commits into
Open
feat(cli): nullify deps analyze — CI-aware dependency malware-analysis workflow#142tim-thacker-nullify wants to merge 4 commits into
tim-thacker-nullify wants to merge 4 commits into
Conversation
…s workflow
Hand-written workflow command (not generated from OpenAPI) that wires
the Phase 5a/5b malware analyzer into customer CI pipelines via scpm's
/scpm/dependencies/analyze endpoint.
Components:
- internal/ci/ — extensible CI provider registry. Nine concrete
Providers: GitHubActions, GitLabCI, CircleCI, BitbucketPipelines,
Jenkins, AzureDevOps, GoogleCloudBuild, AWSCodeBuild, Local (last;
always matches). Each exposes Platform() (matches the
benchmarks.PipelinePlatform enum), Detect() (env-var signature),
BaseRef / HeadRef (context-aware; fall back to
`git rev-parse origin/HEAD` when CI doesn't expose a base),
PRNumber, RepoSlug, and EnrichHeader (stamps CI metadata on outbound
HTTP so scpm's audit log can tie back to the CI run).
- internal/scan/manifest/ — per-ecosystem lockfile parsers:
npm (package-lock.json v2/v3), pypi (requirements.txt), go (go.sum),
rust (Cargo.lock), ruby (Gemfile.lock). Each implements Parser and is
registered in manifest.DefaultParsers(). Deliberately tight:
pnpm-lock, poetry.lock, pom.xml, composer.lock, packages.lock.json
are follow-up work. Every parser produces the same flat Entry
(Ecosystem, Name, Version, File, Direct) shape so diff.go can
compare them uniformly.
- internal/scan/diff.go — the (base, head) diff. Uses
`git diff --name-only base..head` to list changed files, filters to
those a parser matches, then `git show <ref>:<path>` on each side +
parse + set-difference. Produces ChangedDep{added, bumped, removed}.
- internal/commands/deps_analyze.go — the cobra command. Flow:
1. Detect CI provider; resolve base (--base or provider.BaseRef)
and head (--head or provider.HeadRef) to commit SHAs.
2. scan.Diff → list of changed deps.
3. For each added/bumped dep, POST to
{client.BaseURL}/scpm/dependencies/analyze with the CI-provider
headers + an idempotency key derived from CI run ID + package
tuple (so re-runs of the same CI build hit cached jobs).
4. Render results as text (default) or json.
5. Exit per --fail-on (none|vulnerable|suspicious|malicious):
0=clean, 10=vulnerable, 20=suspicious, 30=malicious, 2=invalid
invocation, 1=transient.
The scpm calls are hand-rolled HTTP POSTs rather than generated
api.Client methods because scpm's OpenAPI regen happens in a separate
pipeline — the CLI's scripts/generate/main.go will supersede these
once the spec lands. Follows the RegisterContextPushCommand pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e646727 to
65ffb1c
Compare
golangci-lint v2.12.0 gofmt flagged the space-indented env-var tables in the AWS CodeBuild / Azure DevOps / Bitbucket provider doc comments; reflow to the Go 1.19 preformatted form (blank // + tab indent). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reflow the rest of the CI-provider doc-comment tables to Go 1.19 preformatted form, and fix const/var/struct-tag alignment in deps_analyze.go and npm_lock.go. golangci-lint caps gofmt reports at 3 per run, so these surfaced only after the first batch was fixed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Member
Author
|
Refreshed this PR to merge-ready:
|
Addresses review of the deps-analyze workflow.
Blockers:
- Wire ExitCodeFromError in main.go so the severity exit codes
(10/20/30) actually fire — previously every result exited 1, so the
CI merge-gate was inert. Set SilenceUsage so a verdict failure doesn't
print cobra usage.
- Fix --fail-on=none, which always exited 10: checkFailOn now treats a
zero-rank threshold as "never fail".
Correctness:
- renderResults no longer index-zips two parallel slices (a mid-list
analyze failure misattributed verdicts to the wrong package and
dropped the tail). One analyzedDep{dep,resp,err} entry per dep now.
- Unknown/unrecognised non-empty verdicts fail closed: warn and treat as
malicious so a server-side rename can't silently bypass the gate.
- Provider BaseRef/HeadRef + resolveRef take repoPath and set cmd.Dir,
so --repo is honoured (ref resolution no longer runs in the CWD).
Feature:
- Implement --wait (was parsed but unused): poll by re-POSTing the
idempotent analyze request until the job is terminal or --wait-timeout
elapses; adds --wait-timeout/--wait-interval. An incomplete analysis
now exits transiently (1) instead of greenlighting the merge.
Cleanup:
- Typed enums replace magic strings: ci.Platform, scan.ChangeKind,
manifest.Ecosystem, commands.Verdict.
- Remove the `var _ = fmt.Sprintf` hack and the //nolint:errcheck.
- Correct the doc comments that claimed a benchmarks.PipelinePlatform
enum and a `make lint-ci-providers` target that don't exist.
- Fix the misleading idempotency-key comment; handle SSH repo URLs in
AWSCodeBuild.RepoSlug; note fetch-depth:0 for GitHub push diffs.
Tests:
- Add unit tests for the five lockfile parsers, diffEntries, CI provider
detection/parsing, and the verdict/gate/render/wait/exit-code logic.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Related
Depends on monorepo PR https://github.com/Nullify-Platform/nullify/pull/2280 for the scpm endpoints (`/scpm/dependencies/analyze`, `/scpm/dependencies/query/batch`, `/scpm/containers/analyze`) and the `vuln-database` service those endpoints fan out to.
Test plan
🤖 Generated with Claude Code