Commit Graph
293 Commits
Author SHA1 Message Date
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
0bbcff1ae3 Fix hang when scanning a Java resource adapter (.rar) file (#5348)
* fix: scan a Java resource adapter (.rar) given as a file source

The file source picks an extractor for the scan target from its file name
alone. A Java resource adapter archive (JCA) uses the .rar extension but is
a zip file, so it was handed to the RAR extractor. With rardecode v2.2.0 the
RAR extractor does not return on non-RAR input (an infinite loop in its
signature search), so `syft scan --from file adapter.rar` never finished.
The same bytes named .jar scan in under a second.

When the name says RAR but the content is a zip archive, leave the file
unextracted, the same way .jar, .war and .ear scan targets are handled. The
java cataloger already reads .rar files (anchore/syft#4136) and now finds the
resource adapter and its nested jars. Real RAR archives are still extracted.

Signed-off-by: Ismael Donmez <ismael.donmez@chainguard.dev>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(deps): bump github.com/nwaples/rardecode/v2 from 2.2.0 to 2.4.1

rardecode v2.2.0 loops forever in its RAR signature search when the input
does not start with a RAR signature (fixed upstream in nwaples/rardecode
f501ac8, "fix infinite loop in findSig", released in v2.2.2). syft reaches
that search for any file source whose name contains ".rar", so a scan of a
self-extracting RAR, or of any other file with such a name, never finished.
With v2.4.1 a self-extracting RAR is extracted, and a file that is not a RAR
archive fails fast with "rardecode: RAR signature not found", the same way a
file named .zip that is not a zip archive fails today.

github.com/mholt/archives v0.1.5 (the latest release) still requires v2.2.0,
so the newer version is selected here.

Signed-off-by: Ismael Donmez <ismael.donmez@chainguard.dev>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: clarify the .rar zip log line and cover self-extracting RAR sources

- the debug line no longer calls every `.rar`-named zip a resource adapter
- a self-extracting RAR (stub before the signature) given as a file source is
  still extracted

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

---------

Signed-off-by: Ismael Donmez <ismael.donmez@chainguard.dev>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-30 15:54:36 +00:00
Alex Goodman d0e1e7be05 Harden cataloger parsers against truncated input (do not panic) (#5355)
* fix(javascript): don't panic on a yarn v1 lockfile line missing its value

A v1 `yarn.lock` dependency line without a version constraint, or a
`version`/`resolved`/`integrity` line without a value, indexed past the end of
the split line. Such dependencies are now skipped and empty fields left empty.

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

* fix(alpine): don't panic on an apk db ACL or checksum line before its entry

An `M:`, `a:` or `Z:` line that comes before any directory or file entry in
`lib/apk/db/installed` indexed `files[-1]`. Such a line is now skipped.

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

* fix(erlang): don't panic on a truncated rebar.lock or .app file

The term parser read past the end of the input when a file ended mid-term:
whitespace only, an unclosed list, a lone `<`, or a comment ending in `\r`.
These now return an "unexpected end of input" error.

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

* fix(lua): don't panic on a truncated .rockspec

The rockspec parser read past the end of the input when a file ended mid-statement:
a lone `[`, an unclosed `[[...]]` value or `[...]` index, or a `local` assignment cut off
before its `=`, value, or line end. These now return an "unexpected end of input" error.

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

* fix(swift): don't panic on a Podfile.lock pod without a version

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

* fix(gentoo): don't panic on a short obj line in portage CONTENTS

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

* fix(spdx): don't panic on an opam checksum without an algorithm

The opam cataloger stores checksums verbatim, so a malformed one reached the SPDX encoder and panicked there, outside the cataloger's recover. Checksums without an `=` are now skipped.

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

* refactor: use strings.Cut where a split was only indexed after a Contains check

Also guards `windows.FromPosix` against a path with no separator.

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

* test: guard untyped package metadata fields

- new `any`-typed metadata fields must be allowlisted with a reason
- allowlisted untyped fields are pushed through `SetID` and every encoder with
  non-finite, deeply nested and large values

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

* test: fuzz every generic cataloger parser

One fuzz target over every glob-selected parser in the capabilities data, run
through its cataloger task. Each input must not panic, must finish in time and
must keep allocations proportional to its size. Seeds come from each parser's
testdata plus the string literals in its package.

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

* test: scan malformed inputs under memory and time limits

A directory of small malformed files (deep nesting, oversized declared counts,
truncation, type mismatches, non-finite floats) is scanned by the CLI with a
memory limit and an RSS ceiling. The scan must exit 0 and write an SBOM.

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

* test: stop a fuzz input once its live heap passes the allocation limit

The allocation check only ran after the parser returned, so an input on its way to exhausting memory ran the machine into swap first. The harness now polls the live heap while the parser runs and panics past the same limit, which the fuzz engine saves as a crasher.

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

* fix: bound nesting depth and error context in the erlang and lua parsers

- a deeply nested rebar.lock or .rockspec overflowed the goroutine stack, which is fatal rather than a recoverable panic, so one file could take down the whole scan. Both parsers now stop at 1000 levels with an error.
- parse errors echoed whole input lines into the SBOM as unknowns, and lua appended another copy at every nesting level. `PrintError` now clips to a window around the error column, and lua decorates once at the top.
- the Podfile.lock error no longer echoes the pod entry.

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

* test: close ways the malformed-input checks could pass quietly

- a ctx-aware parser hitting the fuzz timeout now fails the input instead of racing the hard deadline
- the heap watchdog measures growth from a post-GC baseline rather than an absolute process-wide number
- a saved fuzz input naming a target that no longer exists fails instead of being skipped
- the CLI malformed-input scan fails on a recovered parser panic, not only on a non-zero exit

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-29 16:26:42 -04:00
Alex Goodman 3325493831 chore: pin the bounds from the unbounded allocation work (#5298)
* build(deps): bump go-make to v0.8.1

Picks up golangci-lint 2.13.2 (built with go1.27) in place of 2.11.4 (go1.26).
The old build panics outright on a go1.27 GOROOT with "file requires newer Go
version go1.27", and an older mise-shim build fails the quieter way: it loses
type info and reports zero findings with exit 0, so a ruleguard run comes back
green without having evaluated anything.

Also folds in what the newer linter flags:

- `reflect.Ptr` -> `reflect.Pointer` in three files, applied by --fix
- `tw.CellFormatting{MergeMode: ...}` -> `tw.CellMerging{Mode: ...}` in the
  cataloger info table, for a staticcheck SA1019 deprecation

Note the deprecation text names `CellConfig.CellMerging.Mode`, but the field is
`CellConfig.Merging`; `CellMerging` is the type. That command path has no test
coverage, so the swap was checked by rendering the same hierarchical-merge table
both ways and diffing: byte identical.

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

* chore(lint): tune goconst for data tables

goconst got stricter in golangci-lint 2.13 and now counts strings in map
literals and struct fields, which lights up every lookup table in the repo. It
was already enabled, so this is main going red on a linter bump rather than
anything new in the tree: 101 findings, and the default threshold of 3 means a
vendor name appearing in three rows of a table reads as a magic constant.

Raising `min-occurrences` to 5 takes that to 14. The rest split by whether the
repeated string is data or an actual constant:

- `cpegenerate` is excluded by path. It maps artifact names to vendors,
  products, and maven group ids, and repeats strings 35, 83, even 293 times, so
  no threshold reaches it. Hoisting those would trade a readable table for
  indirection.
- the two SBOM fixture builders in `format/internal/testutil` get a
  function-level nolint each. The repeated names and versions are what the
  golden files assert against.
- `mysql-cluster` and `php` were genuine repeated literals and are now
  constants.

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

* chore(test): extract measureAlloc into a shared helper

The allocation-budget tests added during the unbounded allocation work grew a
copy of the same helper in every package they touched: four identical
`measureAlloc` definitions plus two more spelled out inline against
`runtime.MemStats`.

Now `testutils.MeasureAlloc`, at the repo root so `internal/spillbuf` can reach
it too. The doc comment carries the two things that were only recorded in some
of the copies: TotalAlloc is process-wide so callers must not use t.Parallel,
and a budget assertion only means something if the fixture would really blow
past it unguarded, so measure the unguarded path as well.

No behavior change, the body was identical in all six.

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

* chore(lint): add ruleguard rules for overflow and swallowed EOF

Two rules out of the recent unbounded allocation work (#5187, #5195, #5267,
#5291, #5292, #5293, #5294).

`noOverflowingBoundsCheck` flags `offset + size > limit` (and <, <=, >=) where
an operand is unsigned, neither addend is constant, and the operands are at
least 32 bits. Unsigned addition wraps, so an offset out of a file header can
carry the sum past the wrap point and pass a check it should have failed. The
fix is to subtract against the limit instead. Constant addends are excluded
because `pos+4 <= uint32(len(buf))` is the normal way to step a cursor, and the
32-bit floor drops nibbles widened for a comparison. Would have caught four
sites across #5195 and #5291.

`noSwallowedEOF` flags `return nil` / `return nil, nil` on an io.EOF check. The
caller gets a zero value it cannot tell from real data, and anything decoding a
fixed-size struct off it parses the padding as content. That is the shape behind
#5186.

Both decide from the expression alone, and writing the fix deletes the pattern,
so neither needs a suppression anywhere in the tree. That was the bar: rules for
the allocation and decompression classes were tried and dropped, because the
bound they look for lives in a preceding statement (or, for a decompressor
constructor, always downstream), so no correct implementation can silence them.
That would have meant ~15 permanent nolints on code that is already right. The
rules here that do work don't judge whether a bound exists, they route to a
wrapper that takes one: noDirectTempFiles, noDirectELFOpen.

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

* test: pin allocation budgets on the alpm, deb, and changelog bounds

The bounds added for #5292, #5293 and #5294 are asserted by the error they
return. That keeps passing if the bound is removed and something else rejects
the input later, which is the failure these were written for. Each of these
measures bytes instead, and proves the fixture is really a bomb first so a
fixture that quietly stops being one fails rather than passing.

- alpm mtree: 16MB of newlines, well inside the 64MB byte cap, costs 16.5GB
  uncapped against 238MB with maxMtreeLines. That 16.5GB is the measurement the
  line cap was added for and it was recorded only in the commit message. Note
  what the cap actually buys: 300k entries still cost a few hundred MB, per
  concurrent cataloger.
- deb members: 1.28GB against 392KB. Both arms read with io.ReadAll on purpose,
  since the stream itself never holds much whatever the cap says; what the cap
  protects is a consumer that buffers, and the real one is a tar reader building
  entries.
- snap changelog: 1.28GB against 175KB. This one has no explicit cap at all. It
  is held by bufio.Scanner refusing a token past MaxScanTokenSize, which is
  incidental, so switching to io.ReadAll or a bufio.Reader to pick up long lines
  would remove it silently.

Nothing added for the kernel module reader: its copy is already
io.Copy(tempFile, io.LimitReader(rc, max+1)), so peak disk is bounded by
construction and heap is streaming. A heap budget would assert the wrong
resource, and the three existing subtests cover the cap, at-cap fidelity, and
spill cleanup.

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

* test: pin allocation budgets on the ai and alpm byte caps

Follows the same pattern as the alpm line cap: measure bytes, and prove the
fixture is really a bomb first so one that quietly stops being a bomb fails
rather than passes.

- safetensors: 252MB against 2.6KB. The existing over-cap case deliberately
  omits the body, since the guard rejects on the declared length before reading
  anything. That is the right test for the guard but it would keep passing if
  the check moved after the read, so this one delivers the bytes.
- gguf: 268MB against 168MB. copyHeader io.Copy's whatever it is handed, so
  maxHeaderSize holds only because every caller wraps the reader first. This
  pins that the limit is where the bound lives, so dropping the wrapper at a
  call site fails here.
- alpm byte cap: 740MB against 132MB, the counterpart to the line cap budget.

Worth knowing for anyone writing the next one of these: a single enormous line
does not exercise the alpm byte cap. go-mtree runs its own bufio.Scanner and
refuses a token past 64KB, so that fixture fails as "token too long" before the
byte cap is consulted. The fixture here uses ordinary 1KB lines, enough of them
to pass 64MB while staying under the 300k line cap, so the byte cap is actually
the thing under test.

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

* test: assert bytes retained instead of allocated for gguf copyHeader

the bounded arm writes into a bytes.Buffer, whose doubling growth costs a
multiple of what it holds and lands on a different power of two depending on
the platform. it measured 168MB locally and 320MB on CI, past the budget.
buf.Len() states the same property deterministically.

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-17 14:11:16 -04:00
JuanandAlex Goodman e6d364437a feat(convert): passthrough-exact-format copies matching syft-json input unchanged (#5279)
* feat(convert): passthrough-exact-format copies matching syft-json input unchanged

When a syft-json input SBOM already exactly matches the requested output
format and schema version, `syft convert` can write the input bytes out
verbatim instead of decoding and re-encoding them. This avoids the lossy
round trip (and the associated cost) for callers that normalise SBOMs into
a target format without knowing up front whether the source already matches.

The behaviour is opt-in and configuration-only: it is enabled with
convert.passthrough-exact-format in the config file or the
SYFT_CONVERT_PASSTHROUGH_EXACT_FORMAT environment variable, and there is
deliberately no command-line flag, since it changes how every invocation in
a pipeline behaves rather than varying call by call. It defaults to off, so
existing behaviour is unchanged.

Pass-through applies only to syft-json input, and only when the document's
schema version is identical to the one this build of syft produces; any
other input is always converted. Outputs that do not match are still
converted, so a mixed set of `-o` values behaves as expected, and every
output is resolved and validated before anything is written. Pass-through
output is a byte-for-byte copy, so format options such as `format.pretty`
and `format.json.legacy` are not applied to it.

When the option is enabled a warning is logged stating so and noting the
syft-json-only scope, and a second warning is logged whenever an input is
found to match and the shortcut is actually taken.

The option lives under a `convert:` configuration section (options.Convert),
mirroring how attest scopes its own options. The description documents the
caveats above and notes that file-path input written with `-o <format>=<path>`
keeps memory minimal, whereas piped input or STDOUT output must hold the
whole document in memory.

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

* perf(convert): stream pass-through output instead of buffering the input

Identify, copy, and decode the input through a seekable reader rather than
loading the whole document into memory first. File inputs are read in place
and pass-through output is an io.Copy from the file. STDIN is used in place
when it is a redirected regular file. A pipe or terminal cannot seek, so its
contents are drained into an internal/spillbuf buffer: the first 1MB stays in
memory and the rest goes to a temp file under the user's TMPDIR (created
lazily, only when something actually spills), giving a seekable view without
ever holding the document in memory. The temp dir is rooted per invocation
via internal/tmpdir, honouring one already attached to the context, and is
removed when the command returns.

Writing pass-through output over the input file itself is now a no-op rather
than truncating the file before it is copied.

Measured on a 1GB syft-json document (Apple M1 Max), file in, file out:

  origin/main full re-encode      86.3s wall   99s CPU   12.0GB max RSS
  in-memory pass-through           7.4s wall  6.7s CPU    4.2GB max RSS
  streaming pass-through           7.0s wall  6.9s CPU    3.1GB max RSS

and the same 1GB document piped over STDIN with pass-through enabled:

  io.ReadAll into memory           1.3s wall  0.8s CPU    2.7GB max RSS
  spill buffer                     1.8s wall  1.0s CPU     66MB max RSS

The remaining cost of the streaming pass-through is entirely format.Identify,
which for syft-json decodes the whole document through a json.Decoder that
buffers the full value: measured alone it takes 7.1s and 3.1GB on the same
input. Reducing that further belongs to the format package.

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

* perf(syftjson): identify documents from their tail instead of a full parse

syft always writes the schema block as the last key of a syft-json document,
so the format and version can be read from the final bytes of the file. The
syft-json decoder's Identify now reads at most 2MB from the end of a seekable
input, finds the last "schema" key there, and verifies it sits directly within
the top-level object by scanning the remaining bytes for the single closing
brace of the document. Anything the tail cannot vouch for (non-seekable input,
a reordered document, a nested key) falls back to the existing full parse, so
behaviour is unchanged for documents the fast path declines.

The verification is position-independent: it also accepts documents whose
keys have been reordered so that other small keys follow schema. It rejects
nested schema objects, array-wrapped documents, truncated input, trailing
content, and schema text inside strings.

Supporting changes:
- the offset-aware reader the decoder collection hands to decoders now
  supports io.SeekEnd, which the tail read requires
- model.Document documents that Schema must remain its last field, and a
  test guards that the encoder writes it last in both compact and pretty
  output
- the decoder list documents that syft-json must stay first

Since Decode calls Identify before parsing, this also removes one of the two
full parses every syft-json conversion used to perform.

Measured on a 1GB syft-json document (Apple M1 Max), file in, file out:

  pass-through, previous commit     7.0s wall   6.9s CPU   3.1GB max RSS
  pass-through, this commit        0.85s wall  0.05s CPU    66MB max RSS
  full re-encode, previous commit  85.3s wall   99s CPU  11.5GB max RSS
  full re-encode, this commit      75.2s wall   91s CPU   9.9GB max RSS

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

* fix(syftjson): only identify from the tail when the document starts where the reader does

The tail scan vouched for the last 2MB, but nothing checked those bytes belonged to the
document the reader was pointed at. So `Identify` started claiming syft-json for files it
cannot decode: a document with a byte order mark or a stray log line in front of it, or a
syft document sitting after something else in the same stream, where `format.Decode` went
on to return an empty SBOM with a nil error.

Two O(1) checks:

- the first non-space byte at the reader's position has to be `{`
- `Decode` errors when the parsed document has no `schema.version`, instead of handing back
  the empty document it decoded into

Streams holding several concatenated documents are deliberately not detected. Proving there
is exactly one top-level value means reading all of it, which is the cost the tail path
exists to avoid, so `Identify` can still name a later document's version on such a file.
`Decode` reports what it actually parsed.

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

* fix(convert): recognize the input file by identity rather than by path

`convert - -o syft-json=sbom.json < sbom.json` truncated the file and exited 0. The
passthrough guard compared paths, and a shell redirect does not have one, so it was blind to
the one input mode where the truncation was silent.

`openConvertInput` now returns the input's `os.FileInfo`, which the STDIN branch already had
from its `Stat`, and `isSameFile` compares that instead.

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

---------

Signed-off-by: juanjsebgarcia <github@juangarcia.co.uk>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-14 14:33:03 -04:00
Alex Goodman 1d25dfe4da fix(golang): bound allocations from UPX-packed binary headers (#5195)
* fix(golang): bound UPX decompression by what the input can justify

A UPX block's `sz_unc` was passed straight to `make([]byte, n)`, so four bytes of
attacker input spanned the full uint32 range. A ~300KB file could drive multi-GB
resident memory, which Go reports as a fatal runtime OOM that no `recover` on this
path can contain. Syft parses binaries out of arbitrary images, so that is reachable
from any scan.

Two bounds do the work, and UPX's own invariants make them exact:

- all blocks together reconstruct `p_filesize`, so a running remainder caps the sum.
  Bounding only per-block would leave the total at (block count x original size), so
  the remainder is the part that actually closes it
- `p_filesize` sizes the output buffer, so it is capped both absolutely and against
  the size of the file on disk. The absolute cap alone left a ~60 byte header able to
  claim 500MB; the ratio alone cannot work either, since LZMA encodes a run of N
  equal bytes in O(log N) and a `go:embed` of 120MB of zeros legitimately packs 209x

The output buffer is also allocated on the first block that survives validation
rather than up front, so a header claiming a large size with nothing decodable behind
it costs nothing.

Alongside that, several ways the block loop could be steered off its own buffer:

- `parseELFPTLoadOffsets` bounds-checked program headers with `phStart+phentsize >
  len(buf)`, which overflows for a `p_offset` near 2^64 and lets an out-of-range entry
  through into a slice index. Switched to the subtraction form, and a `phentsize`
  shorter than an ELF64 program header is rejected since the reads use fixed offsets
- block placement had the same overflow shape, and on failure it skipped the copy and
  fell through. `outputOffset` derives from the rejected offset, so a `p_offset` at the
  uint64 ceiling wrapped it to 0 and the next block landed on the reconstructed ELF
  header, still returning success. Out-of-range placement now ends the block chain,
  keeping the blocks already placed since those often carry `.go.buildinfo`
- the UPX 2-byte LZMA header carries `lc`/`lp` as nibbles and `pb` as three bits, so
  they can hold values LZMA does not permit. Folded into the props byte they wrap
  (`lc=15, lp=15, pb=7` gives 465, which truncates to 209) and the stream mis-decodes
  instead of failing
- blocks decode directly into a slice of the output buffer instead of a per-block
  buffer that is then copied, so one block no longer doubles peak memory
- the block count is capped: the size budget alone still allows millions of 12-byte
  blocks, each spinning up an LZMA reader

Verified against the `image-small-upx` fixture, a real `upx --best --lzma` binary:
four blocks, max `sz_unc` equal to `p_blocksize` exactly, blocks summing to 0.68 of
`p_filesize`, and a 1.96x expansion against the packed file, so every bound holds with
headroom on genuine output.

Note `p_blocksize` is deliberately not used as a ceiling on `sz_unc`. It adds nothing
the remainder does not already cover, and real output sits at exactly `p_blocksize`,
so it would run with zero headroom against a value the format does not promise.

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

* fix(golang): report UPX binaries we cannot unpack as unknowns

A packed Go binary we fail to unpack means its packages are silently missing from the
SBOM. `getBuildInfo` checked the decompression error for nil and discarded it, so a
rejected file surfaced only the original `buildinfo.Read` error, and that one is
deliberately silenced because it is usually just "not a Go binary".

`decompressUPX` now marks the cases worth reporting with `errUPXDecompress`: it got
past the header and the method dispatch and still could not unpack the file. Everything
else stays quiet, which matters more than it sounds. `upx` defaults to NRV2B unless
`--lzma` is passed and only LZMA is implemented here, so treating any decompression
failure as reportable would attach a golang-cataloger unknown to every packed non-Go
binary in an image. Making the reportable case opt in rather than the quiet case a
growing list also means a guard added later is silent by default.

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

* refactor(golang): drop the vendored xcoff parser

The only thing the golang cataloger read from it was `TargetMachine`, which is the same
two magic bytes `getGOARCHFromBin` had already matched on to dispatch there. So a full
XCOFF walk (string table, symbol table, every relocation table) ran to recover a value
that was already in hand.

`getGOARCHFromBin` reads those two bytes directly now. That is also strictly more
correct: `xcoff.NewFile` bailed with "no symbol table" when `symptr == 0`, so a stripped
XCOFF binary reported no arch at all.

Fixtures move to `testdata/xcoff/`, since they are no longer a package's own testdata.

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

* feat(internal/file): report a reader's real size behind one helper

Bounds get written as "does this claim exceed what the reader actually holds", and the
subtlety is that a reader's own answer cannot be trusted: an `io.SectionReader` reports
the nominal length it was built with, so one constructed with `1<<63-1` will happily
claim to hold 8EB. Confirming the last byte is readable is what separates a real size
from a nominal one.

Returns `(int64, bool)` rather than a bare size, since there are five ways to not know
and collapsing them to 0 makes every caller reinvent "0 means stop bounding".

The doc also names the wrapper trap: a type embedding `io.ReaderAt` as an interface
promotes only `ReadAt`, so it answers no size at all however large the reader beneath it
is, and a bound written against it silently does nothing.

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

* fix(golang): bound every section a reader can expand, not just the name table

`CheckSectionNameTable` bounds the one section `elf.NewFile` expands while parsing, which
is enough for a caller that only parses. It is not enough for one that goes on to read
sections: those are expanded lazily, so a 260KB ELF declaring a compressed `.symtab`
drove 1.3GB of allocation through `goversion`, which opens the file with `debug/elf`
inside its own package and cannot be routed through `elfutil.NewFile`.

`CheckAllSections` is that gate, and is deliberately named as the superset so the
relationship to the narrow one is structural rather than documented.

Also exports `ErrDeclaredSizeExceeded`. A refusal here costs the SBOM a package, so
callers report it as an unknown, and matching on an error string to decide that is not
something to build a reporting policy on.

A ruleguard rule now flags `buildinfo.Read` and `version.ReadExeFromReader` outside
`scan_binary.go`. Both open `debug/elf` internally and are only bounded there by the
wrappers that gate the reader first, which the existing rule on `elf.NewFile` could not
see through.

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

* feat(internal/spillbuf): sparse offset-addressed buffer that spills to disk

For output that arrives out of order, at offsets the input itself declares: a
decompressor placing extents, an archive rebuilding a file from chunks. A plain `[]byte`
cannot do that without either pre-sizing to a length the input claims or growing to the
furthest offset it names, and both hand a hostile input an allocation knob.

The load-bearing property is that it reports only what it actually stored. `Size` is the
contiguous run written from offset zero and a read past it is `io.EOF`, never the zeros
an unwritten region would hand back for free. Sparse storage serving holes as real
content is what lets a write offset stand in for output nothing produced, so anything
sizing an allocation against this reader (`saferio` in `debug/elf` does exactly that)
stays bounded by work actually done.

`FirstGap` answers where the next write fits, so callers filling holes do not need the
extent bookkeeping and cannot re-derive that rule wrongly, and it only reports gaps
lying entirely inside `[0, within)`. The extent type is unexported for the same reason.

The rest of the contract worth stating: reads and writes after `Close` fail with
`os.ErrClosed` rather than looking like an empty buffer, and a write that fails leaves
the buffer unchanged.

Memory is bounded by the limit rather than by how much is written: filling 1MB and
filling 64MB cost about the same. What lands on disk past that limit is the caller's
bound to set, not this package's. Growth is geometric and capped, because sizing the
tier to exactly what each write needs is quadratic once a caller streams through it in
small chunks.

The golang cataloger is the only consumer today, and nothing else in the tree has this
shape.

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

* fix(golang): rebuild UPX binaries through spillbuf and read the reconstruction everywhere

Two amplification paths were still reachable. A 128 byte input allocated 16MB by
trusting `sz_cpr` before weighing it against the bytes the file actually holds, and the
reconstruction was assembled in a `[]byte` sized from the header's declared original
size, so a 301KB input allocated 300MB.

The reconstruction is a `spillbuf.Buffer` now, which is what makes the second one go
away: blocks are placed at the offsets the file declares, nothing is pre-sized from a
claim, and the reader's length is the contiguous run actually rebuilt. That last part is
the invariant everything downstream leans on. A reader reporting the declared size would
serve the holes between placed blocks as zeros it never stored, and a 64 byte block
parked at `p_filesize-64` then made a 300KB input hand out a 64MB reader: measured, that
drove 269MB through `getBuildInfo` and returned nothing, silently.

Placement and storage are separate concerns. `upx.go` places blocks at the offsets the
file declares and asks the buffer how much was rebuilt and where the next gap is; it
knows nothing about temp files or memory limits.

The remaining bounds are ratios against the input wherever they can be, since an
absolute ceiling only ever drops a large legitimate binary. The one absolute left is on
`p_filesize`, because padding an input is nearly free, and the LZMA dictionary is paid
for in its own block's `sz_cpr`.

Interface change: `scanFile` takes a context and hands back the reconstruction for each
binary that turned out to be packed, and the caller owns it. Everything after the build
info read (crypto settings, arch, symbols, the version scan) reads it, so a packed
binary no longer reports its packages with no symbols at all.

Also narrows what gets reported. This cataloger runs on every executable in an image, so
reporting every `getBuildInfo` error attached an unknown to every corrupt ELF, odd PE and
non-Go Mach-O slice in it. Now only four gaps, the ones that cost the SBOM something
syft could have had: a packed file we could not decode (`errUPXDecompress`), a header
the size bounds refused (`errUPXSizeRefused`), a reconstruction that came up short
(`errUPXPartial`), and an ELF expansion `elfutil` declined
(`ErrDeclaredSizeExceeded`). An unimplemented UPX method stays quiet on purpose: `upx`
defaults to NRV2B and only LZMA is implemented here, so reporting it would attach an
unknown to most packed non-Go binaries in an image.

That filtering is a new pattern. No other cataloger picks which of its errors become
unknowns, and the reason this one does is that it runs on every executable in an image
rather than on files a glob already selected.

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

* chore: ignore local spec/ planning notes

`/specs` was already ignored; `/spec` is the same thing under the singular name and was
not, so working notes landed in commits.

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

* refactor(golang): name what the unpack hands back, not where it stores it

the scan's signatures said `*spillbuf.Buffer` all the way down, which told
every reader below the scan that it cares whether the reconstruction lives in
memory or on disk. it does not. two interfaces instead, each naming only what
its side actually uses:

- `unpackedContents` for the consumers: `ReaderAt`, `Closer`, and a `Size` that
  is the contiguous run rebuilt from zero
- `blockSink` for the decoder, which additionally needs `WriterAt` and
  `FirstGap` to place blocks

this costs one thing worth flagging. `Close` on a nil `*spillbuf.Buffer` was
nil-safe, so callers just deferred it; widened into an interface, a nil pointer
becomes a non-nil interface and the same call panics. `closeUnpacked` absorbs
that, and it is now the only way an owner releases contents. `readerFor`,
`seekerFor` and `closeUnpacked` are the three places that resolve the nil.

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

* docs(elfutil): say that CheckAllSections is the decompression-bomb gate

the doc led with "bounds every section syft can drive debug/elf into
decompressing", which describes the mechanism without ever naming what it is
defending against. a reader landing on the call site could not tell that this
is the decompression-bomb check.

state the attack instead: a compressed section header declares its own
decompressed size, debug/elf believes that number and allocates it on open, and
nothing forces it to match what the compressed bytes actually yield. the 260KB
ELF that drove 1.3GB of allocation now lives in the doc rather than only at the
one call site that happened to mention it.

comments only.

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

* docs(golang): move the overflow note onto the bounds test it describes

the "subtraction form" note sat above the phStart assignment with ten lines of
wrap analysis between it and the `if` it was talking about, so the subtraction
it names reads as missing. it is `hdrLen-phStart < phentsize`.

move it onto that test and name the form it is avoiding (`phStart+phentsize >
hdrLen`, which can overflow past the buffer end) so the referent is not several
paragraphs away.

comments only.

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

* chore(golang): drop the internal/ README left over from xcoff

that README existed to record where the vendored xcoff package came from and
that Go keeps it internal, which is a provenance note worth having while
third-party code sat there. dropping xcoff took the reason with it, and
repurposing it to point at gotestdata just made it redundant: gotestdata has
its own README covering why it is under internal/, why it is not testdata/, and
what belongs in each.

internal/ now holds one self-documenting directory.

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-09-10 09:21:19 -04:00
Alex Goodman 58a033f924 Prevent unnecessary allocations when parsing compressed ELF sections (#5187)
* fix(elf): bound compressed ELF section reads

`debug/elf` takes a section's decompressed size from that section's own
compression header, and a highly compressible stream really does deliver the
bytes that header promises, so `internal/saferio` does not help: it faithfully
allocates every one of them. A 2MB input file drives `elf.NewFile` to allocate
over 10GB and return no error, which is a fatal OOM rather than a recoverable
panic.

Which sections get read is not up to the caller. `elf.NewFile` always reads the
section-name string table, and `File.Symbols` reads `.symtab` plus whatever
section its `Link` field points at, so being selective about sections is not
enough to avoid it.

New `elfutil.NewFile` is a drop-in for `elf.NewFile` that rejects a declared
decompressed size over 128MB. Every production call site goes through it, and a
ruleguard rule keeps the next one from going direct.

The check runs in two parts, since `debug/elf` expands sections at two different
times. The section-name string table is the only one `elf.NewFile` expands
itself, so it is checked against the raw bytes before the call; everything else
is expanded lazily by `(*Section).Open` and is checked after the parse, where
names, types and decompressed sizes are already resolved.

Only the sections syft can actually reach are bounded, which keeps the guard
from costing real binaries. DWARF is excluded since nothing calls `File.DWARF`,
so a large compressed `.debug_info` no longer skips the whole file, and sections
`debug/elf` will not decompress anyway (`SHF_ALLOC`, `SHT_NOBITS`) are left
alone. The legacy `.zdebug` form is matched on the section name the way
`debug/elf` gates it rather than on the `ZLIB` magic, so an ordinary section
starting with those four bytes is not mistaken for a compressed one.

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

* fix(elf): gate debug/buildinfo behind the compressed-section check

`debug/buildinfo.Read` opens ELF files with `debug/elf` itself, and `elf.NewFile`
expands the section-name string table as it parses, so the golang cataloger was
still reachable by the same bomb `elfutil` exists to stop. A 261KB fixture drove
1.4GB of allocation through `buildinfo.Read` and returned no error.

`elfutil.CheckSectionNameTable` is now exported for that case: callers that cannot
use `NewFile` because the `debug/elf` call is made for them inside another package.
Both `buildinfo.Read` call sites go through it, including the UPX-decompressed one.

Also corrects claims that did not hold up:

- the package doc's 2MB-to-10GB figure is not reachable with zlib (~1000:1), so it
  now carries the measured 510KB-to-2.6GB, and names zstd's 32767:1 since that is
  what makes the small inputs possible

- `.go.buildinfo` was listed as a hot-path section elfutil covers, but it is read
  through `debug/buildinfo` and never touches `Section.Data`

- the graalvm comment claimed routing size rejections away from `*elf.FormatError`
  improved reporting; both branches are skipped by the caller and only the
  FormatError branch logs, so it did the opposite

- `sharedLibraries` logged short and truncated files as real ELF failures, since
  `debug/elf` returns a bare `io.EOF` rather than an `*elf.FormatError` for those

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

* added test comments around the negative cases

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

* additional tests

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

* better decomposition and comments

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

* use a less brittle constant for error detection

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-08-14 20:08:58 +00:00
Keith Zantow 9c321691d4 feat: SPDX 3 (#4269)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2026-06-22 10:59:34 -04:00
Ludovic Henry 05cc8ee5f4 Add support for linux-riscv64 (#4757) 2026-04-27 10:21:41 +00:00
anchore-oss-update-botandanchore-oss-update-bot 5b58ec96b7 chore(deps): update Go version (#4773)
Signed-off-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
Co-authored-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
2026-04-15 10:01:39 -04:00
Will Murphy e38851143e chore: centralize temp files and prefer streaming IO (#4668)
* chore: centralize temp files and prefer streaming IO

Catalogers that create temp files ad-hoc can easily forget cleanup,
leaking files on disk. Similarly, io.ReadAll is convenient but risks
OOM on large or malicious inputs.

Introduce internal/tmpdir to manage all cataloger temp storage under
a single root directory with automatic cleanup. Prefer streaming
parsers (bufio.Scanner, json/yaml.NewDecoder, io.LimitReader) over
buffering entire inputs into memory. Add ruleguard rules to enforce
both practices going forward.

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

* chore: go back to old release parsing

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

* simplify to limit reader in version check

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

* chore: regex change postponed

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

* simplify supplement release to limitreader

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

---------

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>
2026-03-18 10:53:51 -04:00
Alex Goodman b5e85c3ea5 chore: migrate fixtures to testdata (#4651)
* migrate fixtures to testdata

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

* fix: correct broken symlinks after testdata migration

The migration from test-fixtures to testdata broke several symlinks:
- elf-test-fixtures symlinks pointed to old test-fixtures paths
- elf-test-fixtures needed to be renamed to elf-testdata
- image-pkg-coverage symlink pointed to test-fixtures instead of testdata

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

* fix: handle missing classifiers/bin directory in Makefile

The clean-fingerprint target was failing when classifiers/bin doesn't
exist (e.g., on fresh clone without downloaded binaries).

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

* fix: add gitignore negation for jar/zip fixtures in test/cli

The jar and zip files in test/cli/testdata/image-unknowns were being
gitignored by the root .gitignore patterns. This caused them to be
untracked and not included when building docker images in CI, resulting
in Test_Unknowns failures since the test expects errors from corrupt
archive files that weren't present.

Add a .gitignore in test/cli/testdata to negate the exclusions for
these specific test fixture files.

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

* switch fixture cache to v2

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

* test: update expected versions for rebuilt fixtures

Update test expectations for packages that have been updated in
upstream repositories when docker images are rebuilt:
- glibc: 2.42-r4 → 2.43-r1 (wolfi)
- php: 8.2.29 → 8.2.30 (ubuntu/apache)

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

* upgrade go

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

* fix: add go-shlex dependency for testdata manager tool

The manager tool in syft/pkg/cataloger/binary/testdata/ imports
go-shlex, but since it's in a testdata directory, Go doesn't track
its dependencies. This caused CI failures when go.mod didn't
explicitly list the dependency.

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

* refactor: move binary classifier manager to internal/

Move the manager tool from testdata/manager to internal/manager so
that Go properly tracks its dependencies. Code in testdata directories
is ignored by Go for dependency tracking, which caused CI failures
when go.mod didn't explicitly list transitive dependencies.

This is a cleaner solution than manually adding dependencies to go.mod
for code that happens to live in testdata.

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

* fix: add gitignore negations for test fixtures blocked by root patterns

Multiple test fixtures were being blocked by root-level gitignore patterns
like bin/, *.jar, *.tar, and *.exe. This adds targeted .gitignore files with
negation patterns to allow these specific test fixtures to be tracked:

- syft/linux/testdata/os/busybox/bin/busybox (blocked by bin/)
- syft/pkg/cataloger/java/testdata/corrupt/example.{jar,tar} (blocked by *.jar, *.tar)
- syft/pkg/cataloger/binary/testdata/classifiers/snippets/go-version-hint/**/bin/go (blocked by bin/)
- syft/pkg/cataloger/bitnami/testdata/no-rel/.../bin/redis-server (blocked by bin/)

Also updates the bitnami test expectation to include the newly required
.gitignore files in the test fixture.

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

* test: update glibc version expectation (2.43-r1 -> 2.43-r2)

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

* add capability drift check as unit step

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

* dont clear test observations before drift detection

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

* bump stereoscope commit to main

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-03-06 19:42:04 +00: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
Rez MossandChristopher Phillips 74c9380248 fix: 4423 dotnet-deps cataloger skips project type by def
---------
Signed-off-by: Rez Moss <hi@rezmoss.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.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-12-18 13:38:47 -05:00
Saleem Abdulrasool 21d50d7c31 feat: add ARM64 Windows build target (#4237)
Signed-off-by: Saleem Abdulrasool <compnerd@compnerd.org>
2025-09-24 15:29:03 -04:00
n-bes 170c4c41f4 use go.yaml.in/yaml (#4157)
Signed-off-by: Nikita Besperstov <n.bes@pm.me>
2025-08-26 11:24:23 -04:00
Christopher Angelo Phillips 6b48bd4b5e feat: add package supplier flag (#4131)
---------

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-08-12 14:49:41 -04:00
Christopher Angelo Phillips 1e3d2a2927 chore: update tests to read from latest test-fixture-cache and fix cache publish (#4042)
* feat: update integration test with correct package for httpd

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

* chore: update integration and cli tests with new upstream expectations

- php interpreter 8.3.21 => 8.3.22
- runCycloneDXInDocker update for local arm64 qemu emulation CycloneDX
- getSyftBinaryLocationByOS update to detect arm64 v8.0 artifact path

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

* chore: add snalshot to test command for fixture builds

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

* chore: update cdx in docker for all GOOS

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

---------

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-07-01 14:11:36 +00:00
Keith Zantow 71d84603c1 fix: bump stereoscope to fix symlink performance issue (#3953)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2025-06-04 15:50:03 +00:00
Christopher Angelo Phillips 2a055690e6 chore: delete unused fixture (#3901)
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-05-15 17:30:36 +00:00
Christopher Angelo Phillips 4f73d35051 Include default config licenses (#3900)
* fix: the licenses config was not being carried through causing content to show by default
---------
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-05-15 16:48:18 +00:00
Christopher Angelo PhillipsandAlex Goodman f77d503892 detect license ID from full text when incidentally provided as a value (#3876)
---------
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>
2025-05-13 16:37:18 -04:00
Rez MossandAlex Goodman 12d91f47dc Add a homebrew cataloger (#3724)
* Cataloger homebrew (#4)

* homebrew cataloger

* uptd

* fixed test

* fixed test

* fixed tests

* fixed lint

* inc schema ver

* upt schema

* fixed integration test

* fixed integration tst

* fixed test

Signed-off-by: Rez Moss <hi@rezmoss.com>

* Update parse_homebrew_test.go

Signed-off-by: Rez Moss <hi@rezmoss.com>

* Update parse_homebrew_test.go

fixed DCO

Signed-off-by: Rez Moss <hi@rezmoss.com>



Signed-off-by: Rez Moss <hi@rezmoss.com>

* Update parse_homebrew_test.go

add evd anno to test

Signed-off-by: Rez Moss <hi@rezmoss.com>

* lint

Signed-off-by: Rez Moss <hi@rezmoss.com>

* fixed test

Signed-off-by: Rez Moss <hi@rezmoss.com>

* with PR refactors

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

* regenerate json schema

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

* fix tests

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

* regenerate jsonschema

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

* refactor homebrew parser + add tests

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

* more resiliant variable extraction

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>
2025-05-13 13:01:41 -04:00
Alex Goodman ad9928cb2a Merge the .NET deps.json and PE binary catalogers (#3563)
* add combined deps.json + pe binary cataloger

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

* deprecate pe and deps standalone catalogers

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

* parse resource names + add tests

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

* fix integration and CLI tests

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

* add some helpful code comments

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

* allow for dropping Dep packages that are missing DLLs

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

* migrate json schema changes to 24

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

* keep application configuration

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

* correct config help

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

* [wip] detect claims of dlls within deps.json

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

* [wip] fix tests

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

* add assembly repack detection

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

* .net package count is lower due to dll claim requirement

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-03-27 14:38:16 -04:00
Keith Zantow 4a9437808e feat: parallelize catalogers per-file and hash contents in parallel (#3636)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2025-03-26 11:10:08 -04:00
Alex Goodman 2738291a96 swap centos images for rocky (#3741)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-03-18 14:25:03 +00:00
Christopher Angelo Phillips e584c9f416 feat: 3626 add option enable license content; disable by default (#3631)
---------
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2025-02-05 20:41:03 +00:00
Alex Goodman 684b6e3f98 Add file catalogers to selection configuration (#3505)
* add file catalogers to selection configuration

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

* fix typos

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

* warn when there is conflicting file cataloging configuration

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

* allow for explicit removal of all package and file tasks

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

* address PR feedback

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-02-03 19:10:17 +00:00
anchore-actions-token-generator[bot] 25792160fb chore(deps): update tools to latest versions (#3543)
* chore(deps): update tools to latest versions

---------

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2024-12-23 11:32:17 -05:00
48190233f4 fix: emit NOASSERTION for copyright text to fix SPDX 2.2 validation failure (#3495)
* fixes issue #3346

Signed-off-by: Fearkin <fearjin1@gmail.com>

* chore: update schema and unit tests to reflect new copyright property

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

* chore: revert schema changes

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

* fix: noassert copyright on spdx root package

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

* test: explicitly test spdx 2.2 with tools-java validator

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

* test: update snapshot files

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

---------

Signed-off-by: Fearkin <fearjin1@gmail.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>
Co-authored-by: Fearkin <fearjin1@gmail.com>
Co-authored-by: Will Murphy <willmurphyscode@users.noreply.github.com>
2024-12-04 14:58:36 -05:00
ac8be4ad41 chore(deps): update tools to latest versions (#3413)
* chore(deps): update tools to latest versions

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix linting

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

---------

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-11-12 15:53:27 +00:00
Christopher Angelo PhillipsandKeith Zantow 8a41d77250 chore: prevent file resolver from bubbling errors in binary cataloger (#3410)
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Signed-off-by: Keith Zantow <kzantow@gmail.com>
Co-authored-by: Keith Zantow <kzantow@gmail.com>
2024-11-04 20:23:27 +00:00
Keith Zantow 759b898df5 feat: multi-level configuration and profiles (#3337)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2024-10-23 12:15:59 -04:00
Keith ZantowandAlex Goodman ccbee94b87 feat: report unknowns in sbom (#2998)
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>
2024-10-07 16:11:37 -04:00
Alex Goodman 0a3f513f92 Slim down docker cache size (#3190)
* slim down docker cache size

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

* remove old centos images

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

* troubleshoot test failure

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

* fix wget version ref

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

* refactor caching mechanisms

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

* add cache cleanup steps

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

* simplify deleting cache

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

* fix first clone issue

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

* add tool dep

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-09-09 11:15:13 -04:00
luozexuan c19cf626ab chore: fix some comments (#3114)
Signed-off-by: luozexuan <fetchcode@139.com>
2024-08-12 12:08:04 -04:00
Alex Goodman c43f4fb416 add signature verification to install.sh (#2941)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-06-10 11:29:53 -04:00
Alex Goodman 4bdbd1aa2a remove unused test fixtures and empty dirs (#2924)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-06-04 15:22:49 -04:00
William MurphyandAlex Goodman 557ad73ee6 fix: only skip tmpfs mounts for some paths (#2918)
* fix: only skip tmpfs mounts for some paths

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* refactor and add tests

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

* add regression test for archive processing

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

* bump to golang 1.22

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

* remove rule 1 and add more tests

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

---------

Signed-off-by: Will Murphy <will.murphy@anchore.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-06-04 15:21:45 -04:00
dufucunanddufucun 29d601d1f1 chore: fix some comments (#2920)
Signed-off-by: dufucun <dufuchun@sohu.com>
Co-authored-by: dufucun <dufucunn@sohu.com>
2024-06-03 14:10:39 +00:00
Laurent Goderre b51252dbdb feat: Add Lua cataloger (#2613)
Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
2024-05-24 16:56:34 -04:00
Alex Goodman 048df17e3d Use values in relationship To/From fields (#2871)
* use pkg values in relationship fields

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

* add linter rule for using values in relationships

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

* use new cmptest package for comparing relationships

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

* create cmptest for common cmp.Diff options in test

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

* condense matches for relationship ruleguard

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

* remove relationship type from rules

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

* restore build tag

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

* suggest using values

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

* nil check pkgs

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-05-14 13:48:33 -04:00
Alex Goodman ada8f009d2 Add relationships for ALPM packages (arch linux) (#2851)
* add alpm relationships

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

* tweak reader linter rule to check for reader impl

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

* update JSON schema with alpm dependency information

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-05-07 13:29:46 -04:00
William Murphy 3713d97b7b chore: use ruleguard to test for missing defer statements (#2837)
* chore: ruleguard to enforce defer use

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* fix go.mod location

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close in linux release identifier

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: better lint suggestion

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: refactor binary classifier to defer close

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in gentoo cataloger

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: make go license parsing defer close readers

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer closing readers in alpine apm parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in graalvm parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in debian package parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in alpm parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in executable file cataloger

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in javascript license parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in go mod parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

---------

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2024-05-07 05:42:29 -04:00
Laurent Goderre e0233625cb feat: cataloger for PHP Pecl and PEAR packages (#2604)
Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
2024-04-02 11:55:56 -04:00
Keith Zantow a978966cad feat: add --from flag, refactor source providers (#2610)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2024-02-27 16:44:37 -05:00
Keith Zantow 2995c3c4fd fix: SPDX tag value version selector (#2665)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2024-02-23 08:22:10 -05:00
Keith Zantow 108a5dae9b chore: update busybox image for acceptance tests (#2663)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2024-02-22 15:32:17 -05:00
Alexandr HacicheantandAlex Goodman 96ee2db875 feat: Add Wordpress cataloger (#2218)
* Closes #1911 Wordpress cataloger

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed a few unit tests and static analizer notices

Signed-off-by: disc <a.hacicheant@gmail.com>

* Updated `README.md`

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed `golangci-lint` notices
Added integration test for `wordpress-plugin`

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed `gosimports` notices

Signed-off-by: disc <a.hacicheant@gmail.com>

* Updated `json schema` version

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed CLI tests, increased expected package count

Signed-off-by: disc <a.hacicheant@gmail.com>

* Read first 4Kb of a plugins file's content

Signed-off-by: disc <a.hacicheant@gmail.com>

* replace JSON schema version

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

* change wording on source info for wordpress packages

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

* Minor changes after a huge refactoring

Signed-off-by: disc <a.hacicheant@gmail.com>

* Removed unused files

Signed-off-by: disc <a.hacicheant@gmail.com>

* Updated schema

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed integration tests

Signed-off-by: disc <a.hacicheant@gmail.com>

* fix integration tests

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

* Renamed `metadata.Name` to `metadata.PluginInstallDirectory`

Signed-off-by: disc <a.hacicheant@gmail.com>

* rename fields to be compliant with json conventions

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

---------

Signed-off-by: disc <a.hacicheant@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-14 16:03:25 +00:00
Keith Zantow d26a5c4d30 fix: ensure version output to stdout (#2621) 2024-02-09 20:59:25 +00:00