CLI tool and library for generating a Software Bill of Materials from container images and filesystems
This report summarizes scanner evidence for anchore/syft, a Go project with 9,808 GitHub stars. SynthScan examined 602,726 lines of code across 1935 source files, recording 221 pattern matches distributed across 14 syntactic categories. The legacy adjusted pattern signal is 0.5 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 193 finding(s).
Are imports declared and package/API names verified? 7 finding(s).
Are wrappers, guards, and repeated structures necessary? 31 finding(s).
Which changes need focused human review? 221 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 221 distinct pattern matches across 14 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | .golangci.yaml | 81 | - builtin$ | COMMENT |
| LOW | .bouncer.yaml | 21 | COMMENT | |
| LOW | cmd/syft/internal/options/writer.go | 81 | COMMENT | |
| LOW | …/internal/test/integration/encode_decode_cycle_test.go | 41 | // no redactions necessary | COMMENT |
| LOW | …/test/integration/package_cataloger_convention_test.go | 141 | // note: this is meant to apply to things in static space, not methods on structs or within interfaces. | COMMENT |
| LOW | test/install/test_harness.sh | 181 | # ../../snapshot/syft_0.36.0-SNAPSHOT-e5e847a_linux_arm64.deb | COMMENT |
| LOW | test/cli/scan_cmd_test.go | 81 | "-o", "json", coverageImage}, | COMMENT |
| LOW | test/cli/scan_cmd_test.go | 161 | assertPackageCount(14), | COMMENT |
| LOW | test/cli/scan_cmd_test.go | 181 | name: "all-layers-scope-flag", | COMMENT |
| LOW | test/cli/scan_cmd_test.go | 241 | assertJsonReport, | COMMENT |
| LOW | …st/cli/testdata/attestation/docker-compose-config.yaml | 1 | # | COMMENT |
| LOW | test/cli/testdata/attestation/config/logid.sh | 1 | #!/bin/bash | COMMENT |
| LOW | …data/attestation/config/dex/docker-compose-config.yaml | 1 | # | COMMENT |
| LOW | internal/constants.go | 1 | package internal | COMMENT |
| LOW | internal/spillbuf/buffer.go | 1 | // Package spillbuf provides a sparse, offset-addressed byte buffer that keeps a bounded amount in memory | COMMENT |
| LOW | internal/spillbuf/buffer.go | 41 | // Storage is two tiers with a fixed boundary: bytes below memLimit live in mem, bytes at or past it live | COMMENT |
| LOW | internal/capabilities/model.go | 101 | // CapabilityField represents a single capability field with optional conditional values based on configuration. | COMMENT |
| LOW | …ternal/capabilities/internal/load_capabilities_test.go | 41 | COMMENT | |
| LOW | internal/file/reader_size.go | 1 | package file | COMMENT |
| LOW | internal/file/reader_size.go | 21 | // intermediate position. | COMMENT |
| LOW | internal/spdxlicense/generate/generate_license_list.go | 101 | // https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/#license-short-name. | COMMENT |
| LOW | internal/os/feature_detection.go | 61 | COMMENT | |
| LOW | internal/testutils/alloc.go | 1 | package testutils | COMMENT |
| LOW | .github/scripts/labeler.py | 221 | COMMENT | |
| LOW | syft/archive_cataloger_test.go | 41 | // | COMMENT |
| LOW | syft/file/resolver.go | 21 | // MetadataResolver provides file metadata lookup by location. | COMMENT |
| LOW | syft/file/resolver.go | 41 | // The implementation for this may vary, however, generally the following considerations should be made: | COMMENT |
| LOW | syft/file/cataloger/executable/macho.go | 81 | } | COMMENT |
| LOW | syft/source/snapsource/snapcraft_api.go | 101 | // isEligibleChannel determines whether a candidate channel satisfies a requested | COMMENT |
| LOW | …ft/source/directorysource/directory_source_win_test.go | 1 | //go:build windows | COMMENT |
| LOW | syft/source/ocimodelsource/registry_client.go | 41 | // maxGGUFHeaderBytes is the leading slice we range-GET from a (multi-GB) | COMMENT |
| LOW | syft/internal/fileresolver/filetree_resolver_test.go | 21 | COMMENT | |
| LOW | syft/internal/fileresolver/container_image_model.go | 21 | COMMENT | |
| LOW | syft/internal/fileresolver/path_skipper.go | 41 | } | COMMENT |
| LOW | syft/internal/fileresolver/unindexed_directory_test.go | 41 | COMMENT | |
| LOW | syft/internal/elfutil/elfutil.go | 41 | "math" | COMMENT |
| LOW | syft/internal/elfutil/elfutil.go | 61 | // | COMMENT |
| LOW | syft/internal/elfutil/elfutil.go | 121 | // the case this was written for, a 260KB ELF declaring a compressed .symtab drove 1.3GB of allocation. | COMMENT |
| LOW | syft/internal/elfutil/elfutil.go | 181 | // File.DynamicSymbols pulls the symbol version tables in behind the caller's back, via | COMMENT |
| LOW | syft/internal/elfutil/elfutil.go | 201 | // re-read against it. | COMMENT |
| LOW | syft/internal/elfutil/elfutil.go | 241 | } | COMMENT |
| LOW | syft/internal/elfutil/elfutil.go | 261 | var hdr [legacyZlibHeaderSize]byte | COMMENT |
| LOW | syft/internal/elfutil/elfutil_test.go | 341 | require.Error(t, err) | COMMENT |
| LOW | syft/internal/elfutil/elfutil_test.go | 421 | // here is a size claim at all. A check that sniffed for the magic instead would decode the | COMMENT |
| LOW | syft/cpe/cpe.go | 201 | COMMENT | |
| LOW | syft/format/spdxjson/spdx3_decoder_test.go | 21 | COMMENT | |
| LOW | …format/internal/cyclonedxutil/helpers/licenses_test.go | 201 | }, | COMMENT |
| LOW | …format/internal/cyclonedxutil/helpers/licenses_test.go | 221 | // { | COMMENT |
| LOW | …/internal/cyclonedxutil/helpers/external_references.go | 101 | // not a fork, and CycloneDX components are deliberately agnostic to source vs binary form (see the comments from the | COMMENT |
| LOW | …ormat/internal/spdxutil/helpers/originator_supplier.go | 21 | // | COMMENT |
| LOW | …ormat/internal/spdxutil/helpers/originator_supplier.go | 161 | // or might not be different from the originating distribution source for the package. The name of the Package Supplier | COMMENT |
| LOW | syft/format/common/spdxhelpers/to_format_model.go | 101 | // 6.4: Document Name | COMMENT |
| LOW | syft/format/common/spdxhelpers/to_format_model.go | 461 | if filesAnalyzed && packageVerificationCode == nil { | COMMENT |
| LOW | syft/format/common/spdxhelpers/to_format_model.go | 501 | COMMENT | |
| LOW | syft/format/common/spdxhelpers/to_format_model.go | 521 | FilesAnalyzed: filesAnalyzed, | COMMENT |
| LOW | syft/format/common/spdxhelpers/to_format_model.go | 541 | // Cardinality: optional, one | COMMENT |
| LOW | syft/format/common/spdxhelpers/to_format_model.go | 561 | // Purpose: List the licenses that have been declared by the authors of the package. | COMMENT |
| LOW | syft/format/common/spdxhelpers/to_format_model.go | 581 | COMMENT | |
| LOW | syft/format/table/encoder.go | 81 | // Here’s a simplified diagram of a table with a header, rows, and footer: | COMMENT |
| LOW | syft/format/syftjson/schema_test.go | 41 | // we want to strictly follow https://google.github.io/styleguide/javaguide.html#s5.3-camel-case | COMMENT |
| 107 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | install.sh | 27 | # ------------------------------------------------------------------------ | COMMENT |
| MEDIUM | install.sh | 32 | # ------------------------------------------------------------------------ | COMMENT |
| MEDIUM | install.sh | 288 | # ------------------------------------------------------------------------ | COMMENT |
| MEDIUM | install.sh | 290 | # ------------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | syft/format/table/encoder.go | 94 | // ┌──────┬─────┐ <- Borders.Top | COMMENT |
| MEDIUM⚡ | syft/format/table/encoder.go | 96 | // ├──────┼─────┤ <- Lines.ShowTop | COMMENT |
| MEDIUM⚡ | syft/format/table/encoder.go | 98 | // ├──────┼─────┤ <- Separators.BetweenRows | COMMENT |
| MEDIUM⚡ | syft/format/table/encoder.go | 100 | // ├──────┼─────┤ <- Lines.ShowBottom | COMMENT |
| MEDIUM⚡ | syft/format/table/encoder.go | 102 | // └──────┴─────┘ <- Borders.Bottom | COMMENT |
| MEDIUM⚡ | syft/pkg/cataloger/internal/dotnet/pe/bundle.go | 17 | // ┌──────────────────────────────────┐ | COMMENT |
| MEDIUM⚡ | syft/pkg/cataloger/internal/dotnet/pe/bundle.go | 22 | // ├──────────────────────────────────┤ | COMMENT |
| MEDIUM⚡ | syft/pkg/cataloger/internal/dotnet/pe/bundle.go | 24 | // ├──────────────────────────────────┤ | COMMENT |
| MEDIUM⚡ | syft/pkg/cataloger/internal/dotnet/pe/bundle.go | 27 | // └──────────────────────────────────┘ | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 85 | except (NoOptionError, NoSectionError): | CODE |
| HIGH | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 165 | except (NoOptionError, NoSectionError): | CODE |
| HIGH | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 173 | except (NoOptionError, NoSectionError): | CODE |
| HIGH | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 181 | except (NoOptionError, NoSectionError): | CODE |
| HIGH | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 192 | except (NoOptionError, NoSectionError): | CODE |
| HIGH | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 198 | except (NoOptionError, NoSectionError): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …tdata/image-pkg-coverage/terraform/.terraform.lock.hcl | 1 | # This file is maintained automatically by "terraform init". | COMMENT |
| MEDIUM | internal/capabilities/appconfig.yaml | 2 | # This file is partially auto-generated. Run 'go generate ./internal/capabilities' to regenerate. | COMMENT |
| MEDIUM | internal/capabilities/generate/io.go | 188 | appNode.HeadComment = "# Application-level configuration. See README.md for documentation.\n# This file is partially a | CODE |
| MEDIUM | …r/terraform/testdata/two-providers/.terraform.lock.hcl | 1 | # This file is maintained automatically by "terraform init". | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …/testdata/image-java-virtualpath-regression/extract.py | 50 | def walk_directory_and_slim_jars(base_dir, output_dir): | CODE |
| LOW | …/integration/testdata/image-test-java-purls/extract.py | 50 | def walk_directory_and_slim_jars(base_dir, output_dir): | CODE |
| LOW | .github/scripts/fingerprint_docker_fixtures.py | 24 | def is_git_tracked_or_untracked(directory): | CODE |
| LOW | .github/scripts/fingerprint_docker_fixtures.py | 35 | def find_test_fixture_dirs_with_images(base_dir): | CODE |
| LOW | .github/scripts/labeler_test.py | 24 | def test_summarize_schema_files(self): | CODE |
| LOW | .github/scripts/labeler_test.py | 34 | def test_get_pr_changed_files(self): | CODE |
| LOW | .github/scripts/labeler_test.py | 45 | def test_filter_to_schema_files(self): | CODE |
| LOW | .github/scripts/labeler_test.py | 60 | def test_sort_json_schema_files(self): | CODE |
| LOW | .github/scripts/find_cache_paths.py | 13 | def find_fingerprints_and_check_dirs(base_dir): | CODE |
| LOW | .github/scripts/find_cache_paths.py | 61 | def parse_fingerprint_contents(fingerprint_content): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | syft/format/common/spdxhelpers/to_format_model.go | 870 | // for now we include a 0 sha1 digest as requested by the spdx spec | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …/testdata/image-java-virtualpath-regression/extract.py | 9 | CODE | |
| LOW | …/integration/testdata/image-test-java-purls/extract.py | 9 | CODE | |
| LOW | .github/scripts/fingerprint_docker_fixtures.py | 44 | CODE | |
| LOW | .github/scripts/find_cache_paths.py | 93 | CODE | |
| LOW | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 341 | CODE | |
| LOW | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 254 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | test/install/test_harness.sh | 126 | # if you want to see proof in the logs, feel free to adjust the redirection | COMMENT |
| MEDIUM | …/homebrew/testdata/formulas/crazy/1.0.0/.brew/crazy.rb | 99 | # If you maintain your own repository, you can add your own bottle links. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | schema/cyclonedx/cyclonedx.json | 1251 | "description": "Specifies the format and nature of the data being attached, helping systems correctly interpre | CODE |
| MEDIUM | syft/pkg/cataloger/ruby/parse_gemspec.go | 190 | // we can do this ourselves with strconv.Atoi, or leverage the existing json package. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | .github/scripts/labeler.py | 3 | CODE | |
| LOW | .github/scripts/prune_orphan_fingerprints.py | 21 | CODE | |
| LOW | .github/scripts/find_cache_paths.py | 2 | CODE | |
| LOW | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 20 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | schema/cyclonedx/cyclonedx.json | 956 | "examples": ["Acme Inc"] | CODE |
| LOW | schema/cyclonedx/cyclonedx.json | 962 | "examples": ["Acme Inc"] | CODE |
| LOW | schema/cyclonedx/cyclonedx.json | 1027 | "examples": ["Acme Inc"] | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 71 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …t/pkg/cataloger/python/testdata/setup/dynamic-setup.py | 616 | # Check if this distribution is already on sys.path | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | .github/scripts/find_cache_paths.py | 135 | except Exception as e: | CODE |