Commit Graph
101 Commits
Author SHA1 Message Date
Alex Goodman c38a68e9de fix: hold archive chains to the same bounds when scanning and decoding
Decoding SPDX, CycloneDX and syft-json rebuilt nested archive chains from whatever the document said, with no checks on entry names, depth or length. A small crafted document could forge archive boundaries or cost memory quadratic in its size (a 3 MB SPDX allocated ~14 GB).

- decoders now hold names to the scan's `EntryName` rules, and chains to `MaxDepth` (16) and PATH_MAX in length
- a file within a refused chain is dropped, rather than moved to a top-level path or merged into its outer archive
- the scan holds itself to the same bounds, so its SBOMs always decode back: a configured `nested-archive-max-depth` past 16 stops at 16, and an entry whose chain would be too long is skipped and the archive reported as truncated

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-10-29 15:50:03 -04:00
Keith Zantow 851dc327c5 fix: file selection within archives, spdx / cyclonedx file representation
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2026-10-27 14:52:18 -04:00
Keith Zantow 3149fffada fix: do not use AccessPath / Location.Path() except in special cases
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2026-10-22 10:17:02 -04:00
Alex Goodman c4c0907d4e fix: keep panic stacks out of archive unknowns
A recovered panic while cataloging an archive became an unknown whose reason carried the full
goroutine stack, so a crafted archive that panicked a decoder put kilobytes of stack and build paths
into the published SBOM.

