Commit 652294a
deps: remove fanal framework, call Trivy parsers directly (#2476)
* test: add golden tests for AnalyzeLibrary
Add golden tests that snapshot the output of AnalyzeLibrary() for all 35
lockfile fixtures in integration/data/lockfile/. This establishes a
regression baseline before refactoring the Trivy fanal integration.
- Covers all supported languages: npm, yarn, pnpm, bun, pip, pipenv,
poetry, uv, bundler, cargo, composer, go mod/sum/binary, pom.xml,
gradle, JAR/WAR, NuGet, conan, pubspec, mix, cocoapods, swift
- Results are sorted by name+version for deterministic comparison
- Run with -update flag to regenerate: go test ./scanner/... -args -update
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: extract file-to-parser dispatch function
Extract detectParserType() that maps file paths to parser types,
replicating the logic of each Trivy fanal analyzer's Required() method.
This is a preparatory step for removing the fanal framework dependency.
No changes to existing behavior — the function is not yet called from
production code.
Covers all edge cases:
- node_modules/ and .yarn/ exclusions for npm/yarn/pnpm
- Case-insensitive matching for .NET packages.props and JAR extensions
- Suffix matching for gradle.lockfile and .deps.json
- Executable filemode detection for Go/Rust binaries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* deps: remove fanal framework, call Trivy parsers directly
Replace the Trivy fanal analyzer framework with direct calls to
dependency parsers, eliminating the IaC/misconf package tree that was
pulled in transitively.
Changes:
- Rewrite AnalyzeLibrary() to use detectParserType() + direct parser calls
- Remove all fanal blank imports (25+ analyzer registrations)
- Remove fanal analyzer framework usage (NewAnalyzerGroup, AnalyzeFile, etc.)
- Simplify JAR parser to standalone function, removing fanal PostAnalyzer
- Remove DummyFileInfo (no longer needed)
Scanner-only binary: 191 MB -> 46 MB (-76%)
Trivy deps: 352 -> 144 (-59%)
misconf packages: 1 -> 0
All golden tests pass. Both scanner-only and full builds verified.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: fix goimports formatting and go mod tidy
- Fix goimports formatting in scanner/base.go, dispatch.go, dispatch_test.go
- golang.org/x/sync moved from direct to indirect (errgroup no longer used)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: address Copilot review on golden tests
- Skip test when integration/ submodule is not checked out (t.Skip with
instructions to init submodule)
- Use filepath.ToSlash for cross-platform golden file naming
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: copy text fixtures to testdata for CI compatibility
Copy lockfile fixtures from integration submodule to scanner/testdata/fixtures/
so golden tests run in CI without requiring submodule checkout.
Binary fixtures (JAR, WAR, Go/Rust binaries) remain in the integration
submodule and are skipped when not available.
CI coverage: 29/34 tests run (5 binary fixtures skipped)
Local coverage: 34/34 tests run (with submodule initialized)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: force-add requirements.txt ignored by *.txt gitignore
The repo-level .gitignore has *.txt which prevented requirements.txt
from being committed. Use git add -f to override.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review on PR #2476
- Return parse errors from AnalyzeLibrary instead of silently swallowing
them. Caller (scanLibraries) logs warning and continues to next file.
- Use io.SeekEnd/io.SeekStart instead of magic numbers in JAR parser.
- Golden test treats parse errors as empty result (matches production
behavior where scanLibraries warns and continues).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review round 2 on PR #2476
- Remove unused parserRustBinary constant (dispatch returns parserGoBinary
for all executables, language determined at parse time)
- Make suffix-based dispatch case-insensitive (.deps.json, gradle.lockfile)
for cross-platform compatibility
- Aggregate parse errors into l.warns so they surface in scan results
- Remove unused fanal blank imports from golden test file
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review round 3
- Collect parse errors in l.errs (ScanResult.Errors) with comments
- Rename parserGoBinary to parserExecutable (value "executable")
- Add expectParseError to golden test entries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add diff-lockfile for A/B regression testing
Add scripts/compare-lockfile.go and scripts/lockfile-fixtures.json for
comparing AnalyzeLibrary output between Git refs using real-world
lockfiles from popular OSS projects.
17 fixtures: npm, yarn, pnpm, pip, pipenv, poetry, bundler, cargo,
composer, go.mod, pom.xml, mix, swift, JAR (x2), Go binary, Rust binary
Supports tar.gz extraction for binary fixtures and custom filemodes.
Add diff-lockfile target to GNUmakefile:
make diff-lockfile # compare against master
make diff-lockfile BASE=commit # compare against specific ref
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: gitignore compare-lockfile binary
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add scripts/README.md for diff-lockfile usage
Document when and how to run the lockfile regression test.
Also gitignore the compare-lockfile binary.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review round 4 on PR #2476
scanner/base.go:
- Add Rust binary error types (ErrUnrecognizedExe, ErrNonRustBinary)
to parseBinary suppression list
- Wrap parse errors with file path context in l.errs
scripts/compare-lockfile.go:
- Fix file header (compare-analyze.go -> compare-lockfile.go)
- Add HTTP client timeout (5 min)
- Remove dead code in base runner safe variable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: update fixtures to non-zero libs and fix docs
Fixtures:
- pip: home-assistant/core (43 libs, was django 0 libs)
- pom: apache/spark (2 libs, was apache/maven 0 libs)
- rustbinary: cargo-bins/cargo-binstall (399 libs, built with
cargo-auditable, was sharkdp/fd 0 libs)
- Fix .tgz archive extraction
scanner/base.go:
- Add Rust binary error types to parseBinary suppression
- Wrap parse errors with file path context
scripts/compare-lockfile.go:
- Fix file header, add HTTP timeout, remove dead code, support .tgz
Update scripts/README.md and PR description to match current fixtures.
Result: 17/17 IDENTICAL across 7,194 libraries, all non-zero.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: surface all filesystem errors in compare-lockfile
- Check copyFile return when copying fixtures to worktree
- Check MkdirAll and WriteFile for base_runner.go setup
- Fix MkdirAll error in copyFile itself
All errors now logged and cause runOnBase to return nil, which
triggers the skipped > 0 exit condition in main.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add complete sort tie-breakers and harden error handling
Add Dev field to sort comparators for deterministic ordering across
all normalize functions (main script, runner, golden test). Fix
os.MkdirAll error handling in main() and runner. Replace custom
replaceAll/indexOf with strings.ReplaceAll. Handle diff command errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: sort imports per gofmt and sanitize worktree path
- Reorder imports in base.go and compare-lockfile.go to match gofmt
conventions (stdlib alphabetical, then third-party groups)
- Sanitize baseRef in worktree directory name to handle branch names
containing slashes (e.g. feature/foo → feature_foo)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use MkdirTemp for worktree and handle result-counting errors
- Replace os.RemoveAll with os.MkdirTemp for worktree directory
creation to avoid path traversal risks from unsanitized baseRef
- Handle errors from os.ReadDir, os.ReadFile, and json.Unmarshal
in result-counting block so failures are diagnosable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: check os.Remove and worktree cleanup errors
Handle errors from os.Remove (temp dir removal before git worktree add)
and git worktree remove (deferred cleanup) to avoid silent failures.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use abspath instead of trivypath in error messages
Error messages in ScanResult.Errors are user-facing. Use the original
filesystem path (abspath) so users can locate the failing lockfile,
not the Trivy-internal cleaned path (trivypath).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: use workdir-relative path in README instead of hardcoded /tmp
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address remaining code quality issues
- Use io.SeekStart instead of magic number 0 in parseExecutableBinary
- Ensure parent directory exists in newLogger before creating log file
- Sanitize path separators and ".." in safeFilename (main and runner)
- Use http.StatusOK instead of magic number 200
- Use os.TempDir() for default workdir instead of hardcoded /tmp
- Return error from logger.close() instead of discarding it
- Include HTTP status text in fetch error messages
- Update README to use $TMPDIR instead of /tmp/diet-compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: fix result map key and add diff fallback
- Fix TrimSuffix to trim ".result.json" instead of ".json" so the
result map keys match safeFilename() output
- Use exec.LookPath to detect diff availability and fall back to
printing file paths when diff is not installed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: comprehensive code quality sweep
- Handle deferred log.close() error instead of discarding
- Fix io.Copy + defer Close pattern to not lose write errors
in fetchFixture and extractFromTarGz
- Add os.Args bounds check in generated runner
- Hoist strings.NewReplacer to package var (pathSanitizer)
and outside loop in runner
- Distinguish parse error from OK in log output (main + runner)
- Fix result map key to trim ".result.json" not ".json"
- Add diff command fallback when diff is not installed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add ComposerVendor dispatch and complete test coverage
Add installed.json (ComposerInstalledJson) to detectParserType as
parserComposerVendor, preventing regression from fanal removal.
Verified all FindLockFiles entries are covered by detectParserType.
- dispatch.go/base.go: add parserComposerVendor using same Composer
parser with ComposerVendor type
- dispatch_test.go: add installed.json test cases
- Golden test: add installed.json fixture and golden file
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add ComposerVendor dispatch, fix lint, use request context
- Add installed.json (ComposerInstalledJson) to detectParserType as
parserComposerVendor, preventing regression from fanal removal
- Fix goimports alignment in dispatch.go const block
- Use http.NewRequestWithContext in fetchFixture for cancellation support
- Add golden test fixture and dispatch test cases for installed.json
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: make diff-lockfile fetch optional via FETCH variable
Default FETCH=1 (download fixtures). Use FETCH=0 to re-run comparison
with cached fixtures, avoiding repeated network downloads during
development iterations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: fix README wording to match actual script behavior
The script generates a runner and executes it via go run, not a
separate build step.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: detect .exe and exclude non-regular files in isExecutable
Mimic Trivy's utils.IsExecutable: check .exe extension for Windows,
exclude directories/symlinks, then check Unix execute bits.
Fixes Windows .exe binaries not being scanned.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address review feedback (rename, typo, comments, unused arg)
- Rename diff-lockfile to compare-lockfile in GNUmakefile and README
- Fix typo: Text -> Test in analyze_golden_test.go
- Add comment explaining why lockfileParser is defined locally
- Remove unused fixtures parameter from runOnBase
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add security rationale for not using submodules in CI
Explain the concrete attack scenario (fork PR rewriting .gitmodules)
to document why binary fixture tests are local-only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: expand diff-lockfile to 129 fixtures, remove unused jar method
- Expand lockfile-fixtures.json from 17 to 129 entries (10 per ecosystem)
- Replace all 0-libs fixtures with projects that have actual dependencies
- pipenv reduced to 5 fixtures (Pipfile.lock is extremely rare in OSS)
- Add pom.xml online mode golden file for TestAnalyzeLibrary_PomOnline
- Remove unused properties.string() method in jar parser (Trivy fork code)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: add /compare-lockfile binary to .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: fix goimports alignment in dispatch_test.go
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: check IsRegular before .exe in isExecutable
Move non-regular file check before .exe extension check so that
directories/symlinks ending in .exe are excluded. Allow mode==0
for Windows compatibility (stat returns 0 permission bits).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: update fixture count in scripts/README.md (17 → 129)
* test: compare lib count instead of byte length in pom online test
* fix: unmarshal golden JSON as slice in PomOnline test
* fix: address MaineK00n review feedback
- Rename golden files: .golden.json → .json (redundant under testdata/golden/)
- Use cmp.Or for sort comparators in normalizeResult
- Switch on langType in parseBinary to isolate sentinel errors per language
- Wrap parseExecutableBinary errors with language name, symmetrize structure
- Simplify dispatch.go: inline filepath.Base in switch, use slices.Contains
- Extract base-runner.go from compare-lockfile.go via //go:embed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent b9ac2ff commit 652294a
File tree
81 files changed
+85412
-287
lines changed- scanner
- testdata
- fixtures
- conan-v1
- conan-v2
- npm-v1
- npm-v2
- npm-v3
- pnpm-v9
- pnpm
- poetry-v1
- poetry-v2
- golden
- trivy/jar
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
81 files changed
+85412
-287
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
| 27 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
241 | 242 | | |
242 | 243 | | |
243 | 244 | | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
244 | 256 | | |
245 | 257 | | |
246 | 258 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
62 | | - | |
63 | 62 | | |
64 | 63 | | |
65 | 64 | | |
| |||
347 | 346 | | |
348 | 347 | | |
349 | 348 | | |
| 349 | + | |
350 | 350 | | |
351 | 351 | | |
352 | 352 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
0 commit comments