Compare commits

...
Author SHA1 Message Date
Alex Goodman 78ad3d648f [wip] prototype binary relationships
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-03-13 18:09:19 -04:00
Alex Goodman 1b3e57c264 remove unreleated swift change
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-03-13 17:09:08 -04:00
Alex Goodman ad7edba2a5 remove dead test code
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-03-13 17:07:52 -04:00
Alex Goodman e51d4bcda1 less verbose logging
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-03-13 17:05:56 -04:00
Alex Goodman d8113b5f07 bump JSON schema to v16.0.6 + expand test fixtures
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-03-13 16:44:05 -04:00
Brian Ebarb a35f64c971 feat: elf_binary_package_cataloger
Signed-off-by: Brian Ebarb <brian.ebarb@cgifederal.com>
2024-03-13 15:53:49 -04:00
dependabot[bot] 5534c38d0f chore(deps): bump peter-evans/create-pull-request from 6.0.1 to 6.0.2 (#2712)
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/a4f52f8033a6168103c2538976c07b467e8163bc...70a41aba780001da0a30141984ae2a0c95d8704e)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-13 13:47:47 -04:00
Alex Goodman 47fc909700 Show binary exports, entrypoint, and imports (#2626)
show binary exports, entrypoint, and imports for macho, elf, and pe formats

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-03-12 22:04:02 +00:00
dependabot[bot] 2e2a9377ea chore(deps): bump actions/checkout from 4.1.1 to 4.1.2 (#2703)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/b4ffde65f46336ab88eb53be808477a3936bae11...9bb56186c3b09b4f86b1c65136769dd318469633)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 13:18:44 -04:00
dependabot[bot] 4ca79c7626 chore(deps): bump github.com/knqyf263/go-rpmdb (#2701)
Bumps [github.com/knqyf263/go-rpmdb](https://github.com/knqyf263/go-rpmdb) from 0.0.0-20230301153543-ba94b245509b to 0.1.0.
- [Commits](https://github.com/knqyf263/go-rpmdb/commits/v0.1.0)

---
updated-dependencies:
- dependency-name: github.com/knqyf263/go-rpmdb
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-11 11:48:05 -04:00
guangwu 3743f5ae53 chore: reduce duplicate case SwiftPkg (#2696)
Signed-off-by: guoguangwu <guoguangwug@gmail.com>
2024-03-07 18:15:31 +00:00
guangwu ebb9d4edb6 chore: remove deprecated os.SEEK_SET os.SEEK_CUR (#2693)
Signed-off-by: guoguangwu <guoguangwug@gmail.com>
2024-03-07 13:10:48 -05:00
dependabot[bot] e2a9d891b2 chore(deps): bump github.com/docker/docker (#2698)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 25.0.3+incompatible to 25.0.4+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v25.0.3...v25.0.4)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-07 13:00:14 -05:00
dependabot[bot] 5b09c154bb chore(deps): bump modernc.org/sqlite from 1.29.2 to 1.29.3 (#2699)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.2 to 1.29.3.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.2...v1.29.3)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-07 13:00:02 -05:00
dependabot[bot] 1b121ac3f4 chore(deps): bump golang.org/x/net from 0.21.0 to 0.22.0 (#2689)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to 0.22.0.
- [Commits](https://github.com/golang/net/compare/v0.21.0...v0.22.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-06 14:25:56 -05:00
Keith Zantow f9e09aef19 docs: add simplest example from regsitry (#2691)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2024-03-06 14:25:37 -05:00
anchore-actions-token-generator[bot]andspiffcs d2ac672f8f chore(deps): update tools to latest versions (#2688)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
2024-03-06 14:25:13 -05:00
dependabot[bot] 5e3fde04a5 chore(deps): bump anchore/sbom-action from 0.15.8 to 0.15.9 (#2694)
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.8 to 0.15.9.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/b6a39da80722a2cb0ef5d197531764a89b5d48c3...9fece9e20048ca9590af301449208b2b8861333b)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-06 14:24:56 -05:00
dependabot[bot] e214645394 chore(deps): bump github.com/charmbracelet/lipgloss from 0.9.1 to 0.10.0 (#2695)
Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.9.1 to 0.10.0.
- [Release notes](https://github.com/charmbracelet/lipgloss/releases)
- [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.9.1...v0.10.0)

---
updated-dependencies:
- dependency-name: github.com/charmbracelet/lipgloss
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-06 14:24:46 -05:00
dependabot[bot] 5bd1cd5c13 chore(deps): bump golang.org/x/mod from 0.15.0 to 0.16.0 (#2690)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/mod/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-05 10:15:18 -05:00
dependabot[bot] fe4f17286f chore(deps): bump github.com/stretchr/testify from 1.8.4 to 1.9.0 (#2684)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.4 to 1.9.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-01 13:51:18 -05:00
dependabot[bot] d7e58964ef chore(deps): bump actions/cache from 4.0.0 to 4.0.1 (#2685)
Bumps [actions/cache](https://github.com/actions/cache) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/13aacd865c20de90d75de3b17ebe84f7a17d57d2...ab5e6d0c87105b4c9c2047343972218f562e4319)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-01 13:50:49 -05:00
dependabot[bot] 59d54d6154 chore(deps): bump github/codeql-action from 3.24.5 to 3.24.6 (#2686)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.5 to 3.24.6.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/47b3d888fe66b639e431abf22ebca059152f1eea...8a470fddafa5cbb6266ee11b37ef4d8aae19c571)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-01 13:50:34 -05:00
Christopher Angelo Phillips 4d0dd02d5a chore: update stereoscope (#2683)
* chore: update stereoscope to account for traversal bug fix

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2024-02-29 13:32:18 -05:00
Harm Weites 356f7c92b4 fix: match OpenSSL letter releases (#2682)
* chore: match openssl 1.1 letter releases

Signed-off-by: Harm Weites <harm@weites.com>

* chore: include image sha

Signed-off-by: Harm Weites <harm@weites.com>

---------

Signed-off-by: Harm Weites <harm@weites.com>
2024-02-29 14:39:23 +00:00
Alex Goodman 6377465440 Mark duplicated rows in table output (#2679)
* mark duplicated rows in table output

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

* fix unit test

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-29 09:33:00 -05:00
William Murphy 3ad91f2678 fix: trim path from deps.json in portable way (#2674)
* fix: trim path from deps.json in portable way

Previously, the path trimming regex would leave leading path separator
in place on Windows.

Probably a better long term fix is to a library path operation.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2024-02-29 09:31:55 -05:00
anchore-actions-token-generator[bot]andspiffcs 5ef83fdc79 chore(deps): update tools to latest versions (#2680)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
2024-02-29 09:27:37 -05:00
Alex Goodman 06ff1a353a enforce breaking change bump major version (#2635)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-28 15:48:20 -05:00
Keith Zantow 326ec57d4a docs: fix incorrect flag name in readme (#2677) 2024-02-28 15:39:43 -05:00
Alex Goodman 48e5672a87 Consider filesystem types for mount points when ignoring system paths (#2675)
* consider fs types for mount points when ignoring system paths

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

* address feedback

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-28 15:37:17 -05:00
William Murphy 63171b55dd fix: stop emitting bus events on go mod events (#2673)
Previously, the TUI would hang when scanning directories with lots of go
packages, possibly because this path was spamming the TUI with too
many events. Since checking on a particular go module is fast, don't
show TUI events for each one.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2024-02-28 14:14:46 -05:00
dependabot[bot] acc473fc30 chore(deps): bump peter-evans/create-pull-request from 6.0.0 to 6.0.1 (#2676)
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/b1ddad2c994a25fbc81a28b3ec0e368bb2021c50...a4f52f8033a6168103c2538976c07b467e8163bc)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-28 09:31:29 -05: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
dependabot[bot] 928511ea0f chore(deps): bump modernc.org/sqlite from 1.29.1 to 1.29.2 (#2671) 2024-02-26 10:57:06 -05:00
dependabot[bot] 33b72ccbf8 chore(deps): bump github/codeql-action from 3.24.4 to 3.24.5 (#2666) 2024-02-23 14:10:26 +00: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
Stefan Hacker 170ac079d4 fix(install): return appropriate error codes (#2664)
Signed-off-by: Stefan Hacker <mail@hacst.net>
2024-02-22 19:34:51 -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
dependabot[bot] cdf1e0bacb chore(deps): bump github/codeql-action from 3.24.3 to 3.24.4 (#2662) 2024-02-22 16:50:53 +00:00
Alex Goodman 0c3b8ca4ed rename binary classifier cataloger name (#2643)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-20 13:52:11 -05:00
Alex Goodman 434b6ad506 add cataloger selection example (#2646)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-20 11:44:42 -05:00
anchore-actions-token-generator[bot]andspiffcs 3598cb4f8f chore(deps): update tools to latest versions (#2651)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
2024-02-20 11:39:54 -05:00
anchore-actions-token-generator[bot] 8260bce057 chore(deps): update stereoscope to 6171ee21e1d584f6bde910f354d126c9cd70deaa (#2655) 2024-02-17 10:22:56 -05:00
dependabot[bot] 578ac9cf2d chore(deps): bump github/codeql-action from 3.24.1 to 3.24.3 (#2649)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.1 to 3.24.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/e675ced7a7522a761fc9c8eb26682c8b27c42b2b...379614612a29c9e28f31f39a59013eb8012a51f0)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 09:13:29 -05:00
Alex Goodman a1b23bd57d add syft version used to SBOM tool info by default (#2647)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-14 16:57:31 -05:00
Alex Goodman 65cadda486 Survive indexing dead symlinks (#2645)
* survive indexing branches that start with a bad symlink

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

* add log statement

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-14 21:06:22 +00:00
Alex Goodman a909e3cec9 fix considering base path when ignoring known bad unix paths (#2644)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-14 15:57:38 -05:00
Alex Goodman 8e62ff9831 test for field conventions in json schema (#2642)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-14 11:11:53 -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
Alex Goodman 98b700e83c rename binary cataloger to be more unique (#2633)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-14 11:01:55 -05:00
Christopher Angelo Phillips 9803db2949 fix: update runner size to use larger HD for codeql (#2641)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2024-02-14 10:31:05 -05:00
17ef243956 chore(deps): update tools to latest versions (#2616)
* chore(deps): update tools to latest versions

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

* fix: update to new linter rules

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

---------

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
2024-02-14 14:59:49 +00:00
dependabot[bot] 3ac7369068 chore(deps): bump github/codeql-action from 3.24.0 to 3.24.1 (#2638)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.0 to 3.24.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/e8893c57a1f3a2b659b6b55564fdfdbbd2982911...e675ced7a7522a761fc9c8eb26682c8b27c42b2b)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 09:21:21 -05:00
dependabot[bot] 4d4efa4963 chore(deps): bump dawidd6/action-homebrew-bump-formula (#2639)
Bumps [dawidd6/action-homebrew-bump-formula](https://github.com/dawidd6/action-homebrew-bump-formula) from 3.10.1 to 3.11.0.
- [Release notes](https://github.com/dawidd6/action-homebrew-bump-formula/releases)
- [Commits](https://github.com/dawidd6/action-homebrew-bump-formula/compare/75ed025ff3ad1d617862838b342b06d613a0ddf3...baf2b60c51fc1f8453c884b0c61052668a71bd1d)

---
updated-dependencies:
- dependency-name: dawidd6/action-homebrew-bump-formula
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 09:21:05 -05:00
dependabot[bot] a7da2270c7 chore(deps): bump modernc.org/sqlite from 1.29.0 to 1.29.1 (#2640)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.0 to 1.29.1.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.0...v1.29.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 09:20:54 -05:00
Keith Zantow 6288530835 fix: add BOMRef to CycloneDX OS Component (#2634) 2024-02-14 08:18:16 -05:00
dependabot[bot] 25d3c06962 chore(deps): bump github.com/saferwall/pe from 1.5.0 to 1.5.2 (#2629)
Bumps [github.com/saferwall/pe](https://github.com/saferwall/pe) from 1.5.0 to 1.5.2.
- [Release notes](https://github.com/saferwall/pe/releases)
- [Changelog](https://github.com/saferwall/pe/blob/main/CHANGELOG.md)
- [Commits](https://github.com/saferwall/pe/compare/v1.5.0...v1.5.2)

---
updated-dependencies:
- dependency-name: github.com/saferwall/pe
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 11:23:35 -05:00
dependabot[bot] 79b71be0ee chore(deps): bump modernc.org/sqlite from 1.28.0 to 1.29.0 (#2630)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.28.0 to 1.29.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.28.0...v1.29.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 11:23:22 -05:00
Alex Goodman 25ae7bf55f fix getting union reader for sif images (#2631)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-13 15:12:31 +00:00
dependabot[bot] e72dec8e9e chore(deps): bump golang.org/x/net from 0.20.0 to 0.21.0 (#2607)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.20.0 to 0.21.0.
- [Commits](https://github.com/golang/net/compare/v0.20.0...v0.21.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 14:31:44 -05:00
dependabot[bot] 3398e72066 chore(deps): bump github.com/saferwall/pe from 1.4.8 to 1.5.0 (#2625)
Bumps [github.com/saferwall/pe](https://github.com/saferwall/pe) from 1.4.8 to 1.5.0.
- [Release notes](https://github.com/saferwall/pe/releases)
- [Changelog](https://github.com/saferwall/pe/blob/main/CHANGELOG.md)
- [Commits](https://github.com/saferwall/pe/compare/v1.4.8...v1.5.0)

---
updated-dependencies:
- dependency-name: github.com/saferwall/pe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 14:31:31 -05:00
Keith Zantow d26a5c4d30 fix: ensure version output to stdout (#2621) 2024-02-09 20:59:25 +00:00
Alex Goodman 84576b93e1 Guess go main module version based on binary contents (#2608)
* guess go main module version based on binary contents

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

* add configuration options for golang main module version heuristics

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

* fix test setup for go bin cataloger

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

* fix unit test

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

* fix incorrect test assert ordering

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

* handle error from seek

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-09 19:52:42 +00:00
737c4e44c5 chore(deps): update stereoscope to 681f6715b0e35686d6e6f40bce109176de1ee274 (#2617)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
2024-02-09 14:06:28 -05:00
Alex Goodman 7444a9f976 fix readme around templating options (#2612)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-09 13:44:41 -05:00
Alex Goodman 8683cba081 suppress executable parsing issues (#2614)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-09 17:13:58 +00:00
Christopher Angelo Phillips c0f43e5e2d chore: update license list, cpe dictionary (#2620)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2024-02-09 11:31:42 -05:00
anchore-actions-token-generator[bot]andspiffcs 397cf210de chore(deps): update tools to latest versions (#2606)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
2024-02-08 10:39:18 -05:00
Christopher Angelo Phillips bd0cb916df fix: incorrect conversion between integer types (#2605)
* chore: match strconv.ParseInt to file mode type

if a string is parsed into an int using strconv.Atoi,
and subsequently that int is converted into another integer type of a smaller size,
the result can produce unexpected values.
---------
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2024-02-07 20:41:00 +00:00
dependabot[bot] da31eed637 chore(deps): bump golang.org/x/mod from 0.14.0 to 0.15.0 (#2602)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.14.0 to 0.15.0.
- [Commits](https://github.com/golang/mod/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-07 11:31:49 -05:00
dependabot[bot] 704155eb22 chore(deps): bump github.com/docker/docker (#2601)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 25.0.2+incompatible to 25.0.3+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v25.0.2...v25.0.3)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-07 11:31:41 -05:00
William Murphy ce67927a98 Fix: unmarshal key values in Java, Go, and Conan metadata (#2603)
Previously, Syft represented several metadata fields as map[string]string,
however this representation erased ordering, so Syft now represents these values
as []KeyValue. Add custom unmarshaling so that JSON that was written by
older versions of Syft using the map[string]string representation can be parsed
into the new []KeyValue representation.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2024-02-07 11:26:23 -05:00
Weston Steimel bbd34f61fd fix(dotnet): prefer portable executable product version when semantically greater than file version (#2600)
Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2024-02-07 13:28:37 +00:00
Alex Goodmanandmikey strauss c61f59e7b7 Finalize Conan v2 support (#2587)
* Add support for conan lock v2 (#2461)

* conan lock 2.x requires field support

Signed-off-by: houdini91 <mdstrauss91@gmail.com>

* PR review, struct renaming

Signed-off-by: houdini91 <mdstrauss91@gmail.com>

---------

Signed-off-by: houdini91 <mdstrauss91@gmail.com>

* decompose conanlock parser + add tests

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

---------

Signed-off-by: houdini91 <mdstrauss91@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: mikey strauss <mdstrauss91@gmail.com>
2024-02-07 08:24:02 -05:00
anchore-actions-token-generator[bot]andspiffcs 00d6269e3c chore(deps): update tools to latest versions (#2595)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
2024-02-06 10:48:01 -05:00
dependabot[bot] 0bc5971085 chore(deps): bump actions/upload-artifact from 4.3.0 to 4.3.1 (#2597)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/26f96dfa697d77e81fd5907df203aa23a56210a8...5d5d22a31266ced268874388b861e4b58bb5c2f3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 10:44:51 -05:00
anchore-actions-token-generator[bot]andkzantow 91d7a8a992 chore(deps): update stereoscope to bfa15e446f061bda7f68305d2d6240b053f17e0c (#2589)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com>
2024-02-05 10:27:12 -05:00
dependabot[bot] 05fa8ba4e9 chore(deps): bump actions/cache from 3.3.2 to 4.0.0 (#2592)
Bumps [actions/cache](https://github.com/actions/cache) from 3.3.2 to 4.0.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.3.2...13aacd865c20de90d75de3b17ebe84f7a17d57d2)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-05 10:26:55 -05:00
dependabot[bot] e813a427b9 chore(deps): bump github.com/gkampitakis/go-snaps from 0.5.0 to 0.5.2 (#2591)
Bumps [github.com/gkampitakis/go-snaps](https://github.com/gkampitakis/go-snaps) from 0.5.0 to 0.5.2.
- [Release notes](https://github.com/gkampitakis/go-snaps/releases)
- [Commits](https://github.com/gkampitakis/go-snaps/compare/v0.5.0...v0.5.2)

---
updated-dependencies:
- dependency-name: github.com/gkampitakis/go-snaps
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-05 10:26:39 -05:00
dependabot[bot] 0618b2cb35 chore(deps): bump github/codeql-action from 3.23.2 to 3.24.0 (#2593)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.23.2 to 3.24.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/b7bf0a3ed3ecfa44160715d7c442788f65f0f923...e8893c57a1f3a2b659b6b55564fdfdbbd2982911)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-05 09:46:22 -05:00
Alex Goodman fd3844853a labeler should ignore latest version (#2588)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-02 18:08:15 -05:00
William Murphy b735106848 chore: copy latest schema to stable path for easier diff (#2586)
Because we generate a new JSON schema file every time the schema version
changes, the git diff always shows that the file is completely new.
Therefore, every time the file is re-generated, also write the schema to
a stable path, so that the actual changes to the schema are easily
visible in the git diff of the latest schema file.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2024-02-02 17:09:28 -05:00
Asi GreenholtsandAlex Goodman 98de2e2f62 Adding metadata fields when parsing yarn.lock and poetry.lock (#2350)
* Adding the resolved and integrity fields of yarn.lock to the parsed metadata. This addition is similar to the metadata added when parsing package-lock.json.

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>

* fix comment

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>

* Adding the Index field to metadeta when parsing poetry.lock similarly to the existing Pipfile metadata

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>

* fixing struct accoding to tests

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>

* remove old schema change

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

* remove empty constants

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

* re-generate JSON schema

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

* update document ref

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: asi-cider <88270351+asi-cider@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-02 19:53:42 +00:00
Laurent GoderreandAlex Goodman d7b9cc70b0 Add Erlang OTP Application cataloger (#2403)
* Add cataloger for Erlang OTP applications

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

* Add OTP Package type and Purl for ErLang

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

* remove erlang OTP metadata type

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

* use OTP purl type

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

* restore otp fixture and adjust tests for dir-only results

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

---------

Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-02 13:40:18 -05:00
Alex Goodman 3023a5a7bc Detect ELF security features (#2443)
* add detection of ELF security features

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

* fix linting

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

* update json schema with file executable data

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

* update expected fixure when no tty present

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

* more detailed differ

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

* use json differ

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

* fix tests

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

* remove json schema addition

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

* regenerate json schema

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

* fix mimtype set ref

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-02 16:51:18 +00:00
Alex Goodman 3da679066e Add API examples (#2517)
* [wip] initial syft api examples

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

* smooth over some rough edges in the API

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

* embed example file

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

* address review comments

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

* change name of builder function

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-02 16:26:44 +00:00
William Murphy b7a6d5e946 feat: Record where CPEs come from (#2552)
Syft can get CPEs from several source, including generating them based on
package data, finding them in the NVD CPE dictionary, or finding them declared
in a manifest or existing SBOM. Record where Syft got CPEs so that consumers of
SBOMs can reason about how trustworthy they are.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2024-02-02 16:17:52 +00:00
anchore-actions-token-generator[bot]andkzantow 4fe50f4169 chore(deps): update stereoscope to 37291e81936d2b43b3cef56667a741ef715fbfe4 (#2583)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com>
2024-02-02 10:27:26 -05:00
dependabot[bot] 78d362f91a chore(deps): bump github.com/charmbracelet/bubbles from 0.17.1 to 0.18.0 (#2584)
Bumps [github.com/charmbracelet/bubbles](https://github.com/charmbracelet/bubbles) from 0.17.1 to 0.18.0.
- [Release notes](https://github.com/charmbracelet/bubbles/releases)
- [Commits](https://github.com/charmbracelet/bubbles/compare/v0.17.1...v0.18.0)

---
updated-dependencies:
- dependency-name: github.com/charmbracelet/bubbles
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 10:27:09 -05:00
Alex Goodman 5a9b664fef swap format readseekers for readers (#2581)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-01 14:18:13 -05:00
Alex Goodman 6107e5e2ad translate maps to sequences in pkg metadata (#2553)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-02-01 11:58:10 -05:00
anchore-actions-token-generator[bot]andspiffcs fef0e54c0f chore(deps): update tools to latest versions (#2576)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
2024-02-01 10:27:01 -05:00
dependabot[bot] 4a98f9fbd3 chore(deps): bump anchore/sbom-action from 0.15.7 to 0.15.8 (#2578)
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.7 to 0.15.8.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/767b08fd8822486ad890abb8f1d31721bebd651c...b6a39da80722a2cb0ef5d197531764a89b5d48c3)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 10:26:47 -05:00
dependabot[bot] db49c145f0 chore(deps): bump marocchino/sticky-pull-request-comment (#2579)
Bumps [marocchino/sticky-pull-request-comment](https://github.com/marocchino/sticky-pull-request-comment) from 2.8.0 to 2.9.0.
- [Release notes](https://github.com/marocchino/sticky-pull-request-comment/releases)
- [Commits](https://github.com/marocchino/sticky-pull-request-comment/compare/efaaab3fd41a9c3de579aba759d2552635e590fd...331f8f5b4215f0445d3c07b4967662a32a2d3e31)

---
updated-dependencies:
- dependency-name: marocchino/sticky-pull-request-comment
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 10:26:37 -05:00
dependabot[bot] 3ac7e43e3e chore(deps): bump github.com/docker/docker (#2580)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 25.0.1+incompatible to 25.0.2+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v25.0.1...v25.0.2)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 10:26:25 -05:00
anchore-actions-token-generator[bot]andkzantow 216e211dc8 chore(deps): update stereoscope to db7a4bedaba6ad93becf22ce794f306dfb07fcb9 (#2577)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com>
2024-02-01 08:32:13 +00:00
William MurphyandAlex Goodman bbddac1f9d Fix attest with --key (#2551)
Fix passing "--key" to the attest command. Additionally, pull in an update to
the clio CLI library to permit unit testing that flags and env vars are parsed
to the correct field on command options structs. This testing strategy was
needed here because testing attestation in an end to end test requires a
prohibitive amount of setup.

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Will Murphy <will.murphy@anchore.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-01-31 16:39:17 -05:00
Weston Steimel 3893f80052 fix(java): improve identification for org.apache.kafka artifacts (#2573)
Signed-off-by: Weston Steimel <weston.steimel@proton.me>
2024-01-31 16:34:56 -05:00
Christopher Angelo Phillips 630e7153e6 chore: pluralize the flag (#2564)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2024-01-31 13:21:09 -05:00
anchore-actions-token-generator[bot]andspiffcs 28e9ee7106 chore(deps): update tools to latest versions (#2566)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: spiffcs <spiffcs@users.noreply.github.com>
2024-01-31 13:20:34 -05:00
dependabot[bot] 43837f47f5 chore(deps): bump peter-evans/create-pull-request from 5.0.2 to 6.0.0 (#2567)
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5.0.2 to 6.0.0.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/153407881ec5c347639a548ade7d8ad1d6740e38...b1ddad2c994a25fbc81a28b3ec0e368bb2021c50)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-31 13:20:17 -05:00
dependabot[bot] e880e6dcd6 chore(deps): bump anchore/sbom-action from 0.15.6 to 0.15.7 (#2568)
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.6 to 0.15.7.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/c6aed38a4323b393d05372c58a74c39ae8386d02...767b08fd8822486ad890abb8f1d31721bebd651c)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-31 13:19:50 -05:00
Alex Goodman 6ae5b2904d re-add cosign signing checksums file (#2572)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-01-31 13:19:41 -05:00
Alex Goodman 377538e4a6 revert cosign signing of release checksums file (#2571)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-01-31 16:58:24 +00:00
321 changed files with 36235 additions and 2548 deletions
+5 -6
View File
@@ -1,5 +1,4 @@
tools:
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
- name: binny
version:
@@ -27,7 +26,7 @@ tools:
# used for linting
- name: golangci-lint
version:
want: v1.55.2
want: v1.56.2
method: github-release
with:
repo: golangci/golangci-lint
@@ -43,7 +42,7 @@ tools:
# used for signing the checksums file at release
- name: cosign
version:
want: v2.2.2
want: v2.2.3
method: github-release
with:
repo: sigstore/cosign
@@ -59,7 +58,7 @@ tools:
# used to release all artifacts
- name: goreleaser
version:
want: v1.23.0
want: v1.24.0
method: github-release
with:
repo: goreleaser/goreleaser
@@ -104,7 +103,7 @@ tools:
# used for running all local and CI tasks
- name: task
version:
want: v3.34.1
want: v3.35.1
method: github-release
with:
repo: go-task/task
@@ -112,7 +111,7 @@ tools:
# used for triggering a release
- name: gh
version:
want: v2.42.1
want: v2.45.0
method: github-release
with:
repo: cli/cli
+1 -1
View File
@@ -1,4 +1,4 @@
enforce-v0: true # don't make breaking-change label bump major version before 1.0.
enforce-v0: false
title: ""
github:
+3 -2
View File
@@ -176,7 +176,8 @@ def filter_to_schema_files(list_of_files: list[str]) -> list[str]:
def list_json_schema_files() -> list[str]:
# list files in "schema/json" directory matching the pattern of "schema-*.json"
return sort_json_schema_files(list(glob.glob("schema/json/schema-*.json")))
# special case: always ignore the "latest" schema file
return sort_json_schema_files([f for f in glob.glob("schema/json/schema-*.json") if "latest" not in f])
def run(command: str, **kwargs) -> subprocess.CompletedProcess:
@@ -197,7 +198,7 @@ def sort_json_schema_files(files: list[str]) -> list[str]:
# so that "schema/json/schema-1.2.1.json" comes before "schema/json/schema-1.12.1.json".
versions = [get_semver(file) for file in files if file]
versions = sorted(versions, key=lambda s: [int(u) for u in s.split('.')])
versions = sorted(versions, key=lambda s: [int(u) for u in s.split('.') if "." in s])
return [f"schema/json/schema-{version}.json" for version in versions]
+5
View File
@@ -60,6 +60,11 @@ class Labeler(unittest.TestCase):
expected_sorted_files = ["schema/json/schema-1.2.1.json", "schema/json/schema-1.12.1.json"]
self.assertEqual(labeler.sort_json_schema_files(files), expected_sorted_files)
# ensure that "latest" doesn't cause a problem and is ultimately ignored
files = ["schema/json/schema-1.12.1.json", "schema/json/schema-_bogus.json"]
expected_sorted_files = ["schema/json/schema-_bogus.json", "schema/json/schema-1.12.1.json"]
self.assertEqual(labeler.sort_json_schema_files(files), expected_sorted_files)
if __name__ == "__main__":
unittest.main()
+4 -4
View File
@@ -17,13 +17,13 @@ jobs:
# the job by event.
steps:
- name: Checkout code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
- name: Restore base benchmark result
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: test/results/benchmark-main.txt
# use base sha for PR or new commit hash for main push in benchmark result key
@@ -39,13 +39,13 @@ jobs:
OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
echo "result=$OUTPUT" >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: benchmark-test-results
path: test/results/**/*
- name: Update PR benchmark results comment
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
continue-on-error: true
with:
header: benchmark
+5 -5
View File
@@ -20,7 +20,7 @@ permissions:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
runs-on: ubuntu-22.04-4core-16gb
permissions:
security-events: write
@@ -36,7 +36,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Install Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 #v5.0.0
@@ -45,7 +45,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 #v3.23.2
uses: github/codeql-action/init@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 #v3.24.6
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -56,7 +56,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 #v3.23.2
uses: github/codeql-action/autobuild@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 #v3.24.6
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -70,4 +70,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 #v3.23.2
uses: github/codeql-action/analyze@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 #v3.24.6
+3 -3
View File
@@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- run: python .github/scripts/labeler.py
env:
@@ -40,7 +40,7 @@ jobs:
- name: Delete existing comment
if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }}
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
with:
header: ${{ env.COMMENT_HEADER }}
hide: true
@@ -48,7 +48,7 @@ jobs:
- name: Add comment
if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }}
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
with:
header: ${{ env.COMMENT_HEADER }}
path: ${{ env.CI_COMMENT_FILE }}
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
with:
# we need to be able to get the commit for a tag
fetch-depth: 0
@@ -30,7 +30,7 @@ jobs:
echo -n "commit=$(git rev-parse HEAD)" | tee -a $GITHUB_OUTPUT
- name: Update Homebrew formula
uses: dawidd6/action-homebrew-bump-formula@75ed025ff3ad1d617862838b342b06d613a0ddf3 # v3.10.1
uses: dawidd6/action-homebrew-bump-formula@baf2b60c51fc1f8453c884b0c61052668a71bd1d # v3.11.0
with:
token: ${{ secrets.HOMEBREW_TOKEN }}
org: anchore
+5 -3
View File
@@ -15,7 +15,7 @@ jobs:
environment: release
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Check if tag already exists
# note: this will fail if the tag already exists
@@ -94,8 +94,10 @@ jobs:
permissions:
contents: write
packages: write
# required for goreleaser signs section with cosign
id-token: write
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
with:
fetch-depth: 0
@@ -141,7 +143,7 @@ jobs:
AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
- uses: anchore/sbom-action@c6aed38a4323b393d05372c58a74c39ae8386d02 #v0.15.6
- uses: anchore/sbom-action@9fece9e20048ca9590af301449208b2b8861333b #v0.15.9
continue-on-error: true
with:
artifact-name: sbom.spdx.json
+2 -2
View File
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -50,7 +50,7 @@ jobs:
app_id: ${{ secrets.TOKEN_APP_ID }}
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
- uses: peter-evans/create-pull-request@70a41aba780001da0a30141984ae2a0c95d8704e #v6.0.2
with:
signoff: true
delete-branch: true
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -33,7 +33,7 @@ jobs:
app_id: ${{ secrets.TOKEN_APP_ID }}
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
- uses: peter-evans/create-pull-request@70a41aba780001da0a30141984ae2a0c95d8704e #v6.0.2
with:
signoff: true
delete-branch: true
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 #v5.0.0
with:
@@ -44,7 +44,7 @@ jobs:
app_id: ${{ secrets.TOKEN_APP_ID }}
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
- uses: peter-evans/create-pull-request@70a41aba780001da0a30141984ae2a0c95d8704e #v6.0.2
with:
signoff: true
delete-branch: true
+32 -20
View File
@@ -17,7 +17,7 @@ jobs:
name: "Static analysis"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -31,37 +31,49 @@ jobs:
name: "Unit tests"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
- name: Restore file executable test-fixture cache
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: syft/file/cataloger/executable/test-fixtures/elf/bin
key: ${{ runner.os }}-unit-file-executable-elf-cache-${{ hashFiles( 'syft/file/cataloger/executable/test-fixtures/elf/cache.fingerprint' ) }}
- name: Restore file executable shared-info test-fixture cache
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: syft/file/cataloger/executable/test-fixtures/shared-info/bin
key: ${{ runner.os }}-unit-file-executable-shared-info-cache-${{ hashFiles( 'syft/file/cataloger/executable/test-fixtures/shared-info/cache.fingerprint' ) }}
- name: Restore Java test-fixture cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint' ) }}
- name: Restore RPM test-fixture cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: syft/pkg/cataloger/redhat/test-fixtures/rpms
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/redhat/test-fixtures/rpms.fingerprint' ) }}
- name: Restore go binary test-fixture cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: syft/pkg/cataloger/golang/test-fixtures/archs/binaries
key: ${{ runner.os }}-unit-go-binaries-cache-${{ hashFiles( 'syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint' ) }}
- name: Restore binary cataloger test-fixture cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: syft/pkg/cataloger/binary/test-fixtures/classifiers/bin
key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }}
- name: Restore Kernel test-fixture cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: syft/pkg/cataloger/kernel/test-fixtures/cache
key: ${{ runner.os }}-unit-kernel-cache-${{ hashFiles( 'syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint' ) }}
@@ -75,7 +87,7 @@ jobs:
name: "Integration tests"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -84,7 +96,7 @@ jobs:
run: make validate-cyclonedx-schema
- name: Restore integration test cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: ${{ github.workspace }}/cmd/syft/internal/test/integration/test-fixtures/cache
key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('/cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint') }}
@@ -97,7 +109,7 @@ jobs:
name: "Build snapshot artifacts"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -110,7 +122,7 @@ jobs:
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
# see https://github.com/actions/upload-artifact/issues/199 for more info
- name: Upload snapshot artifacts
uses: actions/cache/save@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache/save@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
# we need to preserve the snapshot data itself as well as the task data that confirms if the
# snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot
@@ -127,14 +139,14 @@ jobs:
needs: [Build-Snapshot-Artifacts]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
- name: Download snapshot build
id: snapshot-cache
uses: actions/cache/restore@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache/restore@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: |
snapshot
@@ -152,7 +164,7 @@ jobs:
- name: Restore install.sh test image cache
id: install-test-image-cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: ${{ github.workspace }}/test/install/cache
key: ${{ runner.os }}-install-test-image-cache-${{ hashFiles('test/install/cache.fingerprint') }}
@@ -175,7 +187,7 @@ jobs:
needs: [Build-Snapshot-Artifacts]
runs-on: macos-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -187,7 +199,7 @@ jobs:
- name: Download snapshot build
id: snapshot-cache
uses: actions/cache/restore@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache/restore@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: |
snapshot
@@ -202,7 +214,7 @@ jobs:
- name: Restore docker image cache for compare testing
id: mac-compare-testing-cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: image.tar
key: ${{ runner.os }}-${{ hashFiles('test/compare/mac.sh') }}
@@ -220,20 +232,20 @@ jobs:
needs: [Build-Snapshot-Artifacts]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
- name: Restore CLI test-fixture cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: ${{ github.workspace }}/test/cli/test-fixtures/cache
key: ${{ runner.os }}-cli-test-cache-${{ hashFiles('test/cli/test-fixtures/cache.fingerprint') }}
- name: Download snapshot build
id: snapshot-cache
uses: actions/cache/restore@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
uses: actions/cache/restore@ab5e6d0c87105b4c9c2047343972218f562e4319 #v4.0.1
with:
path: |
snapshot
+45 -24
View File
@@ -54,6 +54,7 @@ For commercial support options with Syft or Grype, please [contact Anchore](http
- Ruby (gem)
- Rust (cargo.lock)
- Swift (cocoapods, swift-package-manager)
- Wordpress plugins
## Installation
@@ -121,7 +122,8 @@ syft <image> --scope all-layers
### Supported sources
Syft can generate an SBOM from a variety of sources:
Syft can generate an SBOM from a variety of sources including images, files, directories, and archives. Syft will attempt to
determine the type of source based on provided input, for example:
```bash
# catalog a container image archive (from the result of `docker image save ...`, `podman save ...`, or `skopeo copy` commands)
@@ -134,26 +136,24 @@ syft path/to/image.sif
syft path/to/dir
```
Sources can be explicitly provided with a scheme:
To explicitly specify the source behavior, use the `--from` flag. Allowable options are:
```
docker:yourrepo/yourimage:tag use images from the Docker daemon
podman:yourrepo/yourimage:tag use images from the Podman daemon
containerd:yourrepo/yourimage:tag use images from the Containerd daemon
docker-archive:path/to/yourimage.tar use a tarball from disk for archives created from "docker save"
oci-archive:path/to/yourimage.tar use a tarball from disk for OCI archives (from Skopeo or otherwise)
oci-dir:path/to/yourimage read directly from a path on disk for OCI layout directories (from Skopeo or otherwise)
singularity:path/to/yourimage.sif read directly from a Singularity Image Format (SIF) container on disk
dir:path/to/yourproject read directly from a path on disk (any directory)
file:path/to/yourproject/file read directly from a path on disk (any single file)
registry:yourrepo/yourimage:tag pull image directly from a registry (no container runtime required)
docker use images from the Docker daemon
podman use images from the Podman daemon
containerd use images from the Containerd daemon
docker-archive use a tarball from disk for archives created from "docker save"
oci-archive use a tarball from disk for OCI archives (from Skopeo or otherwise)
oci-dir read directly from a path on disk for OCI layout directories (from Skopeo or otherwise)
singularity read directly from a Singularity Image Format (SIF) container on disk
dir read directly from a path on disk (any directory)
file read directly from a path on disk (any single file)
registry pull image directly from a registry (no container runtime required)
```
If a source is not provided and Syft identifies the input as a potential image reference, Syft will attempt to resolve it using:
the Docker, Podman, and Containerd daemons followed by direct registry access, in that order.
If an image source is not provided and cannot be detected from the given reference it is assumed the image should be pulled from the Docker daemon.
If docker is not present, then the Podman daemon is attempted next, followed by reaching out directly to the image registry last.
This default behavior can be overridden with the `default-image-pull-source` configuration option (See [Configuration](https://github.com/anchore/syft#configuration) for more details).
This default behavior can be overridden with the `default-image-pull-source` configuration option (See [Configuration](#configuration) for more details).
### File selection
@@ -228,12 +228,12 @@ syft <a directory> --select-catalogers "python"
Use the default set of catalogers and add a cataloger to the set:
```bash
syft ... --catalogers "+sbom-cataloger"
syft ... --select-catalogers "+sbom-cataloger"
```
Use the default set of catalogers but remove any catalogers that deal with RPMs:
```bash
syft ... --catalogers "-rpm"
syft ... --select-catalogers "-rpm"
```
Only scan with catalogers that:
@@ -305,7 +305,7 @@ Where the `formats` available are:
## Using templates
Syft lets you define custom output formats, using [Go templates](https://pkg.go.dev/text/template). Here's how it works:
Syft lets you define custom output formats, using [Go templates](https://pkg.go.dev/text/template) relative to the Syft JSON output. Here's how it works:
- Define your format as a Go template, and save this template as a file.
@@ -319,9 +319,9 @@ Syft lets you define custom output formats, using [Go templates](https://pkg.go.
Here's what the `csv.tmpl` file might look like:
```gotemplate
"Package","Version Installed","Found by"
{{- range .Artifacts}}
"{{.Name}}","{{.Version}}","{{.FoundBy}}"
"Package","Version Installed", "Found by"
{{- range .artifacts}}
"{{.name}}","{{.version}}","{{.foundBy}}"
{{- end}}
```
@@ -338,6 +338,9 @@ Syft also includes a vast array of utility templating functions from [sprig](htt
Lastly, Syft has custom templating functions defined in `./syft/format/template/encoder.go` to help parse the passed-in JSON structs.
> [!NOTE]
> If you have templates being used before Syft v0.102.0 that are no longer working. This is because templating keys were relative to the internal go structs before this version whereas now the keys are relative to the Syft JSON output. To get the legacy behavior back you can set the `format.template.legacy` option to `true` in your configuration.
## Multiple outputs
Syft can also output _multiple_ files in differing formats by appending
@@ -548,7 +551,7 @@ catalogers:
default-catalogers: []
# add, remove, and filter the catalogers to be used
# SYFT_SELECT_CATALOGERS env var / --select-cataloger flag;
# SYFT_SELECT_CATALOGERS env var / --select-catalogers flag;
select-catalogers: []
# all format configuration
@@ -688,6 +691,24 @@ golang:
# SYFT_GOLANG_NOPROXY env var
no-proxy: ""
# the go main module version discovered from binaries built with the go compiler will
# always show (devel) as the version. Use these options to control heuristics to guess
# a more accurate version from the binary.
main-module-version:
# look for LD flags that appear to be setting a version (e.g. -X main.version=1.0.0)
# SYFT_GOLANG_MAIN_MODULE_VERSION_FROM_LD_FLAGS env var
from-ld-flags: true
# use the build settings (e.g. vcs.version & vcs.time) to craft a v0 pseudo version
# (e.g. v0.0.0-20220308212642-53e6d0aaf6fb) when a more accurate version cannot be found otherwise.
# SYFT_GOLANG_MAIN_MODULE_VERSION_FROM_BUILD_SETTINGS env var
from-build-settings: true
# search for semver-like strings in the binary contents.
# SYFT_GOLANG_MAIN_MODULE_VERSION_FROM_CONTENTS env var
from-contents: true
java:
maven-url: "https://repo1.maven.org/maven2"
max-parent-recursive-depth: 5
+12 -5
View File
@@ -266,6 +266,8 @@ tasks:
desc: Generate test fixture fingerprints
generates:
- cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint
- syft/file/cataloger/executable/test-fixtures/elf/cache.fingerprint
- syft/file/cataloger/executable/test-fixtures/shared-info/cache.fingerprint
- syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint
- syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint
- syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint
@@ -274,17 +276,20 @@ tasks:
- test/install/cache.fingerprint
- test/cli/test-fixtures/cache.fingerprint
cmds:
# for EXECUTABLE unit test fixtures
- "cd syft/file/cataloger/executable/test-fixtures/elf && make cache.fingerprint"
- "cd syft/file/cataloger/executable/test-fixtures/shared-info && make cache.fingerprint"
# for IMAGE integration test fixtures
- "cd cmd/syft/internal/test/integration/test-fixtures && make cache.fingerprint"
# for BINARY test fixtures
# for BINARY unit test fixtures
- "cd syft/pkg/cataloger/binary/test-fixtures && make cache.fingerprint"
# for JAVA BUILD test fixtures
# for JAVA BUILD unit test fixtures
- "cd syft/pkg/cataloger/java/test-fixtures/java-builds && make cache.fingerprint"
# for GO BINARY test fixtures
# for GO BINARY unit test fixtures
- "cd syft/pkg/cataloger/golang/test-fixtures/archs && make binaries.fingerprint"
# for RPM test fixtures
# for RPM unit test fixtures
- "cd syft/pkg/cataloger/redhat/test-fixtures && make rpms.fingerprint"
# for Kernel test fixtures
# for Kernel unit test fixtures
- "cd syft/pkg/cataloger/kernel/test-fixtures && make cache.fingerprint"
# for INSTALL test fixtures
- "cd test/install && make cache.fingerprint"
@@ -294,6 +299,8 @@ tasks:
fixtures:
desc: Generate test fixtures
cmds:
- "cd syft/file/cataloger/executable/test-fixtures/elf && make"
- "cd syft/file/cataloger/executable/test-fixtures/shared-info && make"
- "cd syft/pkg/cataloger/java/test-fixtures/java-builds && make"
- "cd syft/pkg/cataloger/redhat/test-fixtures && make"
- "cd syft/pkg/cataloger/binary/test-fixtures && make"
+2 -44
View File
@@ -8,13 +8,8 @@ import (
"github.com/spf13/cobra"
"github.com/anchore/clio"
"github.com/anchore/stereoscope"
handler "github.com/anchore/syft/cmd/syft/cli/ui"
"github.com/anchore/syft/cmd/syft/internal"
"github.com/anchore/syft/cmd/syft/internal/commands"
"github.com/anchore/syft/cmd/syft/internal/ui"
"github.com/anchore/syft/internal/bus"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/redact"
)
// Application constructs the `syft packages` command and aliases the root command to `syft packages`.
@@ -34,44 +29,7 @@ func Command(id clio.Identification) *cobra.Command {
}
func create(id clio.Identification, out io.Writer) (clio.Application, *cobra.Command) {
clioCfg := clio.NewSetupConfig(id).
WithGlobalConfigFlag(). // add persistent -c <path> for reading an application config from
WithGlobalLoggingFlags(). // add persistent -v and -q flags tied to the logging config
WithConfigInRootHelp(). // --help on the root command renders the full application config in the help text
WithUIConstructor(
// select a UI based on the logging configuration and state of stdin (if stdin is a tty)
func(cfg clio.Config) ([]clio.UI, error) {
noUI := ui.None(out, cfg.Log.Quiet)
if !cfg.Log.AllowUI(os.Stdin) || cfg.Log.Quiet {
return []clio.UI{noUI}, nil
}
return []clio.UI{
ui.New(out, cfg.Log.Quiet,
handler.New(handler.DefaultHandlerConfig()),
),
noUI,
}, nil
},
).
WithInitializers(
func(state *clio.State) error {
// clio is setting up and providing the bus, redact store, and logger to the application. Once loaded,
// we can hoist them into the internal packages for global use.
stereoscope.SetBus(state.Bus)
bus.Set(state.Bus)
redact.Set(state.RedactStore)
log.Set(state.Logger)
stereoscope.SetLogger(state.Logger)
return nil
},
).
WithPostRuns(func(state *clio.State, err error) {
stereoscope.Cleanup()
})
clioCfg := internal.AppClioSetupConfig(id, out)
app := clio.New(*clioCfg)
+55
View File
@@ -0,0 +1,55 @@
package internal
import (
"io"
"os"
"github.com/anchore/clio"
"github.com/anchore/stereoscope"
ui2 "github.com/anchore/syft/cmd/syft/cli/ui"
"github.com/anchore/syft/cmd/syft/internal/ui"
"github.com/anchore/syft/internal/bus"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/redact"
)
func AppClioSetupConfig(id clio.Identification, out io.Writer) *clio.SetupConfig {
clioCfg := clio.NewSetupConfig(id).
WithGlobalConfigFlag(). // add persistent -c <path> for reading an application config from
WithGlobalLoggingFlags(). // add persistent -v and -q flags tied to the logging config
WithConfigInRootHelp(). // --help on the root command renders the full application config in the help text
WithUIConstructor(
// select a UI based on the logging configuration and state of stdin (if stdin is a tty)
func(cfg clio.Config) ([]clio.UI, error) {
noUI := ui.None(out, cfg.Log.Quiet)
if !cfg.Log.AllowUI(os.Stdin) || cfg.Log.Quiet {
return []clio.UI{noUI}, nil
}
return []clio.UI{
ui.New(out, cfg.Log.Quiet,
ui2.New(ui2.DefaultHandlerConfig()),
),
noUI,
}, nil
},
).
WithInitializers(
func(state *clio.State) error {
// clio is setting up and providing the bus, redact store, and logger to the application. Once loaded,
// we can hoist them into the internal packages for global use.
stereoscope.SetBus(state.Bus)
bus.Set(state.Bus)
redact.Set(state.RedactStore)
log.Set(state.Logger)
stereoscope.SetLogger(state.Logger)
return nil
},
).
WithPostRuns(func(_ *clio.State, _ error) {
stereoscope.Cleanup()
})
return clioCfg
}
+7 -10
View File
@@ -13,6 +13,7 @@ import (
"github.com/wagoodman/go-progress"
"github.com/anchore/clio"
"github.com/anchore/stereoscope"
"github.com/anchore/syft/cmd/syft/internal/options"
"github.com/anchore/syft/cmd/syft/internal/ui"
"github.com/anchore/syft/internal"
@@ -26,7 +27,6 @@ import (
"github.com/anchore/syft/syft/format/spdxtagvalue"
"github.com/anchore/syft/syft/format/syftjson"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)
const (
@@ -42,7 +42,7 @@ type attestOptions struct {
options.Output `yaml:",inline" mapstructure:",squash"`
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
options.Catalog `yaml:",inline" mapstructure:",squash"`
options.Attest `yaml:",inline" mapstructure:",squash"`
Attest options.Attest `yaml:"attest" mapstructure:"attest"`
}
func Attest(app clio.Application) *cobra.Command {
@@ -247,7 +247,11 @@ func predicateType(outputName string) string {
}
func generateSBOMForAttestation(ctx context.Context, id clio.Identification, opts *options.Catalog, userInput string) (*sbom.SBOM, error) {
src, err := getSource(opts, userInput, onlyContainerImages)
if len(opts.From) > 1 || (len(opts.From) == 1 && opts.From[0] != stereoscope.RegistryTag) {
return nil, fmt.Errorf("attest requires use of an OCI registry directly, one or more of the specified sources is unsupported: %v", opts.From)
}
src, err := getSource(ctx, opts, userInput, stereoscope.RegistryTag)
if err != nil {
return nil, err
@@ -273,13 +277,6 @@ func generateSBOMForAttestation(ctx context.Context, id clio.Identification, opt
return s, nil
}
func onlyContainerImages(d *source.Detection) error {
if !d.IsContainerImage() {
return fmt.Errorf("attestations are only supported for oci images at this time")
}
return nil
}
func commandExists(cmd string) bool {
_, err := exec.LookPath(cmd)
return err == nil
+62
View File
@@ -4,16 +4,21 @@ import (
"bytes"
"context"
"fmt"
"io"
"os/exec"
"regexp"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/scylladb/go-set/strset"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/clio"
"github.com/anchore/clio/cliotestutils"
"github.com/anchore/syft/cmd/syft/internal"
"github.com/anchore/syft/cmd/syft/internal/options"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
@@ -267,3 +272,60 @@ func Test_buildSBOMForAttestation(t *testing.T) {
})
}
}
func Test_attestCLIWiring(t *testing.T) {
id := clio.Identification{
Name: "syft",
Version: "testing",
}
cfg := internal.AppClioSetupConfig(id, io.Discard)
tests := []struct {
name string
assertionFunc func(*testing.T, *cobra.Command, []string, ...any)
wantOpts attestOptions
args []string
env map[string]string
}{
{
name: "key flag is accepted",
args: []string{"some-image:some-tag", "--key", "some-cosign-key.key"},
assertionFunc: hasAttestOpts(options.Attest{Key: "some-cosign-key.key"}),
},
{
name: "key password is read from env",
args: []string{"some-image:some-tag", "--key", "cosign.key"},
env: map[string]string{
"SYFT_ATTEST_PASSWORD": "some-password",
},
assertionFunc: hasAttestOpts(options.Attest{
Key: "cosign.key",
Password: "some-password",
}),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.env != nil {
for k, v := range tt.env {
t.Setenv(k, v)
}
}
app := cliotestutils.NewApplication(t, cfg, tt.assertionFunc)
cmd := Attest(app)
cmd.SetArgs(tt.args)
err := cmd.Execute()
assert.NoError(t, err)
})
}
}
func hasAttestOpts(wantOpts options.Attest) cliotestutils.AssertionFunc {
return func(t *testing.T, _ *cobra.Command, _ []string, cfgs ...any) {
assert.Equal(t, len(cfgs), 1)
attestOpts, ok := cfgs[0].(*attestOptions)
require.True(t, ok)
if d := cmp.Diff(wantOpts, attestOpts.Attest); d != "" {
t.Errorf("mismatched attest options (-want +got):\n%s", d)
}
}
}
+1 -1
View File
@@ -46,7 +46,7 @@ func CatalogerList(app clio.Application) *cobra.Command {
return app.SetupCommand(&cobra.Command{
Use: "list [OPTIONS]",
Short: "List available catalogers",
RunE: func(cmd *cobra.Command, args []string) error {
RunE: func(_ *cobra.Command, _ []string) error {
return runCatalogerList(opts)
},
}, opts)
@@ -0,0 +1,20 @@
package commands
import (
"os"
"testing"
gologgerredact "github.com/anchore/go-logger/adapter/redact"
"github.com/anchore/syft/internal/redact"
)
func TestMain(m *testing.M) {
// Initialize global state needed to test clio/cobra commands directly
// Should be kept minimal.
// Initialize redact store once for all tests in the commands package
// Redact store must be wired up here because syft will panic unless
// a redact store is wired up exactly once
redact.Set(gologgerredact.NewStore())
os.Exit(m.Run())
}
+1 -1
View File
@@ -47,7 +47,7 @@ func Convert(app clio.Application) *cobra.Command {
}),
Args: validateConvertArgs,
PreRunE: applicationUpdateCheck(id, &opts.UpdateCheck),
RunE: func(cmd *cobra.Command, args []string) error {
RunE: func(_ *cobra.Command, args []string) error {
restoreStdout := ui.CaptureStdoutToTraceLog()
defer restoreStdout()
+43 -36
View File
@@ -13,6 +13,8 @@ import (
"gopkg.in/yaml.v3"
"github.com/anchore/clio"
"github.com/anchore/go-collections"
"github.com/anchore/stereoscope"
"github.com/anchore/stereoscope/pkg/image"
"github.com/anchore/syft/cmd/syft/internal/options"
"github.com/anchore/syft/cmd/syft/internal/ui"
@@ -24,6 +26,7 @@ import (
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
"github.com/anchore/syft/syft/source/sourceproviders"
)
const (
@@ -162,14 +165,23 @@ func validateArgs(cmd *cobra.Command, args []string, error string) error {
return cobra.MaximumNArgs(1)(cmd, args)
}
// nolint:funlen
func runScan(ctx context.Context, id clio.Identification, opts *scanOptions, userInput string) error {
writer, err := opts.SBOMWriter()
if err != nil {
return err
}
src, err := getSource(&opts.Catalog, userInput)
sources := opts.From
if len(sources) == 0 {
// extract a scheme if it matches any provider tag; this is a holdover for compatibility, using the --from flag is recommended
explicitSource, newUserInput := stereoscope.ExtractSchemeSource(userInput, allSourceProviderTags()...)
if explicitSource != "" {
sources = append(sources, explicitSource)
userInput = newUserInput
}
}
src, err := getSource(ctx, &opts.Catalog, userInput, sources...)
if err != nil {
return err
@@ -199,23 +211,21 @@ func runScan(ctx context.Context, id clio.Identification, opts *scanOptions, use
return nil
}
func getSource(opts *options.Catalog, userInput string, filters ...func(*source.Detection) error) (source.Source, error) {
detection, err := source.Detect(
userInput,
source.DetectConfig{
DefaultImageSource: opts.Source.Image.DefaultPullSource,
},
)
if err != nil {
return nil, fmt.Errorf("could not deteremine source: %w", err)
}
for _, filter := range filters {
if err := filter(detection); err != nil {
return nil, err
}
}
func getSource(ctx context.Context, opts *options.Catalog, userInput string, sources ...string) (source.Source, error) {
cfg := syft.DefaultGetSourceConfig().
WithRegistryOptions(opts.Registry.ToOptions()).
WithAlias(source.Alias{
Name: opts.Source.Name,
Version: opts.Source.Version,
}).
WithExcludeConfig(source.ExcludeConfig{
Paths: opts.Exclusions,
}).
WithBasePath(opts.Source.BasePath).
WithSources(sources...).
WithDefaultImagePullSource(opts.Source.Image.DefaultPullSource)
var err error
var platform *image.Platform
if opts.Platform != "" {
@@ -223,29 +233,22 @@ func getSource(opts *options.Catalog, userInput string, filters ...func(*source.
if err != nil {
return nil, fmt.Errorf("invalid platform: %w", err)
}
cfg = cfg.WithPlatform(platform)
}
hashers, err := file.Hashers(opts.Source.File.Digests...)
if opts.Source.File.Digests != nil {
hashers, err := file.Hashers(opts.Source.File.Digests...)
if err != nil {
return nil, fmt.Errorf("invalid hash algorithm: %w", err)
}
cfg = cfg.WithDigestAlgorithms(hashers...)
}
src, err := syft.GetSource(ctx, userInput, cfg)
if err != nil {
return nil, fmt.Errorf("invalid hash algorithm: %w", err)
return nil, fmt.Errorf("could not determine source: %w", err)
}
src, err := detection.NewSource(
source.DetectionSourceConfig{
Alias: source.Alias{
Name: opts.Source.Name,
Version: opts.Source.Version,
},
RegistryOptions: opts.Registry.ToOptions(),
Platform: platform,
Exclude: source.ExcludeConfig{
Paths: opts.Exclusions,
},
DigestAlgorithms: hashers,
BasePath: opts.Source.BasePath,
},
)
if err != nil {
if userInput == "power-user" {
bus.Notify("Note: the 'power-user' command has been removed.")
@@ -445,3 +448,7 @@ func getHintPhrase(expErr task.ErrInvalidExpression) string {
func trimOperation(x string) string {
return strings.TrimLeft(x, "+-")
}
func allSourceProviderTags() []string {
return collections.TaggedValueSet[source.Provider]{}.Join(sourceproviders.All("", nil)...).Tags()
}
+1 -1
View File
@@ -28,7 +28,7 @@ var latestAppVersionURL = struct {
}
func applicationUpdateCheck(id clio.Identification, check *options.UpdateCheck) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
return func(_ *cobra.Command, _ []string) error {
if check.CheckForAppUpdate {
checkForApplicationUpdate(id)
}
+3 -1
View File
@@ -4,6 +4,8 @@ import (
"github.com/anchore/clio"
)
var _ clio.FlagAdder = (*Attest)(nil)
type Attest struct {
// IMPORTANT: do not show the attestation key/password in any YAML/JSON output (sensitive information)
Key secret `yaml:"key" json:"key" mapstructure:"key"`
@@ -12,6 +14,6 @@ type Attest struct {
var _ clio.FlagAdder = (*Attest)(nil)
func (o Attest) AddFlags(flags clio.FlagSet) {
func (o *Attest) AddFlags(flags clio.FlagSet) {
flags.StringVarP((*string)(&o.Key), "key", "k", "the key to use for the attestation")
}
+20 -2
View File
@@ -15,6 +15,7 @@ import (
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/cataloging/filecataloging"
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
"github.com/anchore/syft/syft/file/cataloger/executable"
"github.com/anchore/syft/syft/file/cataloger/filecontent"
"github.com/anchore/syft/syft/pkg/cataloger/binary"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
@@ -45,6 +46,7 @@ type Catalog struct {
// configuration for the source (the subject being analyzed)
Registry registryConfig `yaml:"registry" json:"registry" mapstructure:"registry"`
From []string `yaml:"from" json:"from" mapstructure:"from"`
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
Source sourceConfig `yaml:"source" json:"source" mapstructure:"source"`
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
@@ -61,6 +63,7 @@ func DefaultCatalog() Catalog {
Scope: source.SquashedScope.String(),
Package: defaultPackageConfig(),
LinuxKernel: defaultLinuxKernelConfig(),
Golang: defaultGolangConfig(),
File: defaultFileConfig(),
Relationships: defaultRelationshipsConfig(),
Source: defaultSourceConfig(),
@@ -111,6 +114,10 @@ func (cfg Catalog) ToFilesConfig() filecataloging.Config {
Globs: cfg.File.Content.Globs,
SkipFilesAboveSize: cfg.File.Content.SkipFilesAboveSize,
},
Executable: executable.Config{
MIMETypes: executable.DefaultConfig().MIMETypes,
Globs: cfg.File.Executable.Globs,
},
}
}
@@ -120,13 +127,19 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
IncludeUnindexedArchives: cfg.Package.SearchUnindexedArchives,
}
return pkgcataloging.Config{
Binary: binary.DefaultCatalogerConfig(),
Binary: binary.DefaultClassifierCatalogerConfig(),
Golang: golang.DefaultCatalogerConfig().
WithSearchLocalModCacheLicenses(cfg.Golang.SearchLocalModCacheLicenses).
WithLocalModCacheDir(cfg.Golang.LocalModCacheDir).
WithSearchRemoteLicenses(cfg.Golang.SearchRemoteLicenses).
WithProxy(cfg.Golang.Proxy).
WithNoProxy(cfg.Golang.NoProxy),
WithNoProxy(cfg.Golang.NoProxy).
WithMainModuleVersion(
golang.DefaultMainModuleVersionConfig().
WithFromContents(cfg.Golang.MainModuleVersion.FromContents).
WithFromBuildSettings(cfg.Golang.MainModuleVersion.FromBuildSettings).
WithFromLDFlags(cfg.Golang.MainModuleVersion.FromLDFlags),
),
JavaScript: javascript.DefaultCatalogerConfig().
WithSearchRemoteLicenses(cfg.JavaScript.SearchRemoteLicenses).
WithNpmBaseURL(cfg.JavaScript.NpmBaseURL),
@@ -151,6 +164,9 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
flags.StringVarP(&cfg.Scope, "scope", "s",
fmt.Sprintf("selection of layers to catalog, options=%v", validScopeValues))
flags.StringArrayVarP(&cfg.From, "from", "",
"specify the source behavior to use (e.g. docker, registry, oci-dir, ...)")
flags.StringVarP(&cfg.Platform, "platform", "",
"an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux')")
@@ -208,6 +224,8 @@ func (cfg *Catalog) PostLoad() error {
return out
}
cfg.From = flatten(cfg.From)
cfg.Catalogers = flatten(cfg.Catalogers)
cfg.DefaultCatalogers = flatten(cfg.DefaultCatalogers)
cfg.SelectCatalogers = flatten(cfg.SelectCatalogers)
+10 -2
View File
@@ -11,8 +11,9 @@ import (
)
type fileConfig struct {
Metadata fileMetadata `yaml:"metadata" json:"metadata" mapstructure:"metadata"`
Content fileContent `yaml:"content" json:"content" mapstructure:"content"`
Metadata fileMetadata `yaml:"metadata" json:"metadata" mapstructure:"metadata"`
Content fileContent `yaml:"content" json:"content" mapstructure:"content"`
Executable fileExecutable `yaml:"executable" json:"executable" mapstructure:"executable"`
}
type fileMetadata struct {
@@ -25,6 +26,10 @@ type fileContent struct {
Globs []string `yaml:"globs" json:"globs" mapstructure:"globs"`
}
type fileExecutable struct {
Globs []string `yaml:"globs" json:"globs" mapstructure:"globs"`
}
func defaultFileConfig() fileConfig {
return fileConfig{
Metadata: fileMetadata{
@@ -34,6 +39,9 @@ func defaultFileConfig() fileConfig {
Content: fileContent{
SkipFilesAboveSize: 250 * intFile.KB,
},
Executable: fileExecutable{
Globs: nil,
},
}
}
+5 -3
View File
@@ -3,6 +3,7 @@ package options
import (
"github.com/anchore/clio"
"github.com/anchore/syft/syft/format"
"github.com/anchore/syft/syft/format/spdxtagvalue"
"github.com/anchore/syft/syft/sbom"
)
@@ -41,9 +42,10 @@ func (o Format) Encoders() ([]sbom.FormatEncoder, error) {
return format.EncodersConfig{
Template: o.Template.config(),
SyftJSON: o.SyftJSON.config(),
SPDXJSON: o.SPDXJSON.config(format.AllVersions), // we support multiple versions, not just a single version
CyclonedxJSON: o.CyclonedxJSON.config(format.AllVersions), // we support multiple versions, not just a single version
CyclonedxXML: o.CyclonedxXML.config(format.AllVersions), // we support multiple versions, not just a single version
SPDXJSON: o.SPDXJSON.config(format.AllVersions), // we support multiple versions, not just a single version
SPDXTagValue: spdxtagvalue.EncoderConfig{Version: format.AllVersions}, // we support multiple versions, not just a single version
CyclonedxJSON: o.CyclonedxJSON.config(format.AllVersions), // we support multiple versions, not just a single version
CyclonedxXML: o.CyclonedxXML.config(format.AllVersions), // we support multiple versions, not just a single version
}.Encoders()
}
+34 -5
View File
@@ -1,9 +1,38 @@
package options
import (
"strings"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
)
type golangConfig struct {
SearchLocalModCacheLicenses bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"`
LocalModCacheDir string `json:"local-mod-cache-dir" yaml:"local-mod-cache-dir" mapstructure:"local-mod-cache-dir"`
SearchRemoteLicenses bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
Proxy string `json:"proxy" yaml:"proxy" mapstructure:"proxy"`
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
SearchLocalModCacheLicenses bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"`
LocalModCacheDir string `json:"local-mod-cache-dir" yaml:"local-mod-cache-dir" mapstructure:"local-mod-cache-dir"`
SearchRemoteLicenses bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
Proxy string `json:"proxy" yaml:"proxy" mapstructure:"proxy"`
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"`
}
type golangMainModuleVersionConfig struct {
FromLDFlags bool `json:"from-ld-flags" yaml:"from-ld-flags" mapstructure:"from-ld-flags"`
FromContents bool `json:"from-contents" yaml:"from-contents" mapstructure:"from-contents"`
FromBuildSettings bool `json:"from-build-settings" yaml:"from-build-settings" mapstructure:"from-build-settings"`
}
func defaultGolangConfig() golangConfig {
def := golang.DefaultCatalogerConfig()
return golangConfig{
SearchLocalModCacheLicenses: def.SearchLocalModCacheLicenses,
LocalModCacheDir: def.LocalModCacheDir,
SearchRemoteLicenses: def.SearchRemoteLicenses,
Proxy: strings.Join(def.Proxies, ","),
NoProxy: strings.Join(def.NoProxy, ","),
MainModuleVersion: golangMainModuleVersionConfig{
FromLDFlags: def.MainModuleVersion.FromLDFlags,
FromContents: def.MainModuleVersion.FromContents,
FromBuildSettings: def.MainModuleVersion.FromBuildSettings,
},
}
}
+7 -4
View File
@@ -6,6 +6,8 @@ import (
"strings"
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/syft/source/sourceproviders"
)
type sourceConfig struct {
@@ -25,12 +27,13 @@ type imageSource struct {
}
func defaultSourceConfig() sourceConfig {
var digests []string
for _, alg := range sourceproviders.DefaultConfig().DigestAlgorithms {
digests = append(digests, alg.String())
}
return sourceConfig{
File: fileSource{
Digests: []string{"sha256"},
},
Image: imageSource{
DefaultPullSource: "",
Digests: digests,
},
}
}
@@ -368,6 +368,14 @@ var dirOnlyTestCases = []testCase{
"unicode_util_compat": "0.7.0",
},
},
{
name: "find ErLang OTP applications",
pkgType: pkg.ErlangOTPPkg,
pkgLanguage: pkg.Erlang,
pkgInfo: map[string]string{
"accept": "0.3.5",
},
},
{
name: "find swift package manager packages",
pkgType: pkg.SwiftPkg,
@@ -444,4 +452,12 @@ var commonTestCases = []testCase{
"glibc": "2.34-210",
},
},
{
name: "find wordpress plugins",
pkgType: pkg.WordpressPluginPkg,
pkgLanguage: pkg.PHP,
pkgInfo: map[string]string{
"Akismet Anti-spam: Spam Protection": "5.3",
},
},
}
@@ -22,15 +22,11 @@ func BenchmarkImagePackageCatalogers(b *testing.B) {
tarPath := imagetest.GetFixtureImageTarPath(b, fixtureImageName)
// get the source object for the image
userInput := "docker-archive:" + tarPath
detection, err := source.Detect(userInput, source.DefaultDetectConfig())
require.NoError(b, err)
theSource, err := detection.NewSource(source.DefaultDetectionSourceConfig())
theSource, err := syft.GetSource(context.Background(), tarPath, syft.DefaultGetSourceConfig().WithSources("docker-archive"))
require.NoError(b, err)
b.Cleanup(func() {
theSource.Close()
require.NoError(b, theSource.Close())
})
// build the SBOM
@@ -57,8 +53,8 @@ func TestPkgCoverageImage(t *testing.T) {
definedLanguages.Remove(pkg.Swift.String())
definedLanguages.Remove(pkg.CPP.String())
definedLanguages.Remove(pkg.Haskell.String())
definedLanguages.Remove(pkg.Erlang.String())
definedLanguages.Remove(pkg.Elixir.String())
definedLanguages.Remove(pkg.Erlang.String())
observedPkgs := strset.New()
definedPkgs := strset.New()
@@ -71,6 +67,7 @@ func TestPkgCoverageImage(t *testing.T) {
definedPkgs.Remove(string(pkg.GoModulePkg))
definedPkgs.Remove(string(pkg.RustPkg))
definedPkgs.Remove(string(pkg.DartPubPkg))
definedPkgs.Remove(string(pkg.ErlangOTPPkg))
definedPkgs.Remove(string(pkg.CocoapodsPkg))
definedPkgs.Remove(string(pkg.ConanPkg))
definedPkgs.Remove(string(pkg.HackagePkg))
@@ -122,7 +119,6 @@ func TestPkgCoverageImage(t *testing.T) {
}
t.Fatalf("unexpected package count: %d!=%d", pkgCount, len(c.pkgInfo))
}
})
}
@@ -210,7 +206,6 @@ func TestPkgCoverageDirectory(t *testing.T) {
}
t.Fatalf("unexpected package count: %d!=%d", actualPkgCount, len(test.pkgInfo))
}
})
}
@@ -248,7 +243,6 @@ func TestPkgCoverageImage_HasEvidence(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
for a := range sbom.Artifacts.Packages.Enumerate(c.pkgType) {
assert.NotEmpty(t, a.Locations.ToSlice(), "package %q has no locations (type=%q)", a.Name, a.Type)
for _, l := range a.Locations.ToSlice() {
@@ -258,7 +252,6 @@ func TestPkgCoverageImage_HasEvidence(t *testing.T) {
}
}
}
})
}
@@ -278,7 +271,6 @@ func TestPkgCoverageDirectory_HasEvidence(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
for a := range sbom.Artifacts.Packages.Enumerate(c.pkgType) {
assert.NotEmpty(t, a.Locations.ToSlice(), "package %q has no locations (type=%q)", a.Name, a.Type)
for _, l := range a.Locations.ToSlice() {
@@ -288,7 +280,6 @@ func TestPkgCoverageDirectory_HasEvidence(t *testing.T) {
}
}
}
})
}
@@ -19,7 +19,7 @@ func TestGolangCompilerDetection(t *testing.T) {
name: "syft can detect a single golang compiler given the golang base image",
image: "image-golang-compiler",
expectedCompilers: []string{"go1.18.10"},
expectedCPE: []cpe.CPE{cpe.Must("cpe:2.3:a:golang:go:1.18.10:-:*:*:*:*:*:*")},
expectedCPE: []cpe.CPE{cpe.Must("cpe:2.3:a:golang:go:1.18.10:-:*:*:*:*:*:*", cpe.GeneratedSource)},
expectedPURL: []string{"pkg:golang/stdlib@1.18.10"},
},
}
@@ -51,7 +51,6 @@ var noAssertion = map[string]string{
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar": "pkg:maven/sdk/sdk@3.0",
// syft generates incorrect purls
"/packages/kafka_2.13-3.2.2.jar": "pkg:maven/org.apache.kafka/kafka_2.13@3.2.2",
"/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6",
"/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0",
"/packages/hudson.war:WEB-INF/lib/asm-2.2.3.jar": "pkg:maven/asm/asm@2.2.3",
@@ -366,10 +365,10 @@ var expectedPURLs = map[string]string{
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar": "pkg:maven/org.yaml/snakeyaml@1.18",
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:jline:jline": "pkg:maven/jline/jline@2.11",
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:rubygems:jruby-readline": "pkg:maven/rubygems/jruby-readline@1.2.0",
"/packages/jruby-stdlib-9.1.15.0.jar": "pkg:maven/org.jruby/jruby-stdlib@9.1.15.0",
"/packages/jsch-0.1.55.jar": "pkg:maven/com.jcraft/jsch@0.1.55",
"/packages/junit-4.13.1.jar": "pkg:maven/junit/junit@4.13.1",
// "/packages/kafka_2.13-3.2.2.jar": "pkg:maven/org.apache.kafka/kafka_2.13@3.2.2",
"/packages/jruby-stdlib-9.1.15.0.jar": "pkg:maven/org.jruby/jruby-stdlib@9.1.15.0",
"/packages/jsch-0.1.55.jar": "pkg:maven/com.jcraft/jsch@0.1.55",
"/packages/junit-4.13.1.jar": "pkg:maven/junit/junit@4.13.1",
"/packages/kafka_2.13-3.2.2.jar": "pkg:maven/org.apache.kafka/kafka_2.13@3.2.2",
"/packages/keycloak-core-22.0.2.jar": "pkg:maven/org.keycloak/keycloak-core@22.0.2",
"/packages/log4j-1.2.16.jar": "pkg:maven/log4j/log4j@1.2.16",
"/packages/log4j-core-2.17.0.jar": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.0",
@@ -31,7 +31,9 @@ func Test_packageCatalogerExports(t *testing.T) {
for pkg, expected := range expectAtLeast {
actual, ok := exports[pkg]
require.True(t, ok, pkg)
require.True(t, expected.IsSubset(actual.Names()), pkg)
if !assert.True(t, actual.Names().IsSubset(expected), pkg) {
t.Logf("missing: %s", strset.SymmetricDifference(expected, actual.Names()))
}
}
}
@@ -0,0 +1,10 @@
{application,accept,
[{description,"Accept header(s) for Erlang/Elixir"},
{vsn,"0.3.5"},
{registered,[]},
{applications,[kernel,stdlib]},
{env,[]},
{modules, ['accept_encoding_header','accept_header','accept_neg','accept_parser']},
{maintainers,["Ilya Khaprov"]},
{licenses,["MIT"]},
{links,[{"Github","https://github.com/deadtrickster/accept"}]}]}.
@@ -0,0 +1,17 @@
<?php
/**
* @package Akismet
*/
/*
Plugin Name:Akismet Anti-spam: Spam Protection
Plugin URI: https://akismet.com/
Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. Akismet Anti-spam keeps your site protected even while you sleep. To get started: activate the Akismet plugin and then go to your Akismet Settings page to set up your API key.
Version: 5.3
Requires at least: 5.8
Requires PHP: 5.6.20
Author: Automattic - Anti-spam Team
Author URI: https://automattic.com/wordpress-plugins/
License: GPLv2 or later
Text Domain: akismet
*/
// rest of plugin's code ...
@@ -34,17 +34,13 @@ func catalogFixtureImageWithConfig(t *testing.T, fixtureImageName string, cfg *s
// get the fixture image tar file
imagetest.GetFixtureImage(t, "docker-archive", fixtureImageName)
tarPath := imagetest.GetFixtureImageTarPath(t, fixtureImageName)
userInput := "docker-archive:" + tarPath
// get the source to build an SBOM against
detection, err := source.Detect(userInput, source.DefaultDetectConfig())
require.NoError(t, err)
theSource, err := detection.NewSource(source.DefaultDetectionSourceConfig())
theSource, err := syft.GetSource(context.Background(), tarPath, syft.DefaultGetSourceConfig().WithSources("docker-archive"))
require.NoError(t, err)
t.Cleanup(func() {
theSource.Close()
require.NoError(t, theSource.Close())
})
s, err := syft.CreateSBOM(context.Background(), theSource, cfg)
@@ -71,14 +67,10 @@ func catalogDirectoryWithConfig(t *testing.T, dir string, cfg *syft.CreateSBOMCo
cfg.CatalogerSelection = cfg.CatalogerSelection.WithDefaults(pkgcataloging.DirectoryTag)
// get the source to build an sbom against
userInput := "dir:" + dir
detection, err := source.Detect(userInput, source.DefaultDetectConfig())
require.NoError(t, err)
theSource, err := detection.NewSource(source.DefaultDetectionSourceConfig())
theSource, err := syft.GetSource(context.Background(), dir, syft.DefaultGetSourceConfig().WithSources("dir"))
require.NoError(t, err)
t.Cleanup(func() {
theSource.Close()
require.NoError(t, theSource.Close())
})
// build the SBOM
+15
View File
@@ -0,0 +1,15 @@
# Syft API Examples
This directory contains examples of how to use the Syft API.
- `create_simple_sbom`: Create a simple SBOM from scratch
- `create_custom_sbom`: Create an SBOM using as much custom configuration as possible, including a custom cataloger implementation
- `decode_sbom`: Take an existing SBOM file (of arbitrary format) and decode it into a Syft SBOM object
- `source_detection`: Shows how to detect what to catalog automatically from a user string (e.g. container image vs directory)
- `source_from_image`: Construct a source from a only a container image
You can run any of these examples from this directory with:
```bash
go run ./DIRECTORY_NAME
```
@@ -0,0 +1,127 @@
package main
import (
"context"
"fmt"
"io"
"path"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
)
/*
This is a contrived cataloger that attempts to capture useful APK files from the image as if it were a package.
This isn't a real cataloger, but it is a good example of how to use API elements to create a custom cataloger.
*/
var _ pkg.Cataloger = (*alpineConfigurationCataloger)(nil)
type alpineConfigurationCataloger struct {
}
func newAlpineConfigurationCataloger() pkg.Cataloger {
return alpineConfigurationCataloger{}
}
func (m alpineConfigurationCataloger) Name() string {
return "apk-configuration-cataloger"
}
func (m alpineConfigurationCataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
version, versionLocations, err := getVersion(resolver)
if err != nil {
return nil, nil, fmt.Errorf("unable to get alpine version: %w", err)
}
if len(versionLocations) == 0 {
// this doesn't mean we should stop cataloging, just that we don't have a version to use, thus no package to raise up
return nil, nil, nil
}
metadata, metadataLocations, err := newAlpineConfiguration(resolver)
if err != nil {
return nil, nil, err
}
var locations []file.Location
locations = append(locations, versionLocations...)
locations = append(locations, metadataLocations...)
p := newPackage(version, *metadata, locations...)
return []pkg.Package{p}, nil, nil
}
func newPackage(version string, metadata AlpineConfiguration, locations ...file.Location) pkg.Package {
return pkg.Package{
Name: "alpine-configuration",
Version: version,
Locations: file.NewLocationSet(locations...),
Type: pkg.Type("system-configuration"), // you can make up your own package type here or use an existing one
Metadata: metadata,
}
}
func newAlpineConfiguration(resolver file.Resolver) (*AlpineConfiguration, []file.Location, error) {
var locations []file.Location
keys, keyLocations, err := getAPKKeys(resolver)
if err != nil {
return nil, nil, err
}
locations = append(locations, keyLocations...)
return &AlpineConfiguration{
APKKeys: keys,
}, locations, nil
}
func getVersion(resolver file.Resolver) (string, []file.Location, error) {
locations, err := resolver.FilesByPath("/etc/alpine-release")
if err != nil {
return "", nil, fmt.Errorf("unable to get alpine version: %w", err)
}
if len(locations) == 0 {
return "", nil, nil
}
reader, err := resolver.FileContentsByLocation(locations[0])
if err != nil {
return "", nil, fmt.Errorf("unable to read alpine version: %w", err)
}
version, err := io.ReadAll(reader)
if err != nil {
return "", nil, fmt.Errorf("unable to read alpine version: %w", err)
}
return string(version), locations, nil
}
func getAPKKeys(resolver file.Resolver) (map[string]string, []file.Location, error) {
// name-to-content values
keyContent := make(map[string]string)
locations, err := resolver.FilesByGlob("/etc/apk/keys/*.rsa.pub")
if err != nil {
return nil, nil, fmt.Errorf("unable to get apk keys: %w", err)
}
for _, location := range locations {
basename := path.Base(location.RealPath)
reader, err := resolver.FileContentsByLocation(location)
content, err := io.ReadAll(reader)
if err != nil {
return nil, nil, fmt.Errorf("unable to read apk key content at %s: %w", location.RealPath, err)
}
keyContent[basename] = string(content)
}
return keyContent, locations, nil
}
type AlpineConfiguration struct {
APKKeys map[string]string `json:"apkKeys" yaml:"apkKeys"`
// Add more data you want to capture as part of the package metadata here...
}
+128
View File
@@ -0,0 +1,128 @@
package main
import (
"context"
"crypto"
"fmt"
"os"
"gopkg.in/yaml.v3"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/cataloging/filecataloging"
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)
const defaultImage = "alpine:3.19"
func main() {
// automagically get a source.Source for arbitrary string input
src := getSource(imageReference())
// will catalog the given source and return a SBOM keeping in mind several configurable options
sbom := getSBOM(src)
// show a simple package summary
summarize(sbom)
// show the alpine-configuration cataloger results
showAlpineConfiguration(sbom)
}
func imageReference() string {
// read an image string reference from the command line or use a default
if len(os.Args) > 1 {
return os.Args[1]
}
return defaultImage
}
func getSource(input string) source.Source {
fmt.Println("detecting source type for input:", input, "...")
src, err := syft.GetSource(context.Background(), input, nil)
if err != nil {
panic(err)
}
return src
}
func getSBOM(src source.Source) sbom.SBOM {
fmt.Println("creating SBOM...")
cfg := syft.DefaultCreateSBOMConfig().
// run the catalogers in parallel (5 at a time concurrently max)
WithParallelism(5).
// bake a specific tool name and version into the SBOM
WithTool("my-tool", "v1.0").
// catalog all files with 3 digests
WithFilesConfig(
filecataloging.DefaultConfig().
WithSelection(file.AllFilesSelection).
WithHashers(
crypto.MD5,
crypto.SHA1,
crypto.SHA256,
),
).
// only use OS related catalogers that would have been used with the kind of
// source type (container image or directory), but also add a specific python cataloger
WithCatalogerSelection(
pkgcataloging.NewSelectionRequest().
WithSubSelections("os").
WithAdditions("python-package-cataloger"),
).
// which relationships to include
WithRelationshipsConfig(
cataloging.RelationshipsConfig{
PackageFileOwnership: true,
PackageFileOwnershipOverlap: true,
ExcludeBinaryPackagesWithFileOwnershipOverlap: true,
},
).
// add your own cataloger to the mix
WithCatalogers(
pkgcataloging.NewAlwaysEnabledCatalogerReference(
newAlpineConfigurationCataloger(),
),
)
s, err := syft.CreateSBOM(context.Background(), src, cfg)
if err != nil {
panic(err)
}
return *s
}
func summarize(s sbom.SBOM) {
fmt.Printf("Cataloged %d packages:\n", s.Artifacts.Packages.PackageCount())
for _, p := range s.Artifacts.Packages.Sorted() {
fmt.Printf(" - %s@%s (%s)\n", p.Name, p.Version, p.Type)
}
fmt.Println()
}
func showAlpineConfiguration(s sbom.SBOM) {
pkgs := s.Artifacts.Packages.PackagesByName("alpine-configuration")
if len(pkgs) == 0 {
fmt.Println("no alpine-configuration package found")
return
}
p := pkgs[0]
fmt.Printf("All 'alpine-configuration' packages: %s\n", p.Version)
meta, err := yaml.Marshal(p.Metadata)
if err != nil {
panic(err)
}
fmt.Println(string(meta))
}
+64
View File
@@ -0,0 +1,64 @@
package main
import (
"context"
"fmt"
"os"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/format"
"github.com/anchore/syft/syft/format/syftjson"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)
const defaultImage = "alpine:3.19"
func main() {
// automagically get a source.Source for arbitrary string input
src := getSource(imageReference())
// catalog the given source and return a SBOM
sbom := getSBOM(src)
// take the SBOM object and encode it into the syft-json representation
bytes := formatSBOM(sbom)
// show the SBOM!
fmt.Println(string(bytes))
}
func imageReference() string {
// read an image string reference from the command line or use a default
if len(os.Args) > 1 {
return os.Args[1]
}
return defaultImage
}
func getSource(input string) source.Source {
src, err := syft.GetSource(context.Background(), input, nil)
if err != nil {
panic(err)
}
return src
}
func getSBOM(src source.Source) sbom.SBOM {
s, err := syft.CreateSBOM(context.Background(), src, nil)
if err != nil {
panic(err)
}
return *s
}
func formatSBOM(s sbom.SBOM) []byte {
bytes, err := format.Encode(s, syftjson.NewFormatEncoder())
if err != nil {
panic(err)
}
return bytes
}
File diff suppressed because it is too large Load Diff
+53
View File
@@ -0,0 +1,53 @@
package main
import (
_ "embed"
"fmt"
"io"
"os"
"strings"
"github.com/anchore/syft/syft/format"
)
//go:embed alpine.syft.json
var sbomContents string
func main() {
// decode the SBOM
fmt.Println("decoding SBOM...")
sbom, sbomFormat, formatVersion, err := format.Decode(sbomReader())
if err != nil {
fmt.Printf("failed to decode sbom: %+v\n", err)
os.Exit(1)
}
fmt.Printf("SBOM format: %s@%s\n", sbomFormat, formatVersion)
// print packages found...
fmt.Println("\nPackages found:")
for _, pkg := range sbom.Artifacts.Packages.Sorted() {
fmt.Printf(" %s : %s@%s (%s)\n", pkg.ID(), pkg.Name, pkg.Version, pkg.Type)
}
// print files found...
fmt.Println("\nFiles found:")
for c, f := range sbom.Artifacts.FileMetadata {
fmt.Printf(" %s : %s\n", c.ID(), f.Path)
}
}
func sbomReader() io.Reader {
// read file from sys args (or use the default)
var reader io.Reader
if len(os.Args) < 2 {
reader = strings.NewReader(sbomContents)
} else {
var err error
reader, err = os.Open(os.Args[1])
if err != nil {
panic(err)
}
}
return reader
}
+68
View File
@@ -0,0 +1,68 @@
package main
import (
"context"
"encoding/json"
"os"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)
const defaultImage = "alpine:3.19"
func main() {
// automagically get a source.Source for arbitrary string input
src := getSource(imageReference())
// catalog the given source and return a SBOM
// let's explicitly use catalogers that are:
// - for installed software
// - used in the directory scan
sbom := getSBOM(src, pkgcataloging.InstalledTag, pkgcataloging.DirectoryTag)
// Show a basic catalogers and input configuration used
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(sbom.Descriptor.Configuration); err != nil {
panic(err)
}
}
func imageReference() string {
// read an image string reference from the command line or use a default
if len(os.Args) > 1 {
return os.Args[1]
}
return defaultImage
}
func getSource(input string) source.Source {
src, err := syft.GetSource(context.Background(), input, nil)
if err != nil {
panic(err)
}
return src
}
func getSBOM(src source.Source, defaultTags ...string) sbom.SBOM {
cfg := syft.DefaultCreateSBOMConfig().
WithCatalogerSelection(
// here you can sub-select, add, remove catalogers from the default selection...
// or replace the default selection entirely!
pkgcataloging.NewSelectionRequest().
WithDefaults(defaultTags...),
)
s, err := syft.CreateSBOM(context.Background(), src, cfg)
if err != nil {
panic(err)
}
return *s
}
+71
View File
@@ -0,0 +1,71 @@
package main
import (
"context"
"encoding/json"
"os"
"github.com/anchore/go-collections"
"github.com/anchore/stereoscope"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/source"
"github.com/anchore/syft/syft/source/sourceproviders"
)
/*
This example demonstrates how to create a source object from a generic string input.
Example inputs:
alpine:3.19 pull an image from the docker daemon, podman, or the registry (based on what's available)
./my.tar interpret a local archive as an OCI archive, docker save archive, or raw file from disk to catalog
docker:yourrepo/yourimage:tag explicitly use the Docker daemon
podman:yourrepo/yourimage:tag explicitly use the Podman daemon
registry:yourrepo/yourimage:tag pull image directly from a registry (no container runtime required)
docker-archive:path/to/yourimage.tar use a tarball from disk for archives created from "docker save"
oci-archive:path/to/yourimage.tar use a tarball from disk for OCI archives (from Skopeo or otherwise)
oci-dir:path/to/yourimage read directly from a path on disk for OCI layout directories (from Skopeo or otherwise)
singularity:path/to/yourimage.sif read directly from a Singularity Image Format (SIF) container on disk
dir:path/to/yourproject read directly from a path on disk (any directory)
file:path/to/yourproject/file read directly from a path on disk (any single file)
*/
const defaultImage = "alpine:3.19"
func main() {
userInput := imageReference()
// parse the scheme against the known set of schemes
schemeSource, newUserInput := stereoscope.ExtractSchemeSource(userInput, allSourceTags()...)
// set up the GetSourceConfig
getSourceCfg := syft.DefaultGetSourceConfig()
if schemeSource != "" {
getSourceCfg = getSourceCfg.WithSources(schemeSource)
userInput = newUserInput
}
src, err := syft.GetSource(context.Background(), userInput, getSourceCfg)
if err != nil {
panic(err)
}
// Show a basic description of the source to the screen
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(src.Describe()); err != nil {
panic(err)
}
}
func imageReference() string {
// read an image string reference from the command line or use a default
if len(os.Args) > 1 {
return os.Args[1]
}
return defaultImage
}
func allSourceTags() []string {
return collections.TaggedValueSet[source.Provider]{}.Join(sourceproviders.All("", nil)...).Tags()
}
+45
View File
@@ -0,0 +1,45 @@
package main
import (
"context"
"encoding/json"
"os"
"github.com/anchore/stereoscope"
"github.com/anchore/stereoscope/pkg/image/oci"
"github.com/anchore/syft/syft/source/stereoscopesource"
)
/*
This shows how to create a source from an image reference. This is useful when you are programmatically always
expecting to catalog a container image and always from the same source (e.g. docker daemon, podman, registry, etc).
*/
const defaultImage = "alpine:3.19"
func main() {
// using oci.Registry causes the lookup to always use the registry, there are several other "Source" options here
img, err := stereoscope.GetImageFromSource(context.Background(), imageReference(), oci.Registry, stereoscope.WithPlatform("linux/amd64"))
if err != nil {
panic(err)
}
src := stereoscopesource.New(img, stereoscopesource.ImageConfig{
Reference: imageReference(),
})
// Show a basic description of the source to the screen
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(src.Describe()); err != nil {
panic(err)
}
}
func imageReference() string {
// read an image string reference from the command line or use a default
if len(os.Args) > 1 {
return os.Args[1]
}
return defaultImage
}
+20
View File
@@ -0,0 +1,20 @@
package main
import (
"context"
"os"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/format/syftjson"
)
// This example demonstrates how to create an SBOM, pulling only from "registry", with error handling omitted
func main() {
image := "alpine:3.19"
src, _ := syft.GetSource(context.Background(), image, syft.DefaultGetSourceConfig().WithSources("registry"))
sbom, _ := syft.CreateSBOM(context.Background(), src, syft.DefaultCreateSBOMConfig())
_ = syftjson.NewFormatEncoder().Encode(os.Stdout, *sbom)
}
+29 -31
View File
@@ -9,30 +9,31 @@ require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/acobaugh/osrelease v0.1.0
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc
github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501
github.com/anchore/stereoscope v0.0.1
github.com/anchore/packageurl-go v0.1.1-0.20240202171727-877e1747d426
github.com/anchore/stereoscope v0.0.2-0.20240229175558-fe426d1b1c84
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
// we are hinting brotli to latest due to warning when installing archiver v3:
// go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
github.com/bmatcuk/doublestar/v4 v4.6.1
github.com/charmbracelet/bubbles v0.17.1
github.com/charmbracelet/bubbles v0.18.0
github.com/charmbracelet/bubbletea v0.25.0
github.com/charmbracelet/lipgloss v0.9.1
github.com/charmbracelet/lipgloss v0.10.0
github.com/dave/jennifer v1.7.0
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da
github.com/distribution/reference v0.5.0
github.com/docker/docker v25.0.1+incompatible
github.com/docker/docker v25.0.4+incompatible
github.com/dustin/go-humanize v1.0.1
github.com/facebookincubator/nvdtools v0.1.5
github.com/github/go-spdx/v2 v2.2.0
github.com/gkampitakis/go-snaps v0.5.0
github.com/gkampitakis/go-snaps v0.5.2
github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git/v5 v5.11.0
github.com/go-test/deep v1.1.0
@@ -47,16 +48,17 @@ require (
github.com/jedib0t/go-pretty/v6 v6.5.4
github.com/jinzhu/copier v0.4.0
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953
github.com/knqyf263/go-rpmdb v0.0.0-20230301153543-ba94b245509b
github.com/knqyf263/go-rpmdb v0.1.0
github.com/mholt/archiver/v3 v3.5.1
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/mitchellh/mapstructure v1.5.0
github.com/moby/sys/mountinfo v0.7.1
github.com/olekukonko/tablewriter v0.0.5
github.com/opencontainers/go-digest v1.0.0
github.com/pelletier/go-toml v1.9.5
github.com/saferwall/pe v1.4.8
github.com/saferwall/pe v1.5.2
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
github.com/sanity-io/litter v1.5.5
github.com/sassoftware/go-rpmutils v0.3.0
@@ -66,7 +68,7 @@ require (
github.com/spdx/tools-golang v0.5.3
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.9.0
github.com/vbatts/go-mtree v0.5.3
github.com/vifraa/gopom v1.0.0
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651
@@ -74,17 +76,16 @@ require (
github.com/xeipuuv/gojsonschema v1.2.0
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
go.uber.org/goleak v1.3.0
golang.org/x/mod v0.14.0
golang.org/x/net v0.20.0
golang.org/x/mod v0.16.0
golang.org/x/net v0.22.0
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.28.0
modernc.org/sqlite v1.29.3
)
require (
dario.cat/mergo v1.0.0 // indirect
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
@@ -136,13 +137,13 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
@@ -160,16 +161,16 @@ require (
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/sys/mountinfo v0.6.2 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/signal v0.7.0 // indirect
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/nwaples/rardecode v1.1.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/opencontainers/runc v1.1.12 // indirect
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
github.com/opencontainers/selinux v1.11.0 // indirect
github.com/pborman/indent v1.2.1 // indirect
@@ -180,7 +181,7 @@ require (
github.com/pkg/profile v1.7.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
@@ -215,13 +216,13 @@ require (
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/term v0.16.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.13.0 // indirect
golang.org/x/tools v0.17.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect
@@ -229,15 +230,12 @@ require (
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.29.0 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.41.0 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.0.1 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
)
retract (
+66 -93
View File
@@ -52,8 +52,8 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@@ -93,10 +93,12 @@ github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58Pa
github.com/anchore/archiver/v3 v3.5.2/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 h1:p0ZIe0htYOX284Y4axJaGBvXHU0VCCzLN5Wf5XbKStU=
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9/go.mod h1:3ZsFB9tzW3vl4gEiUeuSOMDnwroWxIxJelOOHUp8dSw=
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc h1:A1KFO+zZZmbNlz1+WKsCF0RKVx6XRoxsAG3lrqH9hUQ=
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc/go.mod h1:QeWvNzxsrUNxcs6haQo3OtISfXUXW0qAuiG4EQiz0GU=
github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65 h1:u9XrEabKlGPsrmRvAER+kUKkwXiJfLyqGhmOTFsXjX4=
github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65/go.mod h1:8Jr7CjmwFVcBPtkJdTpaAGHimoGJGfbExypjzOu87Og=
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b h1:L/djgY7ZbZ/38+wUtdkk398W3PIBJLkt1N8nU/7e47A=
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b/go.mod h1:TLcE0RE5+8oIx2/NPWem/dq1DeaMoC+fPEH7hoSzPLo=
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 h1:GjNGuwK5jWjJMyVppBjYS54eOiiSNv4Ba869k4wh72Q=
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8=
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw=
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a/go.mod h1:ubLFmlsv8/DFUQrZwY5syT5/8Er3ugSr4rDFwHsE3hg=
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb h1:iDMnx6LIjtjZ46C0akqveX83WFzhpTD3eqOthawb5vU=
@@ -107,10 +109,10 @@ github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0v
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ=
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods=
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 h1:AV7qjwMcM4r8wFhJq3jLRztew3ywIyPTRapl2T1s9o8=
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4=
github.com/anchore/stereoscope v0.0.1 h1:OxF7PaxMltnAxjLnDMyka+SKRIQar/bBkDdavsnjyxM=
github.com/anchore/stereoscope v0.0.1/go.mod h1:IylG7ofLoUKHwS1XDF6rPhOmaE3GgpAgsMdvvYfooTU=
github.com/anchore/packageurl-go v0.1.1-0.20240202171727-877e1747d426 h1:agoiZchSf1Nnnos1azwIg5hk5Ao9TzZNBD9++AChGEg=
github.com/anchore/packageurl-go v0.1.1-0.20240202171727-877e1747d426/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4=
github.com/anchore/stereoscope v0.0.2-0.20240229175558-fe426d1b1c84 h1:/E74wU51M87fX5UWHubLZiENXbuAci+xtbSb+JFsIYg=
github.com/anchore/stereoscope v0.0.2-0.20240229175558-fe426d1b1c84/go.mod h1:evQiJMQG56Z7/L5uhA8kfhhjF6ESJUZzUH9ms6bQ2Co=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
@@ -151,19 +153,17 @@ github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/bubbles v0.17.1 h1:0SIyjOnkrsfDo88YvPgAWvZMwXe26TP6drRvmkjyUu4=
github.com/charmbracelet/bubbles v0.17.1/go.mod h1:9HxZWlkCqz2PRwsCbYl7a3KXvGzFaDHpYbSYMJ+nE3o=
github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0=
github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw=
github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM=
github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg=
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -182,7 +182,6 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw=
@@ -206,7 +205,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE=
@@ -225,15 +223,14 @@ github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qe
github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v25.0.1+incompatible h1:k5TYd5rIVQRSqcTwCID+cyVA0yRg86+Pcrz1ls0/frA=
github.com/docker/docker v25.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v25.0.4+incompatible h1:XITZTrq+52tZyZxUOtFIahUf3aH367FLxJzt9vZeAF8=
github.com/docker/docker v25.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
@@ -270,7 +267,6 @@ github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
@@ -285,8 +281,8 @@ github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvp
github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=
github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk=
github.com/gkampitakis/go-snaps v0.5.0 h1:Qpk1+V1WJszsDvYMgrI15XbUvWqpsFvFxgaXKV6RU9Q=
github.com/gkampitakis/go-snaps v0.5.0/go.mod h1:gX47VYsnvqHsjBrTrpaXfm1Dm1Xg+nREZPKRT8xifV8=
github.com/gkampitakis/go-snaps v0.5.2 h1:ay/6f7WHwRkOgpBec9DjMLRBAApziJommZ21NkOOCwY=
github.com/gkampitakis/go-snaps v0.5.2/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y=
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0=
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
@@ -318,7 +314,6 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -445,6 +440,8 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
@@ -487,8 +484,6 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953 h1:WdAeg/imY2JFPc/9CST4bZ80nNJbiBFCAdSZCSgrS5Y=
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953/go.mod h1:6o+UrvuZWc4UTyBhQf0LGjW9Ld7qJxLz/OqvSOWWlEc=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -500,14 +495,13 @@ github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6K
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/knqyf263/go-rpmdb v0.0.0-20230301153543-ba94b245509b h1:boYyvL3tbUuKcMN029mpCl7oYYJ7yIXujLj+fiW4Alc=
github.com/knqyf263/go-rpmdb v0.0.0-20230301153543-ba94b245509b/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww=
github.com/knqyf263/go-rpmdb v0.1.0 h1:pOgjtOGtW0B+ibY905hP3ETrYFmLZsHiReKsplcs+to=
github.com/knqyf263/go-rpmdb v0.1.0/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -548,8 +542,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
@@ -577,9 +571,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
@@ -593,7 +586,6 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA=
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
@@ -603,6 +595,8 @@ github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKt
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
@@ -613,12 +607,10 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=
github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=
github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0pfj+ynAqBxo3v6u9w=
github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -667,8 +659,9 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
@@ -677,8 +670,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/saferwall/pe v1.4.8 h1:ey/L8FGBMrJ1Xh+Rltj1MAFPZ4LOQYGJqNa5B1Na6B0=
github.com/saferwall/pe v1.4.8/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7GZ25s=
github.com/saferwall/pe v1.5.2 h1:h5lLtLsyxGHQ9dN6cd8EfeLEBEo5gdqJpkuw4o4vTMY=
github.com/saferwall/pe v1.5.2/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7GZ25s=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
@@ -697,7 +690,6 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
@@ -740,8 +732,9 @@ github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -753,8 +746,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
@@ -762,7 +756,6 @@ github.com/sylabs/sif/v2 v2.11.5 h1:7ssPH3epSonsTrzbS1YxeJ9KuqAN7ISlSM61a7j/mQM=
github.com/sylabs/sif/v2 v2.11.5/go.mod h1:GBoZs9LU3e4yJH1dcZ3Akf/jsqYgy5SeguJQC+zd75Y=
github.com/sylabs/squashfs v0.6.1 h1:4hgvHnD9JGlYWwT0bPYNt9zaz23mAV3Js+VEgQoRGYQ=
github.com/sylabs/squashfs v0.6.1/go.mod h1:ZwpbPCj0ocIvMy2br6KZmix6Gzh6fsGQcCnydMF+Kx8=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo=
github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
@@ -782,7 +775,6 @@ github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/vbatts/go-mtree v0.5.3 h1:S/jYlfG8rZ+a0bhZd+RANXejy7M4Js8fq9U+XoWTd5w=
@@ -791,8 +783,6 @@ github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RV
github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0=
github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA=
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20=
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 h1:0KGbf+0SMg+UFy4e1A/CPVvXn21f1qtWdeJwxZFoQG8=
@@ -873,8 +863,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -885,8 +875,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w=
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -915,8 +905,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -951,7 +941,6 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
@@ -965,8 +954,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -997,8 +986,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1012,7 +1001,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1020,7 +1008,6 @@ golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1062,12 +1049,10 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1082,15 +1067,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1166,8 +1151,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1360,34 +1345,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.29.0 h1:tTFRFq69YKCF2QyGNuRUQxKBm1uZZLubf6Cjh/pVHXs=
modernc.org/libc v1.29.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk=
modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ=
modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0=
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c=
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE=
modernc.org/sqlite v1.29.3 h1:6L71d3zXVB8oubdVSuwiurNyYRetQ3It8l1FSwylwQ0=
modernc.org/sqlite v1.29.3/go.mod h1:MjUIBKZ+tU/lqjNLbVAAMjsQPdWdA/ciwdhsT9kBwk8=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+2 -1
View File
@@ -694,6 +694,7 @@ main() (
set +u
if [ -z "${TEST_INSTALL_SH}" ]; then
set -u
exit $(main "$@")
main "$@"
exit $?
fi
set -u
+1 -1
View File
@@ -3,5 +3,5 @@ package internal
const (
// JSONSchemaVersion is the current schema version output by the JSON encoder
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
JSONSchemaVersion = "14.0.0"
JSONSchemaVersion = "16.0.6"
)
@@ -0,0 +1,97 @@
package binary
import (
"path"
"github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/sbom"
)
func NewDependencyRelationships(resolver file.Resolver, accessor sbomsync.Accessor) []artifact.Relationship {
// TODO: consider library format (e.g. ELF, Mach-O, PE) for the meantime assume all binaries are homogeneous format
// start with building new file-to-file relationships for executables-to-executables
// you need to make certain that they are unique, store in a map[id]map[id]relationship to avoid dupes.
// before creating the new file-to-file relationship, check to see if there are packages that represent each
// file. If there are, create a package-to-package, file-to-package, or package-to-file relationship as appropriate.
// 1 & 2... build an index of all shared libraries and their owning packages to search against
index := newShareLibIndex(resolver, accessor)
// 3. craft package-to-package or package-to-file relationships that represent binary shared library dependencies
// note: prefer package-to-package relationships over package-to-file relationships
relIndex := newRelationshipIndex()
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
// read all existing dependencyOf relationships
for _, r := range s.Relationships {
if r.Type != artifact.DependencyOfRelationship {
continue
}
relIndex.track(r)
}
})
// find all new relationships to add...
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
for _, parentPkg := range s.Artifacts.Packages.Sorted(pkg.BinaryPkg) {
for _, evidentLocation := range parentPkg.Locations.ToSlice() {
if evidentLocation.Annotations[pkg.EvidenceAnnotationKey] != pkg.PrimaryEvidenceAnnotation {
continue
}
// find all libraries that this package depends on
exec, ok := s.Artifacts.Executables[evidentLocation.Coordinates]
if !ok {
continue
}
for _, libReference := range exec.ImportedLibraries {
// TODO: is this always a basename? technically no, it could be a path...
libBasename := path.Base(libReference)
pkgsThatOwnLib := index.owningLibraryPackage(libBasename)
if pkgsThatOwnLib == nil {
// create package-to-file relationship...
// if there is more than one library for this given library name, then we will include
// all of them as dependencies since we don't know the LD_LIBRARY_PATH order
// TODO: add configuration for LD_LIBRARY_PATH order?
for _, libCoord := range index.owningLibraryLocations(libBasename).ToSlice() {
relIndex.add(
artifact.Relationship{
From: libCoord,
To: parentPkg,
Type: artifact.DependencyOfRelationship,
},
)
}
// don't create a package-to-package relationship for this library... since we can't
continue
}
// create a package-to-package relationship between the binary package and the library package
// if there is more than one library for this given library name, then we will include
// all of them as dependencies since we don't know the LD_LIBRARY_PATH order
for _, pkgThatOwnsLib := range pkgsThatOwnLib.Sorted() {
relIndex.add(
artifact.Relationship{
From: pkgThatOwnsLib,
To: parentPkg,
Type: artifact.DependencyOfRelationship,
},
)
}
}
}
}
})
// so far this handles the first order dependencies from the binary package. Odds are that the OS package manager
// will have already created a package-to-package relationship for the lib packages to other lib packages.
return relIndex.newRelationships()
}
@@ -0,0 +1,58 @@
package binary
import (
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/syft/artifact"
)
type relationshipIndex struct {
typesByFromTo map[artifact.ID]map[artifact.ID]*strset.Set
additional []artifact.Relationship
}
func newRelationshipIndex(existing ...artifact.Relationship) *relationshipIndex {
r := &relationshipIndex{
typesByFromTo: make(map[artifact.ID]map[artifact.ID]*strset.Set),
additional: make([]artifact.Relationship, 0),
}
for _, rel := range existing {
r.track(rel)
}
return r
}
// track this relationship as "exists" in the index (this is used to prevent duplicate relationships from being added).
// returns true if the relationship is new to the index, false otherwise.
func (i *relationshipIndex) track(r artifact.Relationship) bool {
fromID := r.From.ID()
if _, ok := i.typesByFromTo[fromID]; !ok {
i.typesByFromTo[fromID] = make(map[artifact.ID]*strset.Set)
}
toID := r.To.ID()
if _, ok := i.typesByFromTo[fromID][toID]; !ok {
i.typesByFromTo[fromID][toID] = strset.New()
}
var exists bool
if i.typesByFromTo[fromID][toID].Has(string(r.Type)) {
exists = true
}
i.typesByFromTo[fromID][toID].Add(string(r.Type))
return exists
}
// add a new relationship to the index, returning true if the relationship is new to the index, false otherwise (thus is a duplicate).
func (i *relationshipIndex) add(r artifact.Relationship) bool {
if !i.track(r) {
i.additional = append(i.additional, r)
return true
}
return false
}
func (i *relationshipIndex) newRelationships() []artifact.Relationship {
return i.additional
}
@@ -0,0 +1,117 @@
package binary
import (
"path"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/sbom"
)
type sharedLibraryIndex struct {
libLocationsByBasename map[string]file.CoordinateSet
allLibLocations file.CoordinateSet
packagesByLibraryPath map[file.Coordinates]*pkg.Collection
}
func newShareLibIndex(resolver file.Resolver, accessor sbomsync.Accessor) *sharedLibraryIndex {
s := &sharedLibraryIndex{
libLocationsByBasename: make(map[string]file.CoordinateSet),
allLibLocations: file.NewCoordinateSet(),
packagesByLibraryPath: make(map[file.Coordinates]*pkg.Collection),
}
s.build(resolver, accessor)
return s
}
func (i *sharedLibraryIndex) build(resolver file.Resolver, accessor sbomsync.Accessor) {
// 1. map out all locations that provide libraries (indexed by the basename)
i.libLocationsByBasename, i.allLibLocations = locationsThatProvideLibraries(accessor)
// 2. for each library path, find all packages that claim ownership of the library
i.packagesByLibraryPath = packagesWithLibraryOwnership(resolver, accessor, i.allLibLocations)
}
func (i *sharedLibraryIndex) owningLibraryLocations(libraryBasename string) file.CoordinateSet {
if set, ok := i.libLocationsByBasename[libraryBasename]; ok {
return set
}
return file.NewCoordinateSet()
}
func (i *sharedLibraryIndex) owningLibraryPackage(libraryBasename string) *pkg.Collection {
// find all packages that own a library by it's basename
if set, ok := i.libLocationsByBasename[libraryBasename]; ok {
for _, coord := range set.ToSlice() {
if pkgSet, ok := i.packagesByLibraryPath[coord]; ok {
return pkgSet
}
}
}
return nil
}
func locationsThatProvideLibraries(accessor sbomsync.Accessor) (map[string]file.CoordinateSet, file.CoordinateSet) {
// map out all locations that provide libraries (indexed by the basename)
libLocationsByBasename := make(map[string]file.CoordinateSet)
allLibLocations := file.NewCoordinateSet()
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
for coord, f := range s.Artifacts.Executables {
if !f.HasExports {
continue
}
basename := path.Base(coord.RealPath)
set := libLocationsByBasename[basename]
set.Add(coord)
allLibLocations.Add(coord)
libLocationsByBasename[basename] = set
}
})
return libLocationsByBasename, allLibLocations
}
func packagesWithLibraryOwnership(resolver file.Resolver, accessor sbomsync.Accessor, allLibLocations file.CoordinateSet) map[file.Coordinates]*pkg.Collection {
// map out all packages that claim ownership of a library at a specific path
packagesByLibraryPath := make(map[file.Coordinates]*pkg.Collection)
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
for _, p := range s.Artifacts.Packages.Sorted() {
fileOwner, ok := p.Metadata.(pkg.FileOwner)
if !ok {
continue
}
for _, pth := range fileOwner.OwnedFiles() {
ownedLocation, err := resolver.FilesByPath(pth)
if err != nil {
log.WithFields("error", err, "path", pth).Trace("unable to find path for owned file")
continue
}
for _, loc := range ownedLocation {
// if the location is a library, add the package to the set of packages that own the library
if !allLibLocations.Contains(loc.Coordinates) {
continue
}
if _, ok := packagesByLibraryPath[loc.Coordinates]; !ok {
packagesByLibraryPath[loc.Coordinates] = pkg.NewCollection()
}
// we have a library path, add the package to the set of packages that own the library
packagesByLibraryPath[loc.Coordinates].Add(p)
}
}
}
})
return packagesByLibraryPath
}
+12 -1
View File
@@ -1,15 +1,20 @@
package relationship
import (
"github.com/anchore/syft/internal/relationship/binary"
"github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/sbom"
)
func Finalize(builder sbomsync.Builder, cfg cataloging.RelationshipsConfig, src artifact.Identifiable) {
func Finalize(resolver file.Resolver, builder sbomsync.Builder, cfg cataloging.RelationshipsConfig, src artifact.Identifiable) {
accessor := builder.(sbomsync.Accessor)
// remove ELF packages that are already represented by a non-ELF package
// TODO (also, how should we update the TUI to reflect that we removed packages?)
// add relationships showing packages that are evident by a file which is owned by another package (package-to-package)
if cfg.PackageFileOwnershipOverlap {
byFileOwnershipOverlapWorker(accessor)
@@ -21,6 +26,12 @@ func Finalize(builder sbomsync.Builder, cfg cataloging.RelationshipsConfig, src
excludeBinariesByFileOwnershipOverlap(accessor)
}
// add the new relationships for executables to the SBOM
newBinaryRelationships := binary.NewDependencyRelationships(resolver, accessor)
accessor.WriteToSBOM(func(s *sbom.SBOM) {
s.Relationships = append(s.Relationships, newBinaryRelationships...)
})
// add source "contains package" relationship (source-to-package)
var sourceRelationships []artifact.Relationship
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
+64 -2
View File
@@ -1,9 +1,9 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at 2023-10-05 22:45:16.827263 -0400 EDT m=+0.138031521
// This file was generated by robots at 2024-02-09 10:57:33.980847 -0500 EST m=+0.165923154
// using data from https://spdx.org/licenses/licenses.json
package spdxlicense
const Version = "3.22"
const Version = "3.23"
var licenseIDs = map[string]string{
"0bsd": "0BSD",
@@ -13,6 +13,7 @@ var licenseIDs = map[string]string{
"adobe2006": "Adobe-2006",
"adobe2006.0": "Adobe-2006",
"adobe2006.0.0": "Adobe-2006",
"adobedisplaypostscript": "Adobe-Display-PostScript",
"adobeglyph": "Adobe-Glyph",
"adobeutopia": "Adobe-Utopia",
"adsl": "ADSL",
@@ -57,6 +58,7 @@ var licenseIDs = map[string]string{
"aladdin": "Aladdin",
"amdplpa": "AMDPLPA",
"aml": "AML",
"amlglslang": "AML-glslang",
"ampas": "AMPAS",
"antlrpd": "ANTLR-PD",
"antlrpdfallback": "ANTLR-PD-fallback",
@@ -108,6 +110,7 @@ var licenseIDs = map[string]string{
"baekmuk": "Baekmuk",
"bahyph": "Bahyph",
"barr": "Barr",
"bcryptsolardesigner": "bcrypt-Solar-Designer",
"beerware": "Beerware",
"bitstreamcharter": "Bitstream-Charter",
"bitstreamvera": "Bitstream-Vera",
@@ -122,6 +125,9 @@ var licenseIDs = map[string]string{
"blueoak1.0.0": "BlueOak-1.0.0",
"boehmgc": "Boehm-GC",
"borceux": "Borceux",
"briangladman2.0.0clause": "Brian-Gladman-2-Clause",
"briangladman2.0clause": "Brian-Gladman-2-Clause",
"briangladman2clause": "Brian-Gladman-2-Clause",
"briangladman3.0.0clause": "Brian-Gladman-3-Clause",
"briangladman3.0clause": "Brian-Gladman-3-Clause",
"briangladman3clause": "Brian-Gladman-3-Clause",
@@ -129,21 +135,25 @@ var licenseIDs = map[string]string{
"bsd1.0clause": "BSD-1-Clause",
"bsd1clause": "BSD-1-Clause",
"bsd2.0.0clause": "BSD-2-Clause",
"bsd2.0.0clausedarwin": "BSD-2-Clause-Darwin",
"bsd2.0.0clausefreebsd": "BSD-2-Clause-Views",
"bsd2.0.0clausenetbsd": "BSD-2-Clause",
"bsd2.0.0clausepatent": "BSD-2-Clause-Patent",
"bsd2.0.0clauseviews": "BSD-2-Clause-Views",
"bsd2.0clause": "BSD-2-Clause",
"bsd2.0clausedarwin": "BSD-2-Clause-Darwin",
"bsd2.0clausefreebsd": "BSD-2-Clause-Views",
"bsd2.0clausenetbsd": "BSD-2-Clause",
"bsd2.0clausepatent": "BSD-2-Clause-Patent",
"bsd2.0clauseviews": "BSD-2-Clause-Views",
"bsd2clause": "BSD-2-Clause",
"bsd2clausedarwin": "BSD-2-Clause-Darwin",
"bsd2clausefreebsd": "BSD-2-Clause-Views",
"bsd2clausenetbsd": "BSD-2-Clause",
"bsd2clausepatent": "BSD-2-Clause-Patent",
"bsd2clauseviews": "BSD-2-Clause-Views",
"bsd3.0.0clause": "BSD-3-Clause",
"bsd3.0.0clauseacpica": "BSD-3-Clause-acpica",
"bsd3.0.0clauseattribution": "BSD-3-Clause-Attribution",
"bsd3.0.0clauseclear": "BSD-3-Clause-Clear",
"bsd3.0.0clauseflex": "BSD-3-Clause-flex",
@@ -157,6 +167,7 @@ var licenseIDs = map[string]string{
"bsd3.0.0clauseopenmpi": "BSD-3-Clause-Open-MPI",
"bsd3.0.0clausesun": "BSD-3-Clause-Sun",
"bsd3.0clause": "BSD-3-Clause",
"bsd3.0clauseacpica": "BSD-3-Clause-acpica",
"bsd3.0clauseattribution": "BSD-3-Clause-Attribution",
"bsd3.0clauseclear": "BSD-3-Clause-Clear",
"bsd3.0clauseflex": "BSD-3-Clause-flex",
@@ -170,6 +181,7 @@ var licenseIDs = map[string]string{
"bsd3.0clauseopenmpi": "BSD-3-Clause-Open-MPI",
"bsd3.0clausesun": "BSD-3-Clause-Sun",
"bsd3clause": "BSD-3-Clause",
"bsd3clauseacpica": "BSD-3-Clause-acpica",
"bsd3clauseattribution": "BSD-3-Clause-Attribution",
"bsd3clauseclear": "BSD-3-Clause-Clear",
"bsd3clauseflex": "BSD-3-Clause-flex",
@@ -201,8 +213,12 @@ var licenseIDs = map[string]string{
"bsdattributionhpnddisclaimer": "BSD-Attribution-HPND-disclaimer",
"bsdinfernonettverk": "BSD-Inferno-Nettverk",
"bsdprotection": "BSD-Protection",
"bsdsourcebeginningfile": "BSD-Source-beginning-file",
"bsdsourcecode": "BSD-Source-Code",
"bsdsystemics": "BSD-Systemics",
"bsdsystemicsw3.0.0works": "BSD-Systemics-W3Works",
"bsdsystemicsw3.0works": "BSD-Systemics-W3Works",
"bsdsystemicsw3works": "BSD-Systemics-W3Works",
"bsl1": "BSL-1.0",
"bsl1.0": "BSL-1.0",
"bsl1.0.0": "BSL-1.0",
@@ -220,6 +236,7 @@ var licenseIDs = map[string]string{
"cal1.0combinedworkexception": "CAL-1.0-Combined-Work-Exception",
"cal1combinedworkexception": "CAL-1.0-Combined-Work-Exception",
"caldera": "Caldera",
"calderanopreamble": "Caldera-no-preamble",
"catosl1": "CATOSL-1.1",
"catosl1.1": "CATOSL-1.1",
"catosl1.1.0": "CATOSL-1.1",
@@ -241,16 +258,19 @@ var licenseIDs = map[string]string{
"ccby3.0": "CC-BY-3.0",
"ccby3.0.0": "CC-BY-3.0",
"ccby3.0.0at": "CC-BY-3.0-AT",
"ccby3.0.0au": "CC-BY-3.0-AU",
"ccby3.0.0de": "CC-BY-3.0-DE",
"ccby3.0.0igo": "CC-BY-3.0-IGO",
"ccby3.0.0nl": "CC-BY-3.0-NL",
"ccby3.0.0us": "CC-BY-3.0-US",
"ccby3.0at": "CC-BY-3.0-AT",
"ccby3.0au": "CC-BY-3.0-AU",
"ccby3.0de": "CC-BY-3.0-DE",
"ccby3.0igo": "CC-BY-3.0-IGO",
"ccby3.0nl": "CC-BY-3.0-NL",
"ccby3.0us": "CC-BY-3.0-US",
"ccby3at": "CC-BY-3.0-AT",
"ccby3au": "CC-BY-3.0-AU",
"ccby3de": "CC-BY-3.0-DE",
"ccby3igo": "CC-BY-3.0-IGO",
"ccby3nl": "CC-BY-3.0-NL",
@@ -420,6 +440,7 @@ var licenseIDs = map[string]string{
"clartistic": "ClArtistic",
"clips": "Clips",
"cmumach": "CMU-Mach",
"cmumachnodoc": "CMU-Mach-nodoc",
"cnrijython": "CNRI-Jython",
"cnripython": "CNRI-Python",
"cnripythongplcompatible": "CNRI-Python-GPL-Compatible",
@@ -456,6 +477,9 @@ var licenseIDs = map[string]string{
"cuda1.0": "C-UDA-1.0",
"cuda1.0.0": "C-UDA-1.0",
"curl": "curl",
"dec3.0.0clause": "DEC-3-Clause",
"dec3.0clause": "DEC-3-Clause",
"dec3clause": "DEC-3-Clause",
"dfsl1": "D-FSL-1.0",
"dfsl1.0": "D-FSL-1.0",
"dfsl1.0.0": "D-FSL-1.0",
@@ -471,6 +495,8 @@ var licenseIDs = map[string]string{
"drl1": "DRL-1.0",
"drl1.0": "DRL-1.0",
"drl1.0.0": "DRL-1.0",
"drl1.1": "DRL-1.1",
"drl1.1.0": "DRL-1.1",
"dsdp": "DSDP",
"dtoa": "dtoa",
"dvipdfm": "dvipdfm",
@@ -526,12 +552,14 @@ var licenseIDs = map[string]string{
"freebsddoc": "FreeBSD-DOC",
"freeimage": "FreeImage",
"fsfap": "FSFAP",
"fsfapnowarrantydisclaimer": "FSFAP-no-warranty-disclaimer",
"fsful": "FSFUL",
"fsfullr": "FSFULLR",
"fsfullrwd": "FSFULLRWD",
"ftl": "FTL",
"furuseth": "Furuseth",
"fwlw": "fwlw",
"gcrdocs": "GCR-docs",
"gd": "GD",
"gfdl1": "GFDL-1.1-only",
"gfdl1+": "GFDL-1.1-or-later",
@@ -672,7 +700,9 @@ var licenseIDs = map[string]string{
"gsoap1.3.0b": "gSOAP-1.3b",
"gsoap1.3b": "gSOAP-1.3b",
"gsoap1b": "gSOAP-1.3b",
"gtkbook": "gtkbook",
"haskellreport": "HaskellReport",
"hdparm": "hdparm",
"hippocratic2": "Hippocratic-2.1",
"hippocratic2.1": "Hippocratic-2.1",
"hippocratic2.1.0": "Hippocratic-2.1",
@@ -688,8 +718,13 @@ var licenseIDs = map[string]string{
"hpnddocsell": "HPND-doc-sell",
"hpndexportus": "HPND-export-US",
"hpndexportusmodify": "HPND-export-US-modify",
"hpndfenneberglivingston": "HPND-Fenneberg-Livingston",
"hpndinriaimag": "HPND-INRIA-IMAG",
"hpndkevlinhenney": "HPND-Kevlin-Henney",
"hpndmarkuskuhn": "HPND-Markus-Kuhn",
"hpndmitdisclaimer": "HPND-MIT-disclaimer",
"hpndpbmplus": "HPND-Pbmplus",
"hpndsellmitdisclaimerxserver": "HPND-sell-MIT-disclaimer-xserver",
"hpndsellregexpr": "HPND-sell-regexpr",
"hpndsellvariant": "HPND-sell-variant",
"hpndsellvariantmitdisclaimer": "HPND-sell-variant-MIT-disclaimer",
@@ -719,6 +754,7 @@ var licenseIDs = map[string]string{
"ipl1.0": "IPL-1.0",
"ipl1.0.0": "IPL-1.0",
"isc": "ISC",
"iscveillard": "ISC-Veillard",
"jam": "Jam",
"jasper2": "JasPer-2.0",
"jasper2.0": "JasPer-2.0",
@@ -802,6 +838,7 @@ var licenseIDs = map[string]string{
"linuxmanpagescopyleftvar": "Linux-man-pages-copyleft-var",
"linuxopenib": "Linux-OpenIB",
"loop": "LOOP",
"lpddocument": "LPD-document",
"lpl1": "LPL-1.0",
"lpl1.0": "LPL-1.0",
"lpl1.0.0": "LPL-1.0",
@@ -828,7 +865,14 @@ var licenseIDs = map[string]string{
"lzmasdk9.22": "LZMA-SDK-9.22",
"lzmasdk9.22.0": "LZMA-SDK-9.22",
"lzmasdk9to9.20": "LZMA-SDK-9.11-to-9.20",
"mackerras3.0.0clause": "Mackerras-3-Clause",
"mackerras3.0.0clauseacknowledgment": "Mackerras-3-Clause-acknowledgment",
"mackerras3.0clause": "Mackerras-3-Clause",
"mackerras3.0clauseacknowledgment": "Mackerras-3-Clause-acknowledgment",
"mackerras3clause": "Mackerras-3-Clause",
"mackerras3clauseacknowledgment": "Mackerras-3-Clause-acknowledgment",
"magaz": "magaz",
"mailprio": "mailprio",
"makeindex": "MakeIndex",
"martinbirgmeier": "Martin-Birgmeier",
"mcpheeslideshow": "McPhee-slideshow",
@@ -1008,6 +1052,8 @@ var licenseIDs = map[string]string{
"openpbs2.3": "OpenPBS-2.3",
"openpbs2.3.0": "OpenPBS-2.3",
"openssl": "OpenSSL",
"opensslstandalone": "OpenSSL-standalone",
"openvision": "OpenVision",
"opl1": "OPL-1.0",
"opl1.0": "OPL-1.0",
"opl1.0.0": "OPL-1.0",
@@ -1051,6 +1097,7 @@ var licenseIDs = map[string]string{
"php3.0.0": "PHP-3.0",
"php3.01": "PHP-3.01",
"php3.01.0": "PHP-3.01",
"pixar": "Pixar",
"plexus": "Plexus",
"pnmstitch": "pnmstitch",
"polyformnoncommercial1": "PolyForm-Noncommercial-1.0.0",
@@ -1077,6 +1124,7 @@ var licenseIDs = map[string]string{
"qpl1.0.0inria2004": "QPL-1.0-INRIA-2004",
"qpl1.0inria2004": "QPL-1.0-INRIA-2004",
"qpl1inria2004": "QPL-1.0-INRIA-2004",
"radvd": "radvd",
"rdisc": "Rdisc",
"rhecos1": "RHeCos-1.1",
"rhecos1.1": "RHeCos-1.1",
@@ -1094,6 +1142,9 @@ var licenseIDs = map[string]string{
"ruby": "Ruby",
"saxpath": "Saxpath",
"saxpd": "SAX-PD",
"saxpd2": "SAX-PD-2.0",
"saxpd2.0": "SAX-PD-2.0",
"saxpd2.0.0": "SAX-PD-2.0",
"scea": "SCEA",
"schemereport": "SchemeReport",
"sendmail": "Sendmail",
@@ -1129,6 +1180,7 @@ var licenseIDs = map[string]string{
"smppl": "SMPPL",
"snia": "SNIA",
"snprintf": "snprintf",
"softsurfer": "softSurfer",
"soundex": "Soundex",
"spencer86": "Spencer-86",
"spencer86.0": "Spencer-86",
@@ -1145,6 +1197,7 @@ var licenseIDs = map[string]string{
"sshkeyscan": "ssh-keyscan",
"sshopenssh": "SSH-OpenSSH",
"sshshort": "SSH-short",
"ssleaystandalone": "SSLeay-standalone",
"sspl1": "SSPL-1.0",
"sspl1.0": "SSPL-1.0",
"sspl1.0.0": "SSPL-1.0",
@@ -1152,6 +1205,7 @@ var licenseIDs = map[string]string{
"sugarcrm1": "SugarCRM-1.1.3",
"sugarcrm1.1": "SugarCRM-1.1.3",
"sugarcrm1.1.3": "SugarCRM-1.1.3",
"sunppp": "Sun-PPP",
"sunpro": "SunPro",
"swl": "SWL",
"swrule": "swrule",
@@ -1162,6 +1216,9 @@ var licenseIDs = map[string]string{
"tcl": "TCL",
"tcpwrappers": "TCP-wrappers",
"termreadkey": "TermReadKey",
"tgppl1": "TGPPL-1.0",
"tgppl1.0": "TGPPL-1.0",
"tgppl1.0.0": "TGPPL-1.0",
"tmate": "TMate",
"torque1": "TORQUE-1.1",
"torque1.1": "TORQUE-1.1",
@@ -1184,6 +1241,10 @@ var licenseIDs = map[string]string{
"ucl1.0": "UCL-1.0",
"ucl1.0.0": "UCL-1.0",
"ulem": "ulem",
"umichmerit": "UMich-Merit",
"unicode3": "Unicode-3.0",
"unicode3.0": "Unicode-3.0",
"unicode3.0.0": "Unicode-3.0",
"unicodedfs2015": "Unicode-DFS-2015",
"unicodedfs2015.0": "Unicode-DFS-2015",
"unicodedfs2015.0.0": "Unicode-DFS-2015",
@@ -1236,6 +1297,7 @@ var licenseIDs = map[string]string{
"xfree861.1": "XFree86-1.1",
"xfree861.1.0": "XFree86-1.1",
"xinetd": "xinetd",
"xkeyboardconfigzinoviev": "xkeyboard-config-Zinoviev",
"xlock": "xlock",
"xnet": "Xnet",
"xpp": "xpp",
+1 -1
View File
@@ -11,7 +11,7 @@ import (
// TODO: add tui element here?
func NewEnvironmentTask() Task {
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
fn := func(_ context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
release := linux.IdentifyRelease(resolver)
if release != nil {
builder.SetLinuxDistribution(*release)
+26
View File
@@ -8,6 +8,7 @@ import (
"github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/file/cataloger/executable"
"github.com/anchore/syft/syft/file/cataloger/filecontent"
"github.com/anchore/syft/syft/file/cataloger/filedigest"
"github.com/anchore/syft/syft/file/cataloger/filemetadata"
@@ -100,6 +101,31 @@ func NewFileContentCatalogerTask(cfg filecontent.Config) Task {
return NewTask("file-content-cataloger", fn)
}
func NewExecutableCatalogerTask(selection file.Selection, cfg executable.Config) Task {
if selection == file.NoFilesSelection {
return nil
}
cat := executable.NewCataloger(cfg)
fn := func(_ context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
accessor := builder.(sbomsync.Accessor)
result, err := cat.Catalog(resolver)
if err != nil {
return err
}
accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
sbom.Artifacts.Executables = result
})
return nil
}
return NewTask("file-executable-cataloger", fn)
}
// TODO: this should be replaced with a fix that allows passing a coordinate or location iterator to the cataloger
// Today internal to both cataloger this functions differently: a slice of coordinates vs a channel of locations
func coordinatesForSelection(selection file.Selection, accessor sbomsync.Accessor) ([]file.Coordinates, bool) {
+1 -1
View File
@@ -113,7 +113,7 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string
// we might have binary classified CPE already with the package so we want to append here
dictionaryCPE, ok := cpe.DictionaryFind(p)
if ok {
log.Tracef("used CPE dictionary to find CPE for %s package %q: %s", p.Type, p.Name, dictionaryCPE.BindToFmtString())
log.Tracef("used CPE dictionary to find CPE for %s package %q: %s", p.Type, p.Name, dictionaryCPE.Attributes.BindToFmtString())
p.CPEs = append(p.CPEs, dictionaryCPE)
} else {
p.CPEs = append(p.CPEs, cpe.Generate(p)...)
+5 -1
View File
@@ -28,6 +28,7 @@ import (
"github.com/anchore/syft/syft/pkg/cataloger/rust"
sbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/sbom"
"github.com/anchore/syft/syft/pkg/cataloger/swift"
"github.com/anchore/syft/syft/pkg/cataloger/wordpress"
)
//nolint:funlen
@@ -57,6 +58,7 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
newSimplePackageTaskFactory(dotnet.NewDotnetDepsCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "dotnet", "c#"),
newSimplePackageTaskFactory(elixir.NewMixLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "elixir"),
newSimplePackageTaskFactory(erlang.NewRebarLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "erlang"),
newSimplePackageTaskFactory(erlang.NewOTPCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "erlang", "otp"),
newSimplePackageTaskFactory(haskell.NewHackageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "haskell", "hackage", "cabal"),
newPackageTaskFactory(
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
@@ -111,10 +113,11 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
// other package catalogers ///////////////////////////////////////////////////////////////////////////
newPackageTaskFactory(
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
return binary.NewCataloger(cfg.PackagesConfig.Binary)
return binary.NewClassifierCataloger(cfg.PackagesConfig.Binary)
},
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "binary",
),
newSimplePackageTaskFactory(binary.NewELFPackageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "binary", "elf-package"),
newSimplePackageTaskFactory(githubactions.NewActionUsageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "github", "github-actions"),
newSimplePackageTaskFactory(githubactions.NewWorkflowUsageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "github", "github-actions"),
newPackageTaskFactory(
@@ -124,5 +127,6 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "linux", "kernel",
),
newSimplePackageTaskFactory(sbomCataloger.NewCataloger, "sbom"), // note: not evidence of installed packages
newSimplePackageTaskFactory(wordpress.NewWordpressPluginCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "wordpress"),
}
}
+2 -1
View File
@@ -22,8 +22,9 @@ func (s sourceIdentifierAdapter) ID() artifact.ID {
}
func NewRelationshipsTask(cfg cataloging.RelationshipsConfig, src source.Description) Task {
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
fn := func(_ context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
relationship.Finalize(
resolver,
builder,
cfg,
&sourceIdentifierAdapter{desc: src})
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+15 -7
View File
@@ -9,13 +9,15 @@ import (
intFile "github.com/anchore/syft/internal/file"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/file/cataloger/executable"
"github.com/anchore/syft/syft/file/cataloger/filecontent"
)
type Config struct {
Selection file.Selection `yaml:"selection" json:"selection" mapstructure:"selection"`
Hashers []crypto.Hash `yaml:"hashers" json:"hashers" mapstructure:"hashers"`
Content filecontent.Config `yaml:"content" json:"content" mapstructure:"content"`
Selection file.Selection `yaml:"selection" json:"selection" mapstructure:"selection"`
Hashers []crypto.Hash `yaml:"hashers" json:"hashers" mapstructure:"hashers"`
Content filecontent.Config `yaml:"content" json:"content" mapstructure:"content"`
Executable executable.Config `yaml:"executable" json:"executable" mapstructure:"executable"`
}
type configMarshaledForm struct {
@@ -30,9 +32,10 @@ func DefaultConfig() Config {
log.WithFields("error", err).Warn("unable to create file hashers")
}
return Config{
Selection: file.FilesOwnedByPackageSelection,
Hashers: hashers,
Content: filecontent.DefaultConfig(),
Selection: file.FilesOwnedByPackageSelection,
Hashers: hashers,
Content: filecontent.DefaultConfig(),
Executable: executable.DefaultConfig(),
}
}
@@ -72,7 +75,12 @@ func (cfg Config) WithSelection(selection file.Selection) Config {
return cfg
}
func (cfg Config) WithHashers(hashers []crypto.Hash) Config {
func (cfg Config) WithHashers(hashers ...crypto.Hash) Config {
cfg.Hashers = intFile.NormalizeHashes(hashers)
return cfg
}
func (cfg Config) WithContentConfig(content filecontent.Config) Config {
cfg.Content = content
return cfg
}
+3 -3
View File
@@ -10,7 +10,7 @@ import (
)
type Config struct {
Binary binary.CatalogerConfig `yaml:"binary" json:"binary" mapstructure:"binary"`
Binary binary.ClassifierCatalogerConfig `yaml:"binary" json:"binary" mapstructure:"binary"`
Golang golang.CatalogerConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
JavaArchive java.ArchiveCatalogerConfig `yaml:"java-archive" json:"java-archive" mapstructure:"java-archive"`
JavaScript javascript.CatalogerConfig `yaml:"javascript" json:"javascript" mapstructure:"javascript"`
@@ -20,7 +20,7 @@ type Config struct {
func DefaultConfig() Config {
return Config{
Binary: binary.DefaultCatalogerConfig(),
Binary: binary.DefaultClassifierCatalogerConfig(),
Golang: golang.DefaultCatalogerConfig(),
LinuxKernel: kernel.DefaultLinuxKernelCatalogerConfig(),
Python: python.DefaultCatalogerConfig(),
@@ -28,7 +28,7 @@ func DefaultConfig() Config {
}
}
func (c Config) WithBinaryConfig(cfg binary.CatalogerConfig) Config {
func (c Config) WithBinaryConfig(cfg binary.ClassifierCatalogerConfig) Config {
c.Binary = cfg
return c
}
+39
View File
@@ -0,0 +1,39 @@
package cpe
import "sort"
type BySourceThenSpecificity []CPE
func (b BySourceThenSpecificity) Len() int {
return len(b)
}
func (b BySourceThenSpecificity) Less(i, j int) bool {
sourceOrder := map[Source]int{
NVDDictionaryLookupSource: 1,
DeclaredSource: 2,
GeneratedSource: 3,
}
getRank := func(source Source) int {
if rank, exists := sourceOrder[source]; exists {
return rank
}
return 4 // Sourced we don't know about can't be assigned special priority, so
// are considered ties.
}
iSource := b[i].Source
jSource := b[j].Source
rankI, rankJ := getRank(iSource), getRank(jSource)
if rankI != rankJ {
return rankI < rankJ
}
return isMoreSpecific(b[i].Attributes, b[j].Attributes)
}
func (b BySourceThenSpecificity) Swap(i, j int) {
b[i], b[j] = b[j], b[i]
}
var _ sort.Interface = (*BySourceThenSpecificity)(nil)
@@ -0,0 +1,74 @@
package cpe
import (
"sort"
"testing"
"github.com/stretchr/testify/assert"
)
func TestBySourceThenSpecificity(t *testing.T) {
tests := []struct {
name string
input []CPE
want []CPE
}{
{
name: "empty case",
},
{
name: "nvd before generated",
input: []CPE{
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", GeneratedSource),
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", NVDDictionaryLookupSource),
},
want: []CPE{
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", NVDDictionaryLookupSource),
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", GeneratedSource),
},
},
{
name: "declared before generated",
input: []CPE{
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", GeneratedSource),
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", DeclaredSource),
},
want: []CPE{
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", DeclaredSource),
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", GeneratedSource),
},
},
{
name: "most specific attributes of equal sources",
input: []CPE{
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*", NVDDictionaryLookupSource),
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*", NVDDictionaryLookupSource),
Must("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*", NVDDictionaryLookupSource),
},
want: []CPE{
Must("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*", NVDDictionaryLookupSource),
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*", NVDDictionaryLookupSource),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*", NVDDictionaryLookupSource),
},
},
{
name: "most specific attributes of unknown sources",
input: []CPE{
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*", ""),
Must("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*", "some-other-unknown-source"),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*", "some-unknown-source"),
},
want: []CPE{
Must("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*", "some-other-unknown-source"),
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*", ""),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*", "some-unknown-source"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sort.Sort(BySourceThenSpecificity(tt.input))
assert.Equal(t, tt.want, tt.input)
})
}
}
+23 -16
View File
@@ -6,15 +6,22 @@ import (
var _ sort.Interface = (*BySpecificity)(nil)
type BySpecificity []CPE
type BySpecificity []Attributes
func (c BySpecificity) Len() int { return len(c) }
func (c BySpecificity) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c BySpecificity) Less(i, j int) bool {
iScore := weightedCountForSpecifiedFields(c[i])
jScore := weightedCountForSpecifiedFields(c[j])
return isMoreSpecific(c[i], c[j])
}
// Returns true if i is more specific than j, with some
// tie breaking mechanisms to make sorting equally-specific cpe Attributes
// deterministic.
func isMoreSpecific(i, j Attributes) bool {
iScore := weightedCountForSpecifiedFields(i)
jScore := weightedCountForSpecifiedFields(j)
// check weighted sort first
if iScore != jScore {
@@ -22,28 +29,28 @@ func (c BySpecificity) Less(i, j int) bool {
}
// sort longer fields to top
if countFieldLength(c[i]) != countFieldLength(c[j]) {
return countFieldLength(c[i]) > countFieldLength(c[j])
if countFieldLength(i) != countFieldLength(j) {
return countFieldLength(i) > countFieldLength(j)
}
// if score and length are equal then text sort
// note that we are not using String from the syft pkg
// as we are not encoding/decoding this CPE string so we don't
// need the proper quoted version of the CPE.
return c[i].BindToFmtString() < c[j].BindToFmtString()
// as we are not encoding/decoding this Attributes string so we don't
// need the proper quoted version of the Attributes.
return i.BindToFmtString() < j.BindToFmtString()
}
func countFieldLength(cpe CPE) int {
func countFieldLength(cpe Attributes) int {
return len(cpe.Part + cpe.Vendor + cpe.Product + cpe.Version + cpe.TargetSW)
}
func weightedCountForSpecifiedFields(cpe CPE) int {
checksForSpecifiedField := []func(cpe CPE) (bool, int){
func(cpe CPE) (bool, int) { return cpe.Part != "", 2 },
func(cpe CPE) (bool, int) { return cpe.Vendor != "", 3 },
func(cpe CPE) (bool, int) { return cpe.Product != "", 4 },
func(cpe CPE) (bool, int) { return cpe.Version != "", 1 },
func(cpe CPE) (bool, int) { return cpe.TargetSW != "", 1 },
func weightedCountForSpecifiedFields(cpe Attributes) int {
checksForSpecifiedField := []func(cpe Attributes) (bool, int){
func(cpe Attributes) (bool, int) { return cpe.Part != "", 2 },
func(cpe Attributes) (bool, int) { return cpe.Vendor != "", 3 },
func(cpe Attributes) (bool, int) { return cpe.Product != "", 4 },
func(cpe Attributes) (bool, int) { return cpe.Version != "", 1 },
func(cpe Attributes) (bool, int) { return cpe.TargetSW != "", 1 },
}
weightedCount := 0
+56 -56
View File
@@ -10,81 +10,81 @@ import (
func Test_BySpecificity(t *testing.T) {
tests := []struct {
name string
input []CPE
expected []CPE
input []Attributes
expected []Attributes
}{
{
name: "sort strictly by wfn *",
input: []CPE{
Must("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:*:package:1:*:*:*:*:some:*:*"),
Must("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*"),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"),
input: []Attributes{
MustAttributes("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:*:package:1:*:*:*:*:some:*:*"),
MustAttributes("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*"),
MustAttributes("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"),
},
expected: []CPE{
Must("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*"),
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:*:package:1:*:*:*:*:some:*:*"),
Must("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*"),
expected: []Attributes{
MustAttributes("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*"),
MustAttributes("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:*:package:1:*:*:*:*:some:*:*"),
MustAttributes("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*"),
},
},
{
name: "sort strictly by field length",
input: []CPE{
Must("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:1:333:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:666666:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:1:1:*:*:*:*:4444:*:*"),
input: []Attributes{
MustAttributes("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:1:333:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:666666:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:1:1:*:*:*:*:4444:*:*"),
},
expected: []CPE{
Must("cpe:2.3:a:1:666666:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:1:1:*:*:*:*:4444:*:*"),
Must("cpe:2.3:a:1:1:333:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"),
expected: []Attributes{
MustAttributes("cpe:2.3:a:1:666666:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:1:1:*:*:*:*:4444:*:*"),
MustAttributes("cpe:2.3:a:1:1:333:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"),
},
},
{
name: "sort by mix of field length and specificity",
input: []CPE{
Must("cpe:2.3:a:1:666666:*:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:*:1:1:*:*:*:*:4444:*:*"),
Must("cpe:2.3:a:1:*:333:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"),
input: []Attributes{
MustAttributes("cpe:2.3:a:1:666666:*:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:*:1:1:*:*:*:*:4444:*:*"),
MustAttributes("cpe:2.3:a:1:*:333:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"),
},
expected: []CPE{
Must("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:1:666666:*:*:*:*:*:1:*:*"),
Must("cpe:2.3:a:*:1:1:*:*:*:*:4444:*:*"),
Must("cpe:2.3:a:1:*:333:*:*:*:*:*:*:*"),
expected: []Attributes{
MustAttributes("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:1:666666:*:*:*:*:*:1:*:*"),
MustAttributes("cpe:2.3:a:*:1:1:*:*:*:*:4444:*:*"),
MustAttributes("cpe:2.3:a:1:*:333:*:*:*:*:*:*:*"),
},
},
{
name: "sort by mix of field length, specificity, dash",
input: []CPE{
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
input: []Attributes{
MustAttributes("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
},
expected: []CPE{
Must("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
expected: []Attributes{
MustAttributes("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*"),
MustAttributes("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"),
},
},
}
+69 -30
View File
@@ -8,9 +8,29 @@ import (
"github.com/facebookincubator/nvdtools/wfn"
)
// CPE contains the attributes of an NVD Attributes and a string
// describing where Syft got the Attributes, e.g. generated by heuristics
// vs looked up in the NVD Attributes dictionary
type CPE struct {
Attributes Attributes
Source Source
}
type Source string
func (c Source) String() string {
return string(c)
}
const (
GeneratedSource Source = "syft-generated"
NVDDictionaryLookupSource Source = "nvd-cpe-dictionary"
DeclaredSource Source = "declared"
)
const Any = ""
type CPE struct {
type Attributes struct {
Part string
Vendor string
Product string
@@ -24,19 +44,19 @@ type CPE struct {
Language string
}
func (c CPE) asAttributes() wfn.Attributes {
func (c Attributes) asAttributes() wfn.Attributes {
return wfn.Attributes(c)
}
func fromAttributes(a wfn.Attributes) CPE {
return CPE(a)
func fromAttributes(a wfn.Attributes) Attributes {
return Attributes(a)
}
func (c CPE) BindToFmtString() string {
func (c Attributes) BindToFmtString() string {
return c.asAttributes().BindToFmtString()
}
func NewWithAny() CPE {
func NewWithAny() Attributes {
return fromAttributes(*(wfn.NewAttributesWithAny()))
}
@@ -46,36 +66,55 @@ const (
// This regex string is taken from
// https://csrc.nist.gov/schema/cpe/2.3/cpe-naming_2.3.xsd which has the official cpe spec
// This first part matches CPE urls and the second part matches binding strings
// This first part matches Attributes urls and the second part matches binding strings
const cpeRegexString = ((`^([c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\._\-~%]*){0,6})`) +
// Or match the CPE binding string
// Or match the Attributes binding string
// Note that we had to replace '`' with '\x60' to escape the backticks
`|(cpe:2\.3:[aho\*\-](:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&'\(\)\+,/:;<=>@\[\]\^\x60\{\|}~]))+(\?*|\*?))|[\*\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\*\-]))(:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&'\(\)\+,/:;<=>@\[\]\^\x60\{\|}~]))+(\?*|\*?))|[\*\-])){4})$`)
var cpeRegex = regexp.MustCompile(cpeRegexString)
// New will parse a formatted CPE string and return a CPE object. Some input, such as the existence of whitespace
// characters is allowed, however, a more strict validation is done after this sanitization process.
func New(cpeStr string) (CPE, error) {
// get a CPE object based on the given string --don't validate yet since it may be possible to escape select cases on the callers behalf
c, err := newWithoutValidation(cpeStr)
func New(value string, source Source) (CPE, error) {
attributes, err := NewAttributes(value)
if err != nil {
return CPE{}, fmt.Errorf("unable to parse CPE string: %w", err)
}
// ensure that this CPE can be validated after being fully sanitized
if ValidateString(c.String()) != nil {
return CPE{}, err
}
return CPE{
Attributes: attributes,
Source: source,
}, nil
}
// we don't return the sanitized string, as this is a concern for later when creating CPE strings. In fact, since
// NewAttributes will parse a formatted Attributes string and return a Attributes object. Some input, such as the existence of whitespace
// characters is allowed, however, a more strict validation is done after this sanitization process.
func NewAttributes(cpeStr string) (Attributes, error) {
// get a Attributes object based on the given string --don't validate yet since it may be possible to escape select cases on the callers behalf
c, err := newWithoutValidation(cpeStr)
if err != nil {
return Attributes{}, fmt.Errorf("unable to parse Attributes string: %w", err)
}
// ensure that this Attributes can be validated after being fully sanitized
if ValidateString(c.String()) != nil {
return Attributes{}, err
}
// we don't return the sanitized string, as this is a concern for later when creating Attributes strings. In fact, since
// sanitization is lossy (whitespace is replaced, not escaped) it's important that the raw values are left as.
return c, nil
}
// Must returns a CPE or panics if the provided string is not valid
func Must(cpeStr string) CPE {
c, err := New(cpeStr)
func Must(cpeStr string, source Source) CPE {
c := MustAttributes(cpeStr)
return CPE{
Attributes: c,
Source: source,
}
}
func MustAttributes(cpeStr string) Attributes {
c, err := NewAttributes(cpeStr)
if err != nil {
panic(err)
}
@@ -83,22 +122,22 @@ func Must(cpeStr string) CPE {
}
func ValidateString(cpeStr string) error {
// We should filter out all CPEs that do not match the official CPE regex
// The facebook nvdtools parser can sometimes incorrectly parse invalid CPE strings
// We should filter out all CPEs that do not match the official Attributes regex
// The facebook nvdtools parser can sometimes incorrectly parse invalid Attributes strings
if !cpeRegex.MatchString(cpeStr) {
return fmt.Errorf("failed to parse CPE=%q as it doesn't match the regex=%s", cpeStr, cpeRegexString)
return fmt.Errorf("failed to parse Attributes=%q as it doesn't match the regex=%s", cpeStr, cpeRegexString)
}
return nil
}
func newWithoutValidation(cpeStr string) (CPE, error) {
func newWithoutValidation(cpeStr string) (Attributes, error) {
value, err := wfn.Parse(cpeStr)
if err != nil {
return CPE{}, fmt.Errorf("failed to parse CPE=%q: %w", cpeStr, err)
return Attributes{}, fmt.Errorf("failed to parse Attributes=%q: %w", cpeStr, err)
}
if value == nil {
return CPE{}, fmt.Errorf("failed to parse CPE=%q", cpeStr)
return Attributes{}, fmt.Errorf("failed to parse Attributes=%q", cpeStr)
}
syftCPE := fromAttributes(*value)
@@ -120,7 +159,7 @@ func newWithoutValidation(cpeStr string) (CPE, error) {
}
func normalizeField(field string) string {
// replace spaces with underscores (per section 5.3.2 of the CPE spec v 2.3)
// replace spaces with underscores (per section 5.3.2 of the Attributes spec v 2.3)
field = strings.ReplaceAll(field, " ", "_")
// keep dashes and forward slashes unescaped
@@ -144,8 +183,8 @@ func stripSlashes(s string) string {
return sb.String()
}
func (c CPE) String() string {
output := CPE{}
func (c Attributes) String() string {
output := Attributes{}
output.Vendor = sanitize(c.Vendor)
output.Product = sanitize(c.Product)
output.Language = sanitize(c.Language)
+26 -26
View File
@@ -12,38 +12,38 @@ import (
"github.com/stretchr/testify/require"
)
func Test_New(t *testing.T) {
func Test_NewAttributes(t *testing.T) {
tests := []struct {
name string
input string
expected CPE
expected Attributes
}{
{
name: "gocase",
input: `cpe:/a:10web:form_maker:1.0.0::~~~wordpress~~`,
expected: Must(`cpe:2.3:a:10web:form_maker:1.0.0:*:*:*:*:wordpress:*:*`),
expected: MustAttributes(`cpe:2.3:a:10web:form_maker:1.0.0:*:*:*:*:wordpress:*:*`),
},
{
name: "dashes",
input: `cpe:/a:7-zip:7-zip:4.56:beta:~~~windows~~`,
expected: Must(`cpe:2.3:a:7-zip:7-zip:4.56:beta:*:*:*:windows:*:*`),
expected: MustAttributes(`cpe:2.3:a:7-zip:7-zip:4.56:beta:*:*:*:windows:*:*`),
},
{
name: "URL escape characters",
input: `cpe:/a:%240.99_kindle_books_project:%240.99_kindle_books:6::~~~android~~`,
expected: Must(`cpe:2.3:a:\$0.99_kindle_books_project:\$0.99_kindle_books:6:*:*:*:*:android:*:*`),
expected: MustAttributes(`cpe:2.3:a:\$0.99_kindle_books_project:\$0.99_kindle_books:6:*:*:*:*:android:*:*`),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual, err := New(test.input)
actual, err := NewAttributes(test.input)
if err != nil {
t.Fatalf("got an error while creating CPE: %+v", err)
t.Fatalf("got an error while creating Attributes: %+v", err)
}
if d := cmp.Diff(actual, test.expected); d != "" {
t.Errorf("CPE mismatch (-want +got):\n%s", d)
t.Errorf("Attributes mismatch (-want +got):\n%s", d)
}
})
@@ -82,9 +82,9 @@ func Test_normalizeCpeField(t *testing.T) {
func Test_CPEParser(t *testing.T) {
var testCases []struct {
CPEString string `json:"cpe-string"`
CPEUrl string `json:"cpe-url"`
WFN CPE `json:"wfn"`
CPEString string `json:"cpe-string"`
CPEUrl string `json:"cpe-url"`
WFN Attributes `json:"wfn"`
}
out, err := os.ReadFile("test-fixtures/cpe-data.json")
require.NoError(t, err)
@@ -92,9 +92,9 @@ func Test_CPEParser(t *testing.T) {
for _, test := range testCases {
t.Run(test.CPEString, func(t *testing.T) {
c1, err := New(test.CPEString)
c1, err := NewAttributes(test.CPEString)
assert.NoError(t, err)
c2, err := New(test.CPEUrl)
c2, err := NewAttributes(test.CPEUrl)
assert.NoError(t, err)
assert.Equal(t, c1, c2)
assert.Equal(t, c1, test.WFN)
@@ -161,11 +161,11 @@ func Test_InvalidCPE(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
c, err := New(test.in)
c, err := NewAttributes(test.in)
if test.expectedErr {
assert.Error(t, err)
if t.Failed() {
t.Logf("got CPE: %q details: %+v", c, c)
t.Logf("got Attributes: %q details: %+v", c, c)
}
return
}
@@ -179,12 +179,12 @@ func Test_RoundTrip(t *testing.T) {
tests := []struct {
name string
cpe string
parsedCPE CPE
parsedCPE Attributes
}{
{
name: "normal",
cpe: "cpe:2.3:a:some-vendor:name:3.2:*:*:*:*:*:*:*",
parsedCPE: CPE{
parsedCPE: Attributes{
Part: "a",
Vendor: "some-vendor",
Product: "name",
@@ -194,7 +194,7 @@ func Test_RoundTrip(t *testing.T) {
{
name: "escaped colon",
cpe: "cpe:2.3:a:some-vendor:name:1\\:3.2:*:*:*:*:*:*:*",
parsedCPE: CPE{
parsedCPE: Attributes{
Part: "a",
Vendor: "some-vendor",
Product: "name",
@@ -204,7 +204,7 @@ func Test_RoundTrip(t *testing.T) {
{
name: "escaped forward slash",
cpe: "cpe:2.3:a:test\\/some-vendor:name:3.2:*:*:*:*:*:*:*",
parsedCPE: CPE{
parsedCPE: Attributes{
Part: "a",
Vendor: "test/some-vendor",
Product: "name",
@@ -215,13 +215,13 @@ func Test_RoundTrip(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
// CPE string must be preserved through a round trip
assert.Equal(t, test.cpe, Must(test.cpe).String())
// The parsed CPE must be the same after a round trip
assert.Equal(t, Must(test.cpe), Must(Must(test.cpe).String()))
// The test case parsed CPE must be the same after parsing the input string
assert.Equal(t, test.parsedCPE, Must(test.cpe))
// The test case parsed CPE must produce the same string as the input cpe
// Attributes string must be preserved through a round trip
assert.Equal(t, test.cpe, MustAttributes(test.cpe).String())
// The parsed Attributes must be the same after a round trip
assert.Equal(t, MustAttributes(test.cpe), MustAttributes(MustAttributes(test.cpe).String()))
// The test case parsed Attributes must be the same after parsing the input string
assert.Equal(t, test.parsedCPE, MustAttributes(test.cpe))
// The test case parsed Attributes must produce the same string as the input cpe
assert.Equal(t, test.parsedCPE.String(), test.cpe)
})
}
+17 -15
View File
@@ -1,25 +1,27 @@
package cpe
import (
"fmt"
"sort"
)
func Merge(a, b []CPE) (result []CPE) {
aCPEs := make(map[string]CPE)
// keep all CPEs from a and create a quick string-based lookup
for _, aCPE := range a {
aCPEs[aCPE.BindToFmtString()] = aCPE
result = append(result, aCPE)
// Merge returns unique SourcedCPEs that are found in A or B
// Two SourcedCPEs are identical if their source and normalized string are identical
func Merge(a, b []CPE) []CPE {
var result []CPE
dedupe := make(map[string]CPE)
key := func(scpe CPE) string {
return fmt.Sprintf("%s:%s", scpe.Source.String(), scpe.Attributes.BindToFmtString())
}
// keep all unique CPEs from b
for _, bCPE := range b {
if _, exists := aCPEs[bCPE.BindToFmtString()]; !exists {
result = append(result, bCPE)
}
for _, s := range a {
dedupe[key(s)] = s
}
sort.Sort(BySpecificity(result))
for _, s := range b {
dedupe[key(s)] = s
}
for _, val := range dedupe {
result = append(result, val)
}
sort.Sort(BySourceThenSpecificity(result))
return result
}
+9 -7
View File
@@ -16,18 +16,20 @@ func Test_Merge(t *testing.T) {
name: "merge, removing duplicates and ordered",
input: [][]CPE{
{
Must("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*", NVDDictionaryLookupSource),
Must("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*", DeclaredSource),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*", GeneratedSource),
},
{
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*", DeclaredSource),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*", GeneratedSource),
},
},
expected: []CPE{
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*"),
Must("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*", NVDDictionaryLookupSource),
Must("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*", DeclaredSource),
Must("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*", DeclaredSource),
Must("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*", GeneratedSource),
},
},
}
+31 -2
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"runtime/debug"
"strings"
"github.com/anchore/syft/internal/task"
@@ -44,9 +45,34 @@ func DefaultCreateSBOMConfig() *CreateSBOMConfig {
Files: filecataloging.DefaultConfig(),
Parallelism: 1,
packageTaskFactories: task.DefaultPackageTaskFactories(),
// library consumers are free to override the tool values to fit their needs, however, we have some sane defaults
// to ensure that SBOMs generated don't have missing tool metadata.
ToolName: "syft",
ToolVersion: syftVersion(),
}
}
func syftVersion() string {
// extract the syft version from the go module info from the current binary that is running. This is useful for
// library consumers to at least encode the version of syft that was used to generate the SBOM. Note: we don't
// use the version info from main because it's baked in with ldflags, which we don't control for library consumers.
// This approach won't work in all cases though, such as when the binary is stripped of the buildinfo section.
buildInfo, ok := debug.ReadBuildInfo()
if !ok {
return ""
}
for _, d := range buildInfo.Deps {
if d.Path == "github.com/anchore/syft" && d.Version != "(devel)" {
return d.Version
}
}
return ""
}
// WithTool allows for setting the specific name, version, and any additional configuration that is not captured
// in the syft default API configuration. This could cover inputs for catalogers that were user-provided, thus,
// is not visible to the syft API, but would be useful to see in the SBOM output.
@@ -185,6 +211,9 @@ func (c *CreateSBOMConfig) fileTasks() []task.Task {
if t := task.NewFileContentCatalogerTask(c.Files.Content); t != nil {
tsks = append(tsks, t)
}
if t := task.NewExecutableCatalogerTask(c.Files.Selection, c.Files.Executable); t != nil {
tsks = append(tsks, t)
}
return tsks
}
@@ -316,9 +345,9 @@ func (c *CreateSBOMConfig) Create(ctx context.Context, src source.Source) (*sbom
func findDefaultTag(src source.Description) (string, error) {
switch m := src.Metadata.(type) {
case source.StereoscopeImageSourceMetadata:
case source.ImageMetadata:
return pkgcataloging.ImageTag, nil
case source.FileSourceMetadata, source.DirectorySourceMetadata:
case source.FileMetadata, source.DirectoryMetadata:
return pkgcataloging.DirectoryTag, nil
default:
return "", fmt.Errorf("unable to determine default cataloger tag for source type=%T", m)
+21 -18
View File
@@ -62,15 +62,15 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
}
imgSrc := source.Description{
Metadata: source.StereoscopeImageSourceMetadata{},
Metadata: source.ImageMetadata{},
}
dirSrc := source.Description{
Metadata: source.DirectorySourceMetadata{},
Metadata: source.DirectoryMetadata{},
}
fileSrc := source.Description{
Metadata: source.FileSourceMetadata{},
Metadata: source.FileMetadata{},
}
tests := []struct {
@@ -88,7 +88,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
wantTaskNames: [][]string{
environmentCatalogerNames(),
pkgCatalogerNamesWithTagOrName(t, "image"),
fileCatalogerNames(true, true),
fileCatalogerNames(true, true, true),
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -106,7 +106,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
wantTaskNames: [][]string{
environmentCatalogerNames(),
pkgCatalogerNamesWithTagOrName(t, "directory"),
fileCatalogerNames(true, true),
fileCatalogerNames(true, true, true),
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -125,7 +125,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
wantTaskNames: [][]string{
environmentCatalogerNames(),
pkgCatalogerNamesWithTagOrName(t, "directory"),
fileCatalogerNames(true, true),
fileCatalogerNames(true, true, true),
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -139,11 +139,11 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
{
name: "no file digest cataloger",
src: imgSrc,
cfg: DefaultCreateSBOMConfig().WithFilesConfig(filecataloging.DefaultConfig().WithHashers(nil)),
cfg: DefaultCreateSBOMConfig().WithFilesConfig(filecataloging.DefaultConfig().WithHashers()),
wantTaskNames: [][]string{
environmentCatalogerNames(),
pkgCatalogerNamesWithTagOrName(t, "image"),
fileCatalogerNames(false, true), // note: the digest cataloger is not included
fileCatalogerNames(false, true, true), // note: the digest cataloger is not included
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -181,7 +181,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
// note: there is a single group of catalogers for pkgs and files
append(
pkgCatalogerNamesWithTagOrName(t, "image"),
fileCatalogerNames(true, true)...,
fileCatalogerNames(true, true, true)...,
),
relationshipCatalogerNames(),
},
@@ -202,7 +202,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
wantTaskNames: [][]string{
environmentCatalogerNames(),
addTo(pkgCatalogerNamesWithTagOrName(t, "image"), "persistent"),
fileCatalogerNames(true, true),
fileCatalogerNames(true, true, true),
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -222,7 +222,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
wantTaskNames: [][]string{
environmentCatalogerNames(),
addTo(pkgCatalogerNamesWithTagOrName(t, "directory"), "persistent"),
fileCatalogerNames(true, true),
fileCatalogerNames(true, true, true),
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -242,7 +242,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
wantTaskNames: [][]string{
environmentCatalogerNames(),
addTo(pkgIntersect("image", "javascript"), "persistent"),
fileCatalogerNames(true, true),
fileCatalogerNames(true, true, true),
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -263,7 +263,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
wantTaskNames: [][]string{
environmentCatalogerNames(),
addTo(pkgCatalogerNamesWithTagOrName(t, "image"), "user-provided"),
fileCatalogerNames(true, true),
fileCatalogerNames(true, true, true),
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -283,7 +283,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) {
wantTaskNames: [][]string{
environmentCatalogerNames(),
pkgCatalogerNamesWithTagOrName(t, "image"),
fileCatalogerNames(true, true),
fileCatalogerNames(true, true, true),
relationshipCatalogerNames(),
},
wantManifest: &catalogerManifest{
@@ -367,11 +367,14 @@ func pkgCatalogerNamesWithTagOrName(t *testing.T, token string) []string {
return names
}
func fileCatalogerNames(digest, metadata bool) []string {
func fileCatalogerNames(digest, metadata, executable bool) []string {
var names []string
if digest {
names = append(names, "file-digest-cataloger")
}
if executable {
names = append(names, "file-executable-cataloger")
}
if metadata {
names = append(names, "file-metadata-cataloger")
}
@@ -434,21 +437,21 @@ func Test_findDefaultTag(t *testing.T) {
{
name: "image",
src: source.Description{
Metadata: source.StereoscopeImageSourceMetadata{},
Metadata: source.ImageMetadata{},
},
want: pkgcataloging.ImageTag,
},
{
name: "directory",
src: source.Description{
Metadata: source.DirectorySourceMetadata{},
Metadata: source.DirectoryMetadata{},
},
want: pkgcataloging.DirectoryTag,
},
{
name: "file",
src: source.Description{
Metadata: source.FileSourceMetadata{},
Metadata: source.FileMetadata{},
},
want: pkgcataloging.DirectoryTag, // not a mistake...
},
+244
View File
@@ -0,0 +1,244 @@
package executable
import (
"bytes"
"debug/elf"
"debug/macho"
"encoding/binary"
"fmt"
"sort"
"github.com/bmatcuk/doublestar/v4"
"github.com/dustin/go-humanize"
"github.com/anchore/syft/internal/bus"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/mimetype"
"github.com/anchore/syft/syft/event/monitor"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/unionreader"
)
type Config struct {
MIMETypes []string `json:"mime-types" yaml:"mime-types" mapstructure:"mime-types"`
Globs []string `json:"globs" yaml:"globs" mapstructure:"globs"`
}
type Cataloger struct {
config Config
}
func DefaultConfig() Config {
m := mimetype.ExecutableMIMETypeSet.List()
sort.Strings(m)
return Config{
MIMETypes: m,
Globs: nil,
}
}
func NewCataloger(cfg Config) *Cataloger {
return &Cataloger{
config: cfg,
}
}
func (i *Cataloger) Catalog(resolver file.Resolver) (map[file.Coordinates]file.Executable, error) {
locs, err := resolver.FilesByMIMEType(i.config.MIMETypes...)
if err != nil {
return nil, fmt.Errorf("unable to get file locations for binaries: %w", err)
}
locs, err = filterByGlobs(locs, i.config.Globs)
if err != nil {
return nil, err
}
prog := catalogingProgress(int64(len(locs)))
results := make(map[file.Coordinates]file.Executable)
for _, loc := range locs {
prog.AtomicStage.Set(loc.Path())
reader, err := resolver.FileContentsByLocation(loc)
if err != nil {
// TODO: known-unknowns
log.WithFields("error", err).Warnf("unable to get file contents for %q", loc.RealPath)
continue
}
uReader, err := unionreader.GetUnionReader(reader)
if err != nil {
// TODO: known-unknowns
log.WithFields("error", err).Warnf("unable to get union reader for %q", loc.RealPath)
continue
}
exec, err := processExecutable(loc, uReader)
if err != nil {
log.WithFields("error", err).Warnf("unable to process executable %q", loc.RealPath)
}
if exec != nil {
prog.Increment()
results[loc.Coordinates] = *exec
}
}
log.Debugf("executable cataloger processed %d files", len(results))
prog.AtomicStage.Set(fmt.Sprintf("%s executables", humanize.Comma(prog.Current())))
prog.SetCompleted()
return results, nil
}
func catalogingProgress(locations int64) *monitor.CatalogerTaskProgress {
info := monitor.GenericTask{
Title: monitor.Title{
Default: "Executables",
},
ParentID: monitor.TopLevelCatalogingTaskID,
}
return bus.StartCatalogerTask(info, locations, "")
}
func filterByGlobs(locs []file.Location, globs []string) ([]file.Location, error) {
if len(globs) == 0 {
return locs, nil
}
var filteredLocs []file.Location
for _, loc := range locs {
matches, err := locationMatchesGlob(loc, globs)
if err != nil {
return nil, err
}
if matches {
filteredLocs = append(filteredLocs, loc)
}
}
return filteredLocs, nil
}
func locationMatchesGlob(loc file.Location, globs []string) (bool, error) {
for _, glob := range globs {
for _, path := range []string{loc.RealPath, loc.AccessPath} {
if path == "" {
continue
}
matches, err := doublestar.Match(glob, path)
if err != nil {
return false, fmt.Errorf("unable to match glob %q to path %q: %w", glob, path, err)
}
if matches {
return true, nil
}
}
}
return false, nil
}
func processExecutable(loc file.Location, reader unionreader.UnionReader) (*file.Executable, error) {
data := file.Executable{}
// determine the executable format
format, err := findExecutableFormat(reader)
if err != nil {
return nil, fmt.Errorf("unable to determine executable kind: %w", err)
}
if format == "" {
log.Debugf("unable to determine executable format for %q", loc.RealPath)
return nil, nil
}
data.Format = format
switch format {
case file.ELF:
if err := findELFFeatures(&data, reader); err != nil {
log.WithFields("error", err).Tracef("unable to determine ELF features for %q", loc.RealPath)
}
case file.PE:
if err := findPEFeatures(&data, reader); err != nil {
log.WithFields("error", err).Tracef("unable to determine PE features for %q", loc.RealPath)
}
case file.MachO:
if err := findMachoFeatures(&data, reader); err != nil {
log.WithFields("error", err).Tracef("unable to determine Macho features for %q", loc.RealPath)
}
}
// always allocate collections for presentation
if data.ImportedLibraries == nil {
data.ImportedLibraries = []string{}
}
return &data, nil
}
func findExecutableFormat(reader unionreader.UnionReader) (file.ExecutableFormat, error) {
// read the first sector of the file
buf := make([]byte, 512)
n, err := reader.ReadAt(buf, 0)
if err != nil {
return "", fmt.Errorf("unable to read first sector of file: %w", err)
}
if n < 512 {
return "", fmt.Errorf("unable to read enough bytes to determine executable format")
}
switch {
case isMacho(buf):
return file.MachO, nil
case isPE(buf):
return file.PE, nil
case isELF(buf):
return file.ELF, nil
}
return "", nil
}
func isMacho(by []byte) bool {
// sourced from https://github.com/gabriel-vasile/mimetype/blob/02af149c0dfd1444d9256fc33c2012bb3153e1d2/internal/magic/binary.go#L44
if classOrMachOFat(by) && by[7] < 20 {
return true
}
if len(by) < 4 {
return false
}
be := binary.BigEndian.Uint32(by)
le := binary.LittleEndian.Uint32(by)
return be == macho.Magic32 ||
le == macho.Magic32 ||
be == macho.Magic64 ||
le == macho.Magic64
}
// Java bytecode and Mach-O binaries share the same magic number.
// More info here https://github.com/threatstack/libmagic/blob/master/magic/Magdir/cafebabe
func classOrMachOFat(in []byte) bool {
// sourced from https://github.com/gabriel-vasile/mimetype/blob/02af149c0dfd1444d9256fc33c2012bb3153e1d2/internal/magic/binary.go#L44
// There should be at least 8 bytes for both of them because the only way to
// quickly distinguish them is by comparing byte at position 7
if len(in) < 8 {
return false
}
return bytes.HasPrefix(in, []byte{0xCA, 0xFE, 0xBA, 0xBE})
}
func isPE(by []byte) bool {
return bytes.HasPrefix(by, []byte("MZ"))
}
func isELF(by []byte) bool {
return bytes.HasPrefix(by, []byte(elf.ELFMAG))
}
+270
View File
@@ -0,0 +1,270 @@
package executable
import (
"debug/elf"
"regexp"
"strings"
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/unionreader"
)
func findELFFeatures(data *file.Executable, reader unionreader.UnionReader) error {
f, err := elf.NewFile(reader)
if err != nil {
return err
}
libs, err := f.ImportedLibraries()
if err != nil {
// TODO: known-unknowns
log.WithFields("error", err).Trace("unable to read imported libraries from elf file")
libs = nil
}
if libs == nil {
libs = []string{}
}
data.ImportedLibraries = libs
data.ELFSecurityFeatures = findELFSecurityFeatures(f)
data.HasEntrypoint = elfHasEntrypoint(f)
data.HasExports = elfHasExports(f)
return nil
}
func findELFSecurityFeatures(f *elf.File) *file.ELFSecurityFeatures {
return &file.ELFSecurityFeatures{
SymbolTableStripped: isElfSymbolTableStripped(f),
StackCanary: checkElfStackCanary(f),
NoExecutable: checkElfNXProtection(f),
RelocationReadOnly: checkElfRelROProtection(f),
PositionIndependentExecutable: isELFPIE(f),
DynamicSharedObject: isELFDSO(f),
LlvmSafeStack: checkLLVMSafeStack(f),
LlvmControlFlowIntegrity: checkLLVMControlFlowIntegrity(f),
ClangFortifySource: checkClangFortifySource(f),
}
}
func isElfSymbolTableStripped(file *elf.File) bool {
return file.Section(".symtab") == nil
}
func checkElfStackCanary(file *elf.File) *bool {
return hasAnyDynamicSymbols(file, "__stack_chk_fail", "__stack_chk_guard")
}
func hasAnyDynamicSymbols(file *elf.File, symbolNames ...string) *bool {
dynSyms, err := file.DynamicSymbols()
if err != nil {
// TODO: known-unknowns
log.WithFields("error", err).Trace("unable to read dynamic symbols from elf file")
return nil
}
nameSet := strset.New(symbolNames...)
for _, sym := range dynSyms {
if nameSet.Has(sym.Name) {
return boolRef(true)
}
}
return boolRef(false)
}
func boolRef(b bool) *bool {
return &b
}
func checkElfNXProtection(file *elf.File) bool {
// find the program headers until you find the GNU_STACK segment
for _, prog := range file.Progs {
if prog.Type == elf.PT_GNU_STACK {
// check if the GNU_STACK segment is executable
return prog.Flags&elf.PF_X == 0
}
}
return false
}
func checkElfRelROProtection(f *elf.File) file.RelocationReadOnly {
// background on relro https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro
hasRelro := false
hasBindNow := hasBindNowDynTagOrFlag(f)
for _, prog := range f.Progs {
if prog.Type == elf.PT_GNU_RELRO {
hasRelro = true
break
}
}
switch {
case hasRelro && hasBindNow:
return file.RelocationReadOnlyFull
case hasRelro:
return file.RelocationReadOnlyPartial
default:
return file.RelocationReadOnlyNone
}
}
func hasBindNowDynTagOrFlag(f *elf.File) bool {
if hasElfDynTag(f, elf.DT_BIND_NOW) {
// support older binaries...
return true
}
// "DT_BIND_NOW ... use has been superseded by the DF_BIND_NOW flag"
// source: https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html
return hasElfDynFlag(f, elf.DF_BIND_NOW)
}
func hasElfDynFlag(f *elf.File, flag elf.DynFlag) bool {
vals, err := f.DynValue(elf.DT_FLAGS)
if err != nil {
// TODO: known-unknowns
log.WithFields("error", err).Trace("unable to read DT_FLAGS from elf file")
return false
}
for _, val := range vals {
if val&uint64(flag) != 0 {
return true
}
}
return false
}
func hasElfDynFlag1(f *elf.File, flag elf.DynFlag1) bool {
vals, err := f.DynValue(elf.DT_FLAGS_1)
if err != nil {
// TODO: known-unknowns
log.WithFields("error", err).Trace("unable to read DT_FLAGS_1 from elf file")
return false
}
for _, val := range vals {
if val&uint64(flag) != 0 {
return true
}
}
return false
}
func hasElfDynTag(f *elf.File, tag elf.DynTag) bool {
// source https://github.com/golang/go/blob/9b4b3e5acca2dabe107fa2c3ed963097d78a4562/src/cmd/cgo/internal/testshared/shared_test.go#L280
ds := f.SectionByType(elf.SHT_DYNAMIC)
if ds == nil {
return false
}
d, err := ds.Data()
if err != nil {
return false
}
for len(d) > 0 {
var t elf.DynTag
switch f.Class {
case elf.ELFCLASS32:
t = elf.DynTag(f.ByteOrder.Uint32(d[0:4]))
d = d[8:]
case elf.ELFCLASS64:
t = elf.DynTag(f.ByteOrder.Uint64(d[0:8]))
d = d[16:]
}
if t == tag {
return true
}
}
return false
}
func isELFPIE(f *elf.File) bool {
// being a shared object is not sufficient to be a PIE, the explicit flag must be set also
return isELFDSO(f) && hasElfDynFlag1(f, elf.DF_1_PIE)
}
func isELFDSO(f *elf.File) bool {
return f.Type == elf.ET_DYN
}
func checkLLVMSafeStack(file *elf.File) *bool {
// looking for the presence of https://github.com/microsoft/compiler-rt/blob/30b3b8cb5c9a0854f2f40f187c6f6773561a35f2/lib/safestack/safestack.cc#L207
return hasAnyDynamicSymbols(file, "__safestack_init")
}
func checkLLVMControlFlowIntegrity(file *elf.File) *bool {
// look for any symbols that are functions and end with ".cfi"
dynSyms, err := file.Symbols()
if err != nil {
// TODO: known-unknowns
log.WithFields("error", err).Trace("unable to read symbols from elf file")
return nil
}
for _, sym := range dynSyms {
if isFunction(sym) && strings.HasSuffix(sym.Name, ".cfi") {
return boolRef(true)
}
}
return boolRef(false)
}
func isFunction(sym elf.Symbol) bool {
return elf.ST_TYPE(sym.Info) == elf.STT_FUNC
}
var fortifyPattern = regexp.MustCompile(`__\w+_chk@.+`)
func checkClangFortifySource(file *elf.File) *bool {
dynSyms, err := file.Symbols()
if err != nil {
// TODO: known-unknowns
log.WithFields("error", err).Trace("unable to read symbols from elf file")
return nil
}
for _, sym := range dynSyms {
if isFunction(sym) && fortifyPattern.MatchString(sym.Name) {
return boolRef(true)
}
}
return boolRef(false)
}
func elfHasEntrypoint(f *elf.File) bool {
// this is akin to
// readelf -h ./path/to/bin | grep "Entry point address"
return f.Entry > 0
}
func elfHasExports(f *elf.File) bool {
// this is akin to:
// nm -D --defined-only ./path/to/bin | grep ' T \| W \| B '
// where:
// T - symbol in the text section
// W - weak symbol that might be overwritten
// B - variable located in the uninitialized data section
// really anything that is not marked with 'U' (undefined) is considered an export.
symbols, err := f.DynamicSymbols()
if err != nil {
// TODO: known-unknowns?
return false
}
for _, s := range symbols {
// check if the section is SHN_UNDEF, which is the "U" output type from "nm -D" meaning that the symbol
// is undefined, meaning it is not an export. Any entry that is not undefined is considered an export.
if s.Section != elf.SHN_UNDEF {
return true
}
}
return false
}
+226
View File
@@ -0,0 +1,226 @@
package executable
import (
"debug/elf"
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/unionreader"
)
func Test_findELFSecurityFeatures(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper()
f, err := os.Open(filepath.Join("test-fixtures/elf", fixture))
require.NoError(t, err)
return f
}
tests := []struct {
name string
fixture string
want *file.ELFSecurityFeatures
wantStripped bool
}{
{
name: "detect canary",
fixture: "bin/with_canary",
want: &file.ELFSecurityFeatures{
StackCanary: boolRef(true), // ! important !
RelocationReadOnly: file.RelocationReadOnlyNone,
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(false),
ClangFortifySource: boolRef(false),
},
},
{
name: "detect nx",
fixture: "bin/with_nx",
want: &file.ELFSecurityFeatures{
StackCanary: boolRef(false),
NoExecutable: true, // ! important !
RelocationReadOnly: file.RelocationReadOnlyNone,
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(false),
ClangFortifySource: boolRef(false),
},
},
{
name: "detect relro",
fixture: "bin/with_relro",
want: &file.ELFSecurityFeatures{
StackCanary: boolRef(false),
RelocationReadOnly: file.RelocationReadOnlyFull, // ! important !
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(false),
ClangFortifySource: boolRef(false),
},
},
{
name: "detect partial relro",
fixture: "bin/with_partial_relro",
want: &file.ELFSecurityFeatures{
StackCanary: boolRef(false),
RelocationReadOnly: file.RelocationReadOnlyPartial, // ! important !
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(false),
ClangFortifySource: boolRef(false),
},
},
{
name: "detect pie",
fixture: "bin/with_pie",
want: &file.ELFSecurityFeatures{
StackCanary: boolRef(false),
RelocationReadOnly: file.RelocationReadOnlyNone,
PositionIndependentExecutable: true, // ! important !
DynamicSharedObject: true, // ! important !
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(false),
ClangFortifySource: boolRef(false),
},
},
{
name: "detect dso",
fixture: "bin/pie_false_positive.so",
want: &file.ELFSecurityFeatures{
StackCanary: boolRef(false),
RelocationReadOnly: file.RelocationReadOnlyPartial,
NoExecutable: true,
PositionIndependentExecutable: false, // ! important !
DynamicSharedObject: true, // ! important !
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(false),
ClangFortifySource: boolRef(false),
},
},
{
name: "detect safestack",
fixture: "bin/with_safestack",
want: &file.ELFSecurityFeatures{
NoExecutable: true,
StackCanary: boolRef(false),
RelocationReadOnly: file.RelocationReadOnlyPartial,
PositionIndependentExecutable: false,
DynamicSharedObject: false,
LlvmSafeStack: boolRef(true), // ! important !
LlvmControlFlowIntegrity: boolRef(false),
ClangFortifySource: boolRef(false),
},
},
{
name: "detect cfi",
fixture: "bin/with_cfi",
want: &file.ELFSecurityFeatures{
NoExecutable: true,
StackCanary: boolRef(false),
RelocationReadOnly: file.RelocationReadOnlyPartial,
PositionIndependentExecutable: false,
DynamicSharedObject: false,
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(true), // ! important !
ClangFortifySource: boolRef(false),
},
},
{
name: "detect fortify",
fixture: "bin/with_fortify",
want: &file.ELFSecurityFeatures{
NoExecutable: true,
StackCanary: boolRef(false),
RelocationReadOnly: file.RelocationReadOnlyPartial,
PositionIndependentExecutable: false,
DynamicSharedObject: false,
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(false),
ClangFortifySource: boolRef(true), // ! important !
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := elf.NewFile(readerForFixture(t, tt.fixture))
require.NoError(t, err)
got := findELFSecurityFeatures(f)
if d := cmp.Diff(tt.want, got); d != "" {
t.Errorf("findELFSecurityFeatures() mismatch (-want +got):\n%s", d)
}
})
}
}
func Test_elfHasEntrypoint(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper()
f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture))
require.NoError(t, err)
return f
}
tests := []struct {
name string
fixture string
want bool
}{
{
name: "shared lib",
fixture: "bin/libhello.so",
want: false,
},
{
name: "application",
fixture: "bin/hello_linux",
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := elf.NewFile(readerForFixture(t, tt.fixture))
require.NoError(t, err)
assert.Equal(t, tt.want, elfHasEntrypoint(f))
})
}
}
func Test_elfHasExports(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper()
f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture))
require.NoError(t, err)
return f
}
tests := []struct {
name string
fixture string
want bool
}{
{
name: "shared lib",
fixture: "bin/libhello.so",
want: true,
},
{
name: "application",
fixture: "bin/hello_linux",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := elf.NewFile(readerForFixture(t, tt.fixture))
require.NoError(t, err)
assert.Equal(t, tt.want, elfHasExports(f))
})
}
}
+92
View File
@@ -0,0 +1,92 @@
package executable
import (
"debug/macho"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/unionreader"
)
// source http://www.cilinder.be/docs/next/NeXTStep/3.3/nd/DevTools/14_MachO/MachO.htmld/index.html
const (
machoNPExt uint8 = 0x10 /* N_PEXT: private external symbol bit */
machoNExt uint8 = 0x01 /* N_EXT: external symbol bit, set for external symbols */
// > #define LC_REQ_DYLD 0x80000000
// > #define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
lcMain = 0x28 | 0x80000000
)
func findMachoFeatures(data *file.Executable, reader unionreader.UnionReader) error {
// TODO: support security features
// TODO: support multi-architecture binaries
f, err := macho.NewFile(reader)
if err != nil {
return err
}
libs, err := f.ImportedLibraries()
if err != nil {
return err
}
data.ImportedLibraries = libs
data.HasEntrypoint = machoHasEntrypoint(f)
data.HasExports = machoHasExports(f)
return nil
}
func machoHasEntrypoint(f *macho.File) bool {
// derived from struct entry_point_command found from which explicitly calls out LC_MAIN:
// https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL_HEADERS/mach-o/loader.h
// we need to look for both LC_MAIN and LC_UNIXTHREAD commands to determine if the file is an executable
//
// this is akin to:
// otool -l ./path/to/bin | grep -A4 LC_MAIN
// otool -l ./path/to/bin | grep -A4 LC_UNIXTHREAD
for _, l := range f.Loads {
data := l.Raw()
cmd := f.ByteOrder.Uint32(data)
if macho.LoadCmd(cmd) == macho.LoadCmdUnixThread || macho.LoadCmd(cmd) == lcMain {
return true
}
}
return false
}
func machoHasExports(f *macho.File) bool {
for _, sym := range f.Symtab.Syms {
// look for symbols that are:
// - not private and are external
// - do not have an N_TYPE value of N_UNDF (undefined symbol)
//
// here's the bit layout for the n_type field:
// 0000 0000
// ─┬─│ ─┬─│
// │ │ │ └─ N_EXT (external symbol)
// │ │ └─ N_TYPE (N_UNDF, N_ABS, N_SECT, N_PBUD, N_INDR)
// │ └─ N_PEXT (private external symbol)
// └─ N_STAB (debugging symbol)
//
isExternal := sym.Type&machoNExt == machoNExt
isPrivate := sym.Type&machoNPExt == machoNPExt
nTypeIsUndefined := sym.Type&0x0e == 0
if isExternal && !isPrivate {
if sym.Name == "_main" || sym.Name == "__mh_execute_header" {
// ...however there are some symbols that are not exported but are still important
// for debugging or as an entrypoint, so we need to explicitly check for them
continue
}
if nTypeIsUndefined {
continue
}
// we have a symbol that is not private and is external
// and is not undefined, so it is an export
return true
}
}
return false
}
@@ -0,0 +1,80 @@
package executable
import (
"debug/macho"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/internal/unionreader"
)
func Test_machoHasEntrypoint(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper()
f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture))
require.NoError(t, err)
return f
}
tests := []struct {
name string
fixture string
want bool
}{
{
name: "shared lib",
fixture: "bin/libhello.dylib",
want: false,
},
{
name: "application",
fixture: "bin/hello_mac",
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := macho.NewFile(readerForFixture(t, tt.fixture))
require.NoError(t, err)
assert.Equal(t, tt.want, machoHasEntrypoint(f))
})
}
}
func Test_machoHasExports(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper()
f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture))
require.NoError(t, err)
return f
}
tests := []struct {
name string
fixture string
want bool
}{
{
name: "shared lib",
fixture: "bin/libhello.dylib",
want: true,
},
{
name: "application",
fixture: "bin/hello_mac",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := macho.NewFile(readerForFixture(t, tt.fixture))
require.NoError(t, err)
assert.Equal(t, tt.want, machoHasExports(f))
})
}
}
+84
View File
@@ -0,0 +1,84 @@
package executable
import (
"debug/pe"
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/unionreader"
)
func findPEFeatures(data *file.Executable, reader unionreader.UnionReader) error {
// TODO: support security features
f, err := pe.NewFile(reader)
if err != nil {
return err
}
libs, err := f.ImportedLibraries()
if err != nil {
return err
}
data.ImportedLibraries = libs
data.HasEntrypoint = peHasEntrypoint(f)
data.HasExports = peHasExports(f)
return nil
}
var (
windowsExeEntrypoints = strset.New("main", "WinMain", "wWinMain")
windowsDllEntrypoints = strset.New("DllMain", "_DllMainCRTStartup@12", "CRT_INIT")
)
func peHasEntrypoint(f *pe.File) bool {
// DLLs can have entrypoints, but they are not "executables" in the traditional sense,
// but instead point to an initialization function (DLLMain).
// The PE format does not require an entrypoint, so it is possible to not have one, however,
// the microsoft C runtime does: https://learn.microsoft.com/en-US/troubleshoot/developer/visualstudio/cpp/libraries/use-c-run-time
//
// > When building a DLL which uses any of the C Run-time libraries, in order to ensure that the CRT is properly initialized, either
// > 1. the initialization function must be named DllMain() and the entry point must be specified with the linker option -entry:_DllMainCRTStartup@12 - or -
// > 2. the DLL's entry point must explicitly call CRT_INIT() on process attach and process detach
//
// This isn't really helpful from a user perspective when it comes to indicating if there is an entrypoint or not
// since it will always effectively be true for DLLs! All DLLs and Executables (aka "modules") have a single
// entrypoint, _GetPEImageBase, but we're more interested in the logical idea of an entrypoint.
// See https://learn.microsoft.com/en-us/windows/win32/psapi/module-information for more details.
var hasLibEntrypoint, hasExeEntrypoint bool
for _, s := range f.Symbols {
if windowsExeEntrypoints.Has(s.Name) {
hasExeEntrypoint = true
}
if windowsDllEntrypoints.Has(s.Name) {
hasLibEntrypoint = true
}
}
switch v := f.OptionalHeader.(type) {
case *pe.OptionalHeader32:
return v.AddressOfEntryPoint > 0 && !hasLibEntrypoint && hasExeEntrypoint
case *pe.OptionalHeader64:
return v.AddressOfEntryPoint > 0 && !hasLibEntrypoint && hasExeEntrypoint
}
return false
}
func peHasExports(f *pe.File) bool {
if f.OptionalHeader == nil {
return false
}
switch v := f.OptionalHeader.(type) {
case *pe.OptionalHeader32:
return v.DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].Size > 0
case *pe.OptionalHeader64:
return v.DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].Size > 0
}
return false
}
+80
View File
@@ -0,0 +1,80 @@
package executable
import (
"debug/pe"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/internal/unionreader"
)
func Test_peHasEntrypoint(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper()
f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture))
require.NoError(t, err)
return f
}
tests := []struct {
name string
fixture string
want bool
}{
{
name: "shared lib",
fixture: "bin/hello.dll", // though this is a shared lib, it has an entrypoint (DLLMain)
want: false,
},
{
name: "application",
fixture: "bin/hello.exe",
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := pe.NewFile(readerForFixture(t, tt.fixture))
require.NoError(t, err)
assert.Equal(t, tt.want, peHasEntrypoint(f))
})
}
}
func Test_peHasExports(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper()
f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture))
require.NoError(t, err)
return f
}
tests := []struct {
name string
fixture string
want bool
}{
{
name: "shared lib",
fixture: "bin/hello.dll",
want: true,
},
{
name: "application",
fixture: "bin/hello.exe",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := pe.NewFile(readerForFixture(t, tt.fixture))
require.NoError(t, err)
assert.Equal(t, tt.want, peHasExports(f))
})
}
}
@@ -0,0 +1,3 @@
bin
actual_verify
Dockerfile.sha256
@@ -0,0 +1,3 @@
../bin
actual_verify
Dockerfile.sha256
@@ -0,0 +1,16 @@
FROM gcc:9.5.0
RUN apt update -y && apt install -y clang cmake git make m4 pkg-config zlib1g-dev
## from https://github.com/runsafesecurity/selfrando/blob/tb-v0.4.2/docs/linux-build-instructions.md
#RUN git clone https://github.com/runsafesecurity/selfrando.git && \
# export SR_ARCH=`uname -m | sed s/i686/x86/` && \
# cd selfrando && \
# cmake . -DSR_DEBUG_LEVEL=env -DCMAKE_BUILD_TYPE=Release -DSR_BUILD_LIBELF=1 \
# -DSR_ARCH=$SR_ARCH -DSR_LOG=console \
# -DSR_FORCE_INPLACE=1 -G "Unix Makefiles" \
# -DCMAKE_INSTALL_PREFIX:PATH=$PWD/out/$SR_ARCH
#RUN cd selfrando && make -j`nprocs --all`
#RUN cd selfrando && make install
RUN curl -o /bin/checksec https://raw.githubusercontent.com/slimm609/checksec.sh/2.6.0/checksec && chmod +x /bin/checksec
@@ -0,0 +1,34 @@
BIN=./bin
TOOL_IMAGE=localhost/syft-bin-build-tools:latest
VERIFY_FILE=actual_verify
all: build verify
tools-check:
@sha256sum -c Dockerfile.sha256 || (echo "Tools Dockerfile has changed" && exit 1)
# for selfrando...
# docker buildx build --platform linux/amd64 -t $(TOOL_IMAGE) .
tools:
@(docker inspect $(TOOL_IMAGE) > /dev/null && make tools-check) || (docker build -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256)
build: tools
mkdir -p $(BIN)
docker run -i -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) make
verify: tools
@rm -f $(VERIFY_FILE)
docker run -i -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) make verify > $(VERIFY_FILE)
@python ./differ expected_verify $(VERIFY_FILE)
debug:
docker run -i --rm -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) bash
cache.fingerprint:
@find project Dockerfile Makefile -type f -exec md5sum {} + | awk '{print $1}' | sort | tee cache.fingerprint
clean:
rm -f $(BIN)/*
.PHONY: build verify debug build-image build-bins clean dockerfile-check cache.fingerprint
@@ -0,0 +1,53 @@
import json
import sys
def load_json(file_path):
with open(file_path, 'r') as file:
return json.load(file)
def diff_json(json1, json2):
differences_found = False
for key in json1:
if key not in json2:
print(f'missing key "{key}"')
continue
differences = []
for subkey in json1[key]:
if subkey not in json2[key]:
differences.append(f' - "{subkey}": expected "{json1[key][subkey]}" but was MISSING')
continue
if subkey in json2[key] and json1[key][subkey] != json2[key][subkey]:
differences.append(f' - "{subkey}": expected "{json1[key][subkey]}" got "{json2[key][subkey]}"')
if differences:
differences_found = True
print(f'{key}')
for diff in differences:
print(diff)
print()
return differences_found
def main():
if len(sys.argv) != 3:
print("Usage: python ./differ file1.json file2.json")
sys.exit(1)
json1 = load_json(sys.argv[1])
json2 = load_json(sys.argv[2])
if diff_json(json1, json2):
print("FAIL: unexpected security feature differences")
sys.exit(1)
else:
print("PASS: all security features accounted for")
sys.exit(0)
main()
@@ -0,0 +1 @@
{ "dir": { "name":"../bin" }, "../bin/no_protection": { "relro":"no","canary":"no","nx":"no","pie":"no","clangcfi":"no","safestack":"no","rpath":"no","runpath":"yes","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/no_protection"}, "../bin/with_nx": { "relro":"no","canary":"no","nx":"yes","pie":"no","clangcfi":"no","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/with_nx"}, "../bin/with_rpath": { "relro":"no","canary":"no","nx":"no","pie":"no","clangcfi":"no","safestack":"no","rpath":"yes","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/with_rpath"}, "../bin/with_canary": { "relro":"no","canary":"yes","nx":"no","pie":"no","clangcfi":"no","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/with_canary"}, "../bin/with_relro": { "relro":"full","canary":"no","nx":"no","pie":"no","clangcfi":"no","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/with_relro"}, "../bin/with_pie": { "relro":"no","canary":"no","nx":"no","pie":"yes","clangcfi":"no","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/with_pie"}, "../bin/with_runpath": { "relro":"no","canary":"no","nx":"no","pie":"no","clangcfi":"no","safestack":"no","rpath":"no","runpath":"yes","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/with_runpath"}, "../bin/with_safestack": { "relro":"partial","canary":"no","nx":"yes","pie":"no","clangcfi":"no","safestack":"yes","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"3", "filename":"../bin/with_safestack"}, "../bin/pie_false_positive.so": { "relro":"partial","canary":"no","nx":"yes","pie":"dso","clangcfi":"no","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"0", "filename":"../bin/pie_false_positive.so"}, "../bin/with_cfi": { "relro":"partial","canary":"no","nx":"yes","pie":"no","clangcfi":"yes","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/with_cfi"}, "../bin/with_partial_relro": { "relro":"partial","canary":"no","nx":"no","pie":"no","clangcfi":"no","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/with_partial_relro"}, "../bin/protected": { "relro":"full","canary":"yes","nx":"yes","pie":"yes","clangcfi":"no","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"no","fortified":"0","fortify-able":"2", "filename":"../bin/protected"}, "../bin/with_fortify": { "relro":"partial","canary":"no","nx":"yes","pie":"no","clangcfi":"no","safestack":"no","rpath":"no","runpath":"no","symbols":"yes","fortify_source":"yes","fortified":"1","fortify-able":"2", "filename":"../bin/with_fortify"}}
@@ -0,0 +1,93 @@
### GCC Options ############################################
CANARY := -fstack-protector
NO_CANARY := -fno-stack-protector
SHARED_OBJ := -shared
RELRO := -z relro -z now
PARTIAL_RELRO := -z relro
NO_RELRO := -z norelro
NX := -z noexecstack
NO_NX := -z execstack
PIE := -fpic -pie
NO_PIE := -no-pie
# deprecated
RPATH := -Wl,--disable-new-dtags,-rpath,./libs
# replaces RPATH (thus us mutually exclusive with it)
RUNPATH := -Wl,-rpath,./libs
GCCFLAGS := -g
### Clang Options ############################################
SAFE_STACK := -fsanitize=safe-stack
CFI := -flto -fvisibility=hidden -fsanitize=cfi
FORTIFY := -O2 -D_FORTIFY_SOURCE=2
### Common Options ############################################
SRC := main.c
LIB_SRC := lib.c
BIN := ../bin
BINS := $(BIN)/no_protection $(BIN)/with_nx $(BIN)/pie_false_positive.so $(BIN)/with_pie $(BIN)/with_canary $(BIN)/with_relro $(BIN)/with_partial_relro $(BIN)/with_rpath $(BIN)/with_runpath $(BIN)/with_safestack $(BIN)/with_cfi $(BIN)/with_fortify $(BIN)/protected
#.PHONY: verify $(BIN)/no_protection $(BIN)/with_nx $(BIN)/pie_false_positive.so $(BIN)/with_pie $(BIN)/with_canary $(BIN)/with_relro $(BIN)/with_partial_relro $(BIN)/with_rpath $(BIN)/with_runpath $(BIN)/with_safestack $(BIN)/with_cfi $(BIN)/with_fortify $(BIN)/protected
.PHONY: verify clean all
all: $(BINS)
$(BIN)/no_protection : $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(NO_CANARY) $(NO_NX) $(NO_RELRO) $(NO_PIE) $(RUNPATH)
$(BIN)/with_nx : $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(NO_CANARY) $(NX) $(NO_RELRO) $(NO_PIE)
$(BIN)/pie_false_positive.so: $(LIB_SRC)
gcc $< -c -Wall -Werror -fpic $(LIB_SRC)
gcc -shared -o $@ lib.o ; rm lib.o
$(BIN)/with_pie: $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(NO_CANARY) $(NO_NX) $(NO_RELRO) $(PIE)
$(BIN)/with_canary: $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(CANARY) $(NO_NX) $(NO_RELRO) $(NO_PIE)
$(BIN)/with_relro: $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(NO_CANARY) $(NO_NX) $(RELRO) $(NO_PIE)
$(BIN)/with_partial_relro: $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(NO_CANARY) $(NO_NX) $(PARTIAL_RELRO) $(NO_PIE)
$(BIN)/with_rpath: $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(NO_CANARY) $(NO_NX) $(NO_RELRO) $(NO_PIE) $(RPATH)
$(BIN)/with_runpath: $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(NO_CANARY) $(NO_NX) $(NO_RELRO) $(NO_PIE) $(RUNPATH)
$(BIN)/with_safestack: $(SRC)
clang $< -o $@ $(SAFE_STACK)
$(BIN)/with_cfi: $(SRC)
clang $< -o $@ $(CFI)
$(BIN)/with_fortify: $(SRC)
clang $< -o $@ $(FORTIFY)
#$(BIN)/with_selfrando: $(SRC)
# srenv gcc $< -o $@ $(GCCFLAGS) $(NO_CANARY) $(NO_NX) $(NO_RELRO) $(NO_PIE)
$(BIN)/protected: $(SRC)
gcc $< -o $@ $(GCCFLAGS) $(CANARY) $(NX) $(RELRO) $(PIE)
verify:
@/bin/checksec --dir=$(BIN) --extended --output=json
clean:
rm -rf $(BINS)
@@ -0,0 +1,6 @@
#include <stdio.h>
void foo(void)
{
puts("Share me!");
}
@@ -0,0 +1,6 @@
#ifndef foo_h__
#define foo_h__
extern void foo(void);
#endif // foo_h__

Some files were not shown because too many files have changed in this diff Show More