- the reason is now just `panic while cataloging archive: <value>`
- the stack is logged at debug, matching `runSubTaskSafely`

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-10-21 11:42:23 -04:00
Keith Zantow a1f7c52d89 fix: unknowns, better full vs local path handling
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2026-10-20 11:15:17 -04:00
Keith Zantow 3e4b036e22 fix: keep RealPath as top-level, use FullPath and utility functions FullNestedPath, LocalPath, Path
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2026-10-19 15:44:37 -04:00
Keith Zantow 702d7d6100 chore: update failing tests
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-10-08 13:16:42 -04:00
Keith Zantow fda2fe4fcc chore: archive memory and disk limits of 0 mean 0
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-09-30 15:57:48 -04:00
Keith Zantow d95abbf6b5 chore: truncation reason to error type
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-09-30 15:52:45 -04:00
Keith Zantow b2942743a5 Merge remote-tracking branch 'upstream/main' into add-nested-archive-cataloging
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-09-30 15:31:47 -04:00
Keith Zantow 12d3097741 Merge remote-tracking branch 'upstream/main' into add-nested-archive-cataloging
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-09-30 14:55:38 -04:00
Alex Goodman 8d5567c423 feat: catalog CPAN distributions installed by perl clients (#5131)
* feat: catalog CPAN distributions installed by perl clients

Adds `perl` as a language and `cpan` as a package type, with two catalogers behind them.

- `perl-cpan-installed-cataloger` reads `.meta/*/install.json` (cpanm, cpm, carton) and `auto/**/.packlist` (anything installed through `ExtUtils::MakeMaker` or `Module::Build`, including CPAN.pm). Both globs are unanchored, so a local-lib or carton application tree is found the same as a system install.
- `perl-cpan-meta-cataloger` reads an unpacked release's own `META.json` or `META.yml`, gated on a sibling `MANIFEST` so source checkouts are ignored.

Packages are keyed on the **distribution**, not the module, because that is what CPAN, MetaCPAN and the advisory data all use. `LWP.pm` belongs to `libwww-perl` and reporting it as `LWP` would make every advisory for it unreachable. The distribution name comes from `install.json`'s `dist` field, and from the `auto/` path for packlists.

purls are `pkg:cpan/<distribution>@<version>`, with the PAUSE author added as an `author` qualifier when the evidence carries it. Metadata comes in two types: `cpan-distribution` for installed evidence and `cpan-unpacked-release` for a release sitting on disk. The tiers differ in more than a name, so a consumer should not have to string-match a cataloger name to tell them apart: an unpacked release has no PAUSE path and therefore no author and no file list, and "installed and loadable by the interpreter" is a materially stronger claim than "a source tree exists here".

A packlist's version comes from `perllocal.pod`. EUMM writes it and the packlist from the same variables in the same install target, so the `auto/` path segments and the perllocal `Module` name are the same key, and the recorded `VERSION` is what was evaluated at build time rather than what can be read back statically. Scraping `$VERSION` out of the main `.pm` is the fallback, since `NO_PERLLOCAL` suppresses the file and Module::Build never writes one. Three rules pick the stanza: dashed module name, longest `installed into` libdir that prefixes the packlist path, and last match wins because the file is append-only. Without the libdir rule a second perl on the image silently supplies the version.

Where scraping is the fallback, it reads more than a plain `our $VERSION = '...'`. A version declared in the package statement (`package Foo::Bar v1.0.0;`) counts, which matters because a distribution can declare it that way and carry no `$VERSION` at all: `CPAN::02Packages::Search` is one, and without this it reports no version and matches nothing. Fully qualified `$Foo::Bar::VERSION` counts too, which is what older Dist::Zilla emitted and what real `JSON::PP` 2.27300 still carries. `qv('1.2.3')` is handled. A version computed at runtime is not, and those are reported without one rather than guessed at.

Packlist entries are parsed the way `ExtUtils::Packlist` writes them: a line can carry space-separated metadata after the path (`/path/to/File.pm type=file`), which is what `installperl` produces, so the suffix is stripped rather than the line being cut at its first space.

`META.yml` is read alongside `META.json`, because about 43% of current CPAN releases ship no `META.json` and they skew old, which is where the advisories are. Where both sit in one directory the `META.json` wins. A `META.yml` a strict parser rejects skips that directory rather than failing the scan, which is routine rather than defensive for pre-spec releases.

A packlist is literally a file list, so its paths are surfaced through `pkg.FileOwner`. They are reported as recorded, unfiltered: a path the packlist claims and the filesystem lacks means the file was removed or overwritten out from under the installer, which is worth seeing rather than hiding.

Build leftovers under `~/.cpanm/work` and `~/.cpan/build` are skipped. They genuinely are unpacked release tarballs, `MANIFEST` included, so the `MANIFEST` gate admits them and a path exclusion is the only signal available. Without it every distribution on an image that did not clean up is reported twice. The cost is that a tarball deliberately kept under `~/.cpan/build` stops being reported.

Two behaviors that look wrong but are not:

- a distribution can be reported twice at different versions. `libwww-perl` 5.836 bundles `HTTP-Date`, `HTTP-Message` and `LWP-MediaTypes`, and installing it over the modern standalone releases overwrites their `.pm` files. Both versions are genuinely present, so the merge refuses to pair disagreeing versions rather than hiding one.
- a distribution with no readable version is reported without one rather than dropped, so it stays visible.

The coverage boundary is stated in full in the `package perl` doc comment. In short: modules installed from distro packages are out of scope, since packagers strip CPAN metadata with `NO_PACKLIST` and deb, rpm and apk already report them. Core and dual-life distributions bundled with the interpreter have no coverage, because nothing on disk carries their versions; the interpreter itself is reported separately. Vendored trees, `App::FatPacker` output and PAR archives are invisible, because what they carry is module identity with no offline map to a distribution. A packlist-derived name is the installer's `NAME` and may not be the distribution name, which is left to the vulnerability data to resolve.

One correction worth calling out, since it is easy to arrive at twice: a sibling `MANIFEST` is the only thing separating an unpacked release from a source checkout. An earlier version of the guard also rejected any tree containing a `dist.ini`, on the theory that it marked a Dist::Zilla source tree. dzil ships `dist.ini` *inside* the tarballs it builds and lists it in the generated `MANIFEST`, so that exclusion was silently skipping real releases, `URI` among them.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* test(cli): bump coverage image package count for the new perl fixture

The CPAN fixture added to `image-pkg-coverage` (`URI-5.35`) is shared with the CLI suite through a symlink, so the squashed package count goes from 42 to 43.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix(perl): take CPAN distribution name and version from install.json dist

cpanm writes the main module's `$VERSION` into `version` and the release distvname into `dist`, and the two often disagree (`Carp-Assert-More-2.9.0` records `2.009000`). Trimming `version` off `dist` failed on those, so the whole distvname became the package name, and the module version never paired with the packlist record for the same install, which reported the distribution twice.

- name and version are now split out of `dist` at the last `-` followed by a version, as CPAN::DistnameInfo does
- a `-TRIAL` suffix is dropped, so `Try-Tiny-0.26-TRIAL` reports as `Try-Tiny` `0.26`
- the PAUSE path fallback uses the same split

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-30 14:15:05 -04:00
Alex Goodman 10af8342c0 fix: don't fail the whole SBOM when a cataloger panics on one file (#5342)
* fix(generic): recover from parser and processor panics

- a panic while parsing one file becomes an unknown for that location instead of failing the whole SBOM
- a panic in a package processor is logged as a warning and the unprocessed results are kept
- stacks go to the trace log, not into the unknown text

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix(unknown): keep errors that unwrap to nil

`sync.PanicError` with a non-error panic value (e.g. `panic("boom")`) unwraps to nil, and was being dropped entirely from the error graph instead of being kept as a leaf.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix(task): don't put the stack trace in task panic errors

Task panics are still fatal, but the error now reads `panic in task "<name>": <value>` and the stack goes to the debug log.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* test(generic): cover chained processors when a later one panics

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix(file): recover from panics in the executable and file digest catalogers

A panic while reading one file is now recorded as an unknown for that file instead of failing the whole SBOM, the same as generic catalogers.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-29 09:21:03 -04:00
Alex Goodman 22edfe66ca fix: link nested java packages to their enclosing jar when nested cataloging is on
the legacy recursion links a nested jar to the jar that holds it: a `DEPENDENCY_OF` edge from inner to outer, and `JavaArchive.Parent` on the inner package. Inside an extracted archive java called `parse(ctx, nil)`, so both went away as soon as the feature was on. What replaced them was `file CONTAINS package`, which SPDX and CycloneDX drop, so those formats lost all war-to-jar structure.

- `archive.Traversal` gains `Parent` and `Packages` (the packages found describing that archive, filled in by the task after its sub-pipeline runs)
- java picks the enclosing jar's main package from the parent traversal (the one whose virtual path is the archive's own; pom-derived aux packages carry a suffixed one) and passes it to `parse`, then sets `Parent` the same way the legacy path does

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 13:36:52 -04:00
Alex Goodman 23de18918e fix: run root file catalogers after the archive task with owned-by-package selection
with nested cataloging on, java leaves root-level archives to the archive task, so a root `app.jar` package only exists once that task has run. With the default `FilesOwnedByPackageSelection` the root file catalogers ran in an earlier group, never saw the package, and `app.jar` got no file metadata or digests. It did get them with the feature off.

- in owned-by-package mode the groups are now packages, then the archive task, then the root file tasks. Other modes are unchanged
- the file tasks merge their results into the SBOM instead of replacing the maps, since the archive task has already written nested files into them

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 13:34:09 -04:00
Alex Goodman 9d820c6d94 fix: only look up owned-by-package files in the resolver's own frame
with `FilesOwnedByPackageSelection` the file catalogers take every package location in the SBOM and look it up by `RealPath` in the resolver they were given. Inside an archive, the java package's location is the archive itself *in its parent's frame* (`WEB-INF/lib/dep.jar`), so the sub-pipeline looked that path up inside `dep.jar`'s own resolver: a miss, or an unrelated same-named entry by coincidence. At the root, coordinates from inside archives were looked up against the scan root the same way.

`coordinatesForSelection` now keeps only coordinates whose `ArchivePath` matches the current frame (the traversal's `ContentsArchivePath()`, or blank at the root).

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 13:30:33 -04:00
Alex Goodman 0152e5b59c fix: a damaged entry truncates the archive instead of failing it
a read error while copying one entry (a zip CRC mismatch, a corrupt deflate stream) was returned from `add`. That aborted the walk, and `Extract` threw away every entry already stored. So a large war with one damaged, irrelevant entry produced zero packages with the feature on, while java's legacy path (which reads only the entries it needs) still cataloged it.

- a read error on one entry now drops that entry and marks the resolver truncated (`entry "x" could not be read: ...`), and the walk continues
- if the stream itself breaks partway (a truncated `.tar.gz`), whatever was read before the break is kept and the archive is truncated. With nothing read it is still an error, as before
- disk limit and decompression budget errors still stop the walk

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 13:28:53 -04:00
Alex Goodman 14bae1a0d9 fix: emit archive-to-archive CONTAINS edges and drop self-loops
the archive's `CONTAINS` edges were built from every coordinate in the sub-pipeline's scratch SBOM, which gets one of two things wrong:
- with the default `FilesOwnedByPackageSelection`, nothing records the nested archives as files, so the archive-to-archive chain was missing and grandchild packages hung off coordinates with no incoming edge
- the scratch SBOM also holds coordinates from the parent's frame, most notably unknowns recorded at the archive's own coordinates (e.g. a jar with no manifest). Those turned into `x.jar CONTAINS x.jar`

edges now go to the nested archives found in it (always, whatever the file selection), plus coordinates whose `ArchivePath` is this archive's own chain, i.e. files that are actually inside it. The walk reuses that one discovery pass for the recursion.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 13:26:59 -04:00
Alex Goodman fe4fdc786c fix: report archives left unexplored at the nested depth limit
with nested cataloging on, java stops recursing into jars itself (the task owns recursion) and its own "nested archives not cataloged" unknown is suppressed. The task then just returned at the depth bound. So `MaxDepth: 1` on a war silently found fewer jars than leaving the feature off, and nothing in the SBOM said so.

at the bound, every archive that sits there (by content sniff) is now recorded as a "nested archive not cataloged: the nested archive depth limit was reached" unknown. The CLI description for `nested-archive-max-depth` notes that it replaces java's unbounded jar-in-jar recursion.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 13:24:29 -04:00
Alex Goodman 81ee189bf4 fix: bound total decompression under each top-level archive
the limiter bounds what's held *at once*, and each archive gives its bytes back when it's released. So a recursive bomb (42.zip shape) never trips a limit: every level fits on its own, and the scan just runs for effectively forever. Capping each archive at N× its own size wouldn't help either, since every level of such a bomb is high-ratio, so the work still grows about N-fold per level.

- each top-level archive gets one decompression budget of `max(100 × its size, 1 GiB)`, spent by every archive nested under it at any depth
- the budget is attached to the context when the walk enters a top-level archive, so `Extract` picks it up without a signature change
- once it's spent, the archive being extracted is truncated with a "possible decompression bomb" unknown and the walk moves on. The next top-level archive starts fresh

real trees (a war of jars, a layer of tarballs) expand a few times over, well under the ratio.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 13:23:32 -04:00
Alex Goodman d27b6ebb1b fix: cap each extracted archive entry at 2 GB
`put` had no per-entry cap, unlike the legacy java path which capped every file at 2 GB through `intFile.SafeCopy`. At depth 1, one entry of an overlapping-entry zip bomb could decompress all the way to the 100 GB disk limit before anything stopped it.

- entries are now read through the same 2 GB cap (`intFile.PerFileReadLimit`, now exported). An entry over it is dropped after cap+1 bytes and the rest of the archive is still extracted
- `Resolver` gains `TruncatedReason`, so the truncation unknown says what happened ("an entry larger than 2.0 GiB was skipped", or the existing disk-limit text) instead of always blaming the limits

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 13:21:08 -04:00
Alex Goodman 27655c2be0 fix: bound archive recursion with a cycle guard and depth ceiling
a negative `MaxDepth` really was unbounded, and nothing noticed an archive nested inside a copy of itself. A zip quine at `-1` recursed until memory, disk or file descriptors ran out, running the full sub-pipeline at every level.

- the walk keeps a stack of the digests of the archives it's inside, and an archive identical to one of them is recorded as an unknown instead of being entered
- negative depth now stops at 16 levels (docs and CLI description updated)
- cancellation is checked between candidates, so a cancelled scan stops walking instead of finishing the archive tree

the three unknown-recording blocks in `processArchive` became a one-line helper to stay under `funlen`.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 11:32:15 -04:00
Alex Goodman c9b4f9c085 fix: recover from panics while extracting an archive
sub-pipeline catalogers were already run under `runTaskSafely`, but extraction wasn't: the zip, tar and compressor decoders run on untrusted bytes, and a panic in one unwound the whole walk and failed `CreateSBOM` with "failed to run tasks".

- `processArchive` recovers and returns the panic (with its stack) as an error at the archive's coordinates, so it becomes an unknown and the sibling archives are still cataloged
- `Extract` now defers `Cleanup` on failure instead of calling it on each error path, so a panic no longer leaks the limiter charge or the spill file

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 11:28:26 -04:00
Alex Goodman f5bac4a026 fix: build ArchivePath from real paths, not access paths
each `ArchivePath` segment came from `loc.Path()`, so it was the link path when an archive was reached through a symlink and the real path otherwise. That depended on how discovery happened to find the archive. The package location said `store/3f9a1c` while the files inside the same jar were recorded under `...:app/lib/json-simple-1.1.1.jar`, so a consumer couldn't join a package to its files by prefix.

The chain for extracted files is now built from `RealPath`. `Traversal.Location` still carries the access path, so java's name check and `VirtualPath` metadata behave the same as before. The field comment and schema now say every segment has links resolved.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 11:26:38 -04:00
Alex Goodman 5fc384dddb fix: keep the access path of archives discovered through a link
`discoverArchives` collects MIME hits first, and those are bare real paths. When the glob pass then found the same file through a symlink, it was dropped as a duplicate along with its access path. Java decides whether to describe an archive by its name, so a content-addressed jar (`store/3f9a1c`, linked from `lib/json-simple-1.1.1.jar`) was extracted but produced no package. This is the pnpm / nix / bazel layout.

When deduping, the candidate now takes the first location that carries an access path.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 11:25:40 -04:00
Alex Goodman a4a1d7afa7 fix: treat zero archive limits as the default
`ArchiveSearchConfig{MaxDepth: 2}` is the natural literal, but zero memory and zero disk meant "forbid both", so every archive was truncated to nothing and only unknowns came out.

- `MaxMemoryBytes` / `MaxDiskBytes` of `0` now mean the default, negative is still unbounded
- the limiter keeps its own zero-forbids semantics internally; it's just no longer reachable from config
- tests that relied on zero to force spilling now pass `archive.Limits` directly, and the two "both limits zero" tests are gone since that config no longer exists

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 11:14:23 -04:00
Alex Goodman fe4a9a287a chore: use only the default title for archive progress
matches how the per-cataloger progress rows are titled (`Default` only), so the archive row reads like its siblings.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-24 11:11:36 -04:00
Keith Zantow b36234cfe7 feat: simplify+improve resolver implementation / glob search
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-09-22 11:32:30 -04:00
Keith Zantow 47cafae01b chore: simplify and cleanup
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-09-22 00:23:36 -04:00
Keith Zantow 53cd4254e4 chore: revert custom index in favor of key_Split
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-09-20 11:22:10 -04:00
Keith Zantow 245fc03887 Merge remote-tracking branch 'upstream/main' into add-nested-archive-cataloging 2026-09-10 13:32:07 -04:00
Keith Zantow 8c0d3747ce feat: initial recursive archive cataloging impl
Signed-off-by: Keith Zantow <keith.zantow@anchore.com>
2026-09-10 08:45:36 -04:00
Christopher Angelo PhillipsandAlex Goodman aff2c247db feat: add safe tensor model type to SBOM output (#4844)
---------
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-07-15 17:14:03 -04:00
gabandAlex Goodman 656a4d46d7 Vcpkg Cataloger (#4081)
* Vcpkg cataloger for vcpkg "Manifest Mode"

Find and parse vcpkg-lock.json to get HEAD commit hash

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* just use local vcpkg git repo if it exists, clone it if it doesn't

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* Config opt for git remote clones for vcpkg and README update

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>

* Look in vcpkg cache git repo for custom git repos

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add triplet to metadata and support overlay-ports from config file

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* Add PURL to packages (not sure if this is correct)

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* flatten structs in pkg module and move vcpkg structs to resolver

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* account for overriden versions in toplevel manifest

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* generate json schema for vcpkg metadata

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>

* test for basic vcpkg project

dependencies for vcpkg registry to be pulled in

add tree hashes and use correct git hash in builtin-baseline for helloworld test

vcpkg-registry for testing that uses object hashes from syft repo

fix broken tests

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>

* formatting

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>

* fix static-analysis violations

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix integration test failure

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>

* remove uneeded files from vcpkg test fixture and use custom registry

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>

* change vcpkg registry to anchore one

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* purl spec based on open PR

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* generate-json-schema

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* rebased and generate json schema 16.0.40

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>

* address low hanging fruit

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* handle additional comments

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* migrate to testdata

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* improve docs and testing

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix static analysis

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* remove license from pkg metadata

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix capabilities claim

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Gabriel Rau <gabetrau@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-07-01 09:11:33 -04:00
Rez MossandAlex Goodman 148fe572bc added macOS .app cataloger (#4490)
* added macOS .app cataloger, fixed #4010

Signed-off-by: Rez Moss <hi@rezmoss.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* added macOS .app cataloger, fixed #4010

Signed-off-by: Rez Moss <hi@rezmoss.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* added macOS .app cataloger, fixed #4010

Signed-off-by: Rez Moss <hi@rezmoss.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* address review comments

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* bump schema to 16.1.7

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* address static analysis failures

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* migrate to testdata

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* expand fields and improve test coverage

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Rez Moss <hi@rezmoss.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-06-30 10:32:57 -04:00
Rez MossandChristopher Phillips fea4a50124 feat: deno cataloger #4417 (#4523)
Signed-off-by: Rez Moss <hi@rezmoss.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2026-06-23 10:58:22 -04:00
MarcusandChristopher Phillips 908eb57890 feat: add .bpl extension to PE cataloger (#4954)
BPL (Borland Package Library) files are standard PE/DLL format used by
Delphi and C++Builder. Adding the extension to the glob list so syft
picks them up during directory scans without users needing to rename
to .dll first.
---------
Signed-off-by: jfjrh2014 <jfjrh2014@gmail.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2026-06-08 10:07:15 -04:00
b3c70da3ea Add experimental cataloger capabilities command (#4317)
* add info command from generated capabilities

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* correct gentoo and arch ecosystems

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* rename os pkg types

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* better binary cataloger description

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* expose metadata and pacakge types in json

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* expose json schema types

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add completeness tests for metadata types

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* latest generation

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix linting

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* improve testing a docs

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix tests and linting

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* restore goreleaser config

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* tweak diagram

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix pdm

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* chore: java binary data

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* new capability descriptions for gguf and python

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* correct poetry lock integrity hash claim

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix compile error

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix: remove purl version from overrides

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* fix lua deps ref

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* keep gguf as ai ecosystem

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* split packages.yaml to multiple files by go package

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* ensure tests do not use go test cache

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* sort json output for info command

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* docs: fix ocaml, php, and portage capabilities yaml

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* chore: update erlang capabilities

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* chore: update java capabilities

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* chore: update javascript capabilities

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* chore: update linux kernel capabilities

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* remove missing tests

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix package.yaml references

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* revert license list change

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* check for drift in capability descriptions

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* regenerate capabilities

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* test cleanup

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* use fixture cache in static analysis

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* claim fixtures pre-req for cap generation

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* update documentation with correct regeneration procedure

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* chore: ruby-gemspec-cataloger finds no dependencies

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* chore: fix python docs and config comment

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* chore: commit re-generated java yaml

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* add cataloger selection to caps command

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* re-generate cap yamls

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix tests for cataloger selection

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix cli test

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add missing tests

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix linting

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* rename cmd to `cataloger info`

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* [wip] change capability description locations

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* [wip] continued

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* [wip] adjust for import cycles

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* correct docs

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix linting

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Keith Zantow <kzantow@gmail.com>
Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>
Co-authored-by: Keith Zantow <kzantow@gmail.com>
Co-authored-by: Will Murphy <willmurphyscode@users.noreply.github.com>
2025-12-22 19:34:10 +00:00
VictorHuuandChristopher Phillips afe28a2fc0 fix:handle compound aliases like ``.tgz`` when cataloging archives (#4421)
---------
Signed-off-by: Yuntao Hu <victorhu493@gmail.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-12-02 16:55:32 -05:00
Kudryavcev Nikolay 89842bd2f6 chore: migrate syft to use mholt/archives instead of anchore fork (#4029)
---------
Signed-off-by: Kudryavcev Nikolay <kydry.nikolau@gmail.com>
Signed-off-by: Christopher Phillips <spiffcs@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-11-13 23:04:43 +00:00
Christopher Angelo Phillips 4a60c41f38 feat: 4184 gguf parser (ai artifact cataloger) part 1 (#4279)
---------
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-11-13 17:43:48 -05:00
Tim Olshansky bbef262b8f feat: Add license enrichment from pypi to python packages (#4295)
* feat: Add license enrichment from pypi to python packages
* Implement license caching and improve test coverage
---------
Signed-off-by: Tim Olshansky <456103+timols@users.noreply.github.com>
2025-11-06 16:05:08 -05:00
Alex Goodman e5711e9b42 Update CPE processing to use NVD API (#4332)
* update NVD CPE dictionary processor to use API

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* pass linting with exceptions

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-11-06 16:02:26 -05:00
Alan PopeandChristopher Phillips 0a36dabf23 feat(cataloger): add snap package cataloger for metadata extraction (#4151)
---------
Signed-off-by: Alan Pope <alan.pope@anchore.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-09-26 10:42:29 -04:00
Simeon StoykovandChristopher Phillips a433045d51 feat: basic Conda ecosystem support (#4002)
----------------------------------------------------------------
Signed-off-by: Simeon Stoykov <simeon.stoykov@quantco.com>
Signed-off-by: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-08-19 22:37:27 -04:00
Keith ZantowandAlex Goodman 02703d5c80 feat: RHEL EUS detection (#4023)
* feat: rhel eus detection

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* chore: update tests

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* chore: update more tests

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* rename feature detection functions

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Keith Zantow <kzantow@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-07-07 14:11:20 +00:00
Alex Goodman 2bda086423 Add ability to scan snaps (as a source) (#3929) 2025-06-25 16:53:35 -04:00
Alex Goodman e23ca43a83 add PE binary cataloger (#3911)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-05-19 14:17:09 -04:00
Christopher Angelo Phillips e1374f758e fix: update license content filtering default case to be 'none' for no content returned
---------
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-05-16 14:25:15 +00:00
Laurent GoderreandAlex Goodman a8e5b25632 Add PHP interpreter + extensions cataloger (#2585)
* Add PHP extensions binary classifiers

Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>

* [wip] add php extensions cataloger

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix linting

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* find interpreters + extension

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* internalize binary cataloger utilities

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* default to linux/amd64 for test fixtures

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-05-15 08:22:50 -04:00