Compare commits

...
68 Commits
Author SHA1 Message Date
Alex Goodman 8f6bdde666 Label PRs when the json schema changes (#2240)
* label PRs when the json schema changes

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

* moderate pr comments

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

* be more strict about processing file names

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-20 13:00:15 -04:00
Christopher Angelo PhillipsandAuston-Zhang ef43294d0e Add download location when cataloging directory npm package lock (#2238)
* added download locatoin (resolved) when cataloging a directory - javascript ecosystem- npm - packag-lock
	Signed-off by Auston(Aoxiang) Zhang <auston.zhang@dal.ca>

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

* chore: get DCO to fire

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

---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: Auston-Zhang <ax706429@dal.ca>
2023-10-20 11:40:38 -04:00
Christopher Angelo Phillips e1ad340c2d fix: allow packages to be captured from DIST/EGG case (#2239)
* fix: allow packages to be captured from DIST/EGG case

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

* test: update expected glob paths

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

---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-10-20 11:29:13 -04:00
07f13049da Account for maven bundle plugin and fix filename matching (#2220)
* account for maven bundle plugin and fix filename matching

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

* add in-repo jar tests based on metadata to cover #2130

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

* tests: fix test merge commit

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-10-19 17:57:23 -04:00
dependabot[bot] 6c7900f5b8 chore(deps): bump actions/checkout from 4.1.0 to 4.1.1 (#2236)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
- [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/8ade135a41bc03ea155e62e844d188df1ea18608...b4ffde65f46336ab88eb53be808477a3936bae11)

---
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>
2023-10-18 09:54:26 -04:00
Alex Goodman 7018573bf7 Remove internal string set (#2219)
* remove internal string set

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

* incorporate changes from #2227

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

* beef up the pkg.License.Merg() doc string

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-17 12:52:11 -04:00
Alex Goodman f3ad8cf250 bump clio to get stderr reporting fix (#2232)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-16 12:47:48 -04:00
Alex Goodman 31f1d7dbf0 Fix panic for empty input to Swift cataloger (#2226)
* survive invalid input in swift parser

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

* add empty file

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-16 11:04:33 -04:00
Colm O hEigeartaighandAlex Goodman 144ed725a7 Add additional license filenames (#2227)
* Add additional license filenames

Signed-off-by: Colm O hEigeartaigh <coheigea@apache.org>

* add comment about the license list being manually updated

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

---------

Signed-off-by: Colm O hEigeartaigh <coheigea@apache.org>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-16 13:20:00 +00:00
dependabot[bot] dcec2bc352 chore(deps): bump github/codeql-action from 2.22.2 to 2.22.3 (#2229)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.2 to 2.22.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/d90b8d79de6dc1f58e83a1499aa58d6c93dc28de...0116bc2df50751f9724a2e35ef1f24d22f90e4e1)

---
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>
2023-10-16 08:59:39 -04:00
dependabot[bot] 1fe0921a5b chore(deps): bump github.com/charmbracelet/lipgloss from 0.9.0 to 0.9.1 (#2222)
Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.9.0 to 0.9.1.
- [Release notes](https://github.com/charmbracelet/lipgloss/releases)
- [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.9.0...v0.9.1)

---
updated-dependencies:
- dependency-name: github.com/charmbracelet/lipgloss
  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>
2023-10-12 11:10:56 -04:00
dependabot[bot] 538fe5ee1d chore(deps): bump github/codeql-action from 2.22.1 to 2.22.2 (#2224)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.1 to 2.22.2.
- [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/fdcae64e1484d349b3366718cdfef3d404390e85...d90b8d79de6dc1f58e83a1499aa58d6c93dc28de)

---
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>
2023-10-12 11:10:45 -04:00
Colm O hEigeartaigh 2687100e6a Detect a license file in the root directory or META-INF of a jar (#2213)
Signed-off-by: Colm O hEigeartaigh <coheigea@apache.org>
2023-10-12 11:09:53 -04:00
Benji VisserandAlex Goodman fe7a417fb2 Parse donet dependency trees (#2143)
* add dependency information for .NET pkgs

Signed-off-by: Benji Visser <benji@093b.org>

* update pkg coverage directory test

Signed-off-by: Benji Visser <benji@093b.org>

* reverse dependsOn relationship

Signed-off-by: Benji Visser <benji@093b.org>

* update root pkg parsing

Signed-off-by: Benji Visser <benji@093b.org>

* add comments about the test relationships represented

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

* add docs around relationship sorting functions + update test helpers

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

---------

Signed-off-by: Benji Visser <benji@093b.org>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-11 18:01:24 +00:00
dependabot[bot] 7732cd3b48 chore(deps): bump golang.org/x/net from 0.16.0 to 0.17.0 (#2214)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.16.0...v0.17.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>
2023-10-11 13:52:07 -04:00
dependabot[bot] 0302fc5b48 chore(deps): bump github.com/google/go-cmp from 0.5.9 to 0.6.0 (#2215)
Bumps [github.com/google/go-cmp](https://github.com/google/go-cmp) from 0.5.9 to 0.6.0.
- [Release notes](https://github.com/google/go-cmp/releases)
- [Commits](https://github.com/google/go-cmp/compare/v0.5.9...v0.6.0)

---
updated-dependencies:
- dependency-name: github.com/google/go-cmp
  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>
2023-10-11 09:53:00 -04:00
dependabot[bot] b899536814 chore(deps): bump github.com/charmbracelet/lipgloss from 0.8.0 to 0.9.0 (#2216)
Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.8.0 to 0.9.0.
- [Release notes](https://github.com/charmbracelet/lipgloss/releases)
- [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.8.0...v0.9.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>
2023-10-11 09:52:42 -04:00
Christopher Angelo PhillipsandAlex Goodman d1120ad56e chore: add automated homebrew action (#2164)
* chore: add automated homebrew action

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

* migrate homebrew publish step to separate post-release workflow

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

---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-11 09:52:22 -04:00
Alex Goodman ef759038f5 Add relationships for dpkg packages (#2212)
* add relationships for deb packages

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

* update snapshots

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

* bump json schema

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

* small refactor to remove duplicate code

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-11 08:56:26 -04:00
0748945c83 Parse the Maven license from the pom.xml if not contained in the mani… (#2115)
* Parse the Maven license from the pom.xml if not contained in the manifest

Signed-off-by: Colm O hEigeartaigh <coheigea@apache.org>

* chore: restore 10.0.2 schema

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

* chore: generate new 11.0.1 schema

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

* refactor: remove schema change

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

* test: update unit tests to align with new pattern

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

* chore: pr feedback

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

* chore: remove struct tags

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

* keep license name and url semantics preserved on the pkg object

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

---------

Signed-off-by: Colm O hEigeartaigh <coheigea@apache.org>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-10 13:09:44 -04:00
Alex Goodman 185d0d1bfa Refine the docs for building a cataloger (#2175)
* refine the docs for building a cataloger

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

* incorporate comments

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-10-09 13:44:38 -04:00
Mohammad Sharief Baig d16ecdf715 Fix algo lookup by converting key to lower case (#2207)
Signed-off-by: Mohammad Sharief Baig <shariefmohammad007@gmail.com>
2023-10-09 13:07:18 -04:00
dependabot[bot] 68cf57ed03 chore(deps): bump github/codeql-action from 2.22.0 to 2.22.1 (#2208)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.0 to 2.22.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/2cb752a87e96af96708ab57187ab6372ee1973ab...fdcae64e1484d349b3366718cdfef3d404390e85)

---
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>
2023-10-09 13:05:57 -04:00
Christopher Angelo Phillips f6c8057977 feat: add package for go compiler given binary detection (#2195)
adds a unique synthetic package to the SBOM output that represents the go compiler when it is detected as a part of a package discovered by the go binary cataloger.

When using an SBOM generated by syft - downstream vulnerability scanners now have the opportunity to detect/report on the PURL/CPEs attached to the new stdlib package.
---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-10-06 13:15:50 -04:00
dependabot[bot]andChristopher Phillips 87e57aa925 chore(deps): bump github.com/docker/distribution from 2.8.2+incompatible to 2.8.3+incompatible (#2193)
* chore(deps): bump github.com/docker/distribution

Bumps [github.com/docker/distribution](https://github.com/docker/distribution) from 2.8.2+incompatible to 2.8.3+incompatible.
- [Release notes](https://github.com/docker/distribution/releases)
- [Commits](https://github.com/docker/distribution/compare/v2.8.2...v2.8.3)

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

Signed-off-by: dependabot[bot] <support@github.com>

* chore: update reference import

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-10-06 12:54:19 -04:00
dependabot[bot] eed35ec9ce chore(deps): bump github/codeql-action from 2.21.9 to 2.22.0 (#2202)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.9 to 2.22.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/ddccb873888234080b77e9bc2d4764d5ccaaccf9...2cb752a87e96af96708ab57187ab6372ee1973ab)

---
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>
2023-10-06 12:02:34 -04:00
dependabot[bot] b23879fd37 chore(deps): bump golang.org/x/net from 0.15.0 to 0.16.0 (#2204)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/net/compare/v0.15.0...v0.16.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>
2023-10-06 12:01:38 -04:00
Christopher Angelo Phillips 30f0686353 chore: update license list to 3.22 (#2201) 2023-10-06 10:56:47 -04:00
Marc-Etienne Vargenau 235ad2e749 Add exact syntax of the conversion formats (#2196)
Signed-off-by: Marc-Etienne Vargenau <marc-etienne.vargenau@nokia.com>
2023-10-05 14:48:30 -04:00
dependabot[bot] 127fac8ca9 chore(deps): bump github.com/saferwall/pe from 1.4.6 to 1.4.7 (#2198)
Bumps [github.com/saferwall/pe](https://github.com/saferwall/pe) from 1.4.6 to 1.4.7.
- [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.6...v1.4.7)

---
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>
2023-10-05 13:02:30 -04:00
dependabot[bot] 37bb95f5c9 chore(deps): bump golang.org/x/mod from 0.12.0 to 0.13.0 (#2199)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.12.0 to 0.13.0.
- [Commits](https://github.com/golang/mod/compare/v0.12.0...v0.13.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>
2023-10-05 11:50:05 -04:00
chavacava 1067dc2ce9 chore: removes unnecessary conditional (#2194)
Signed-off-by: chavacava <salvadorcavadini+github@gmail.com>
2023-10-04 18:06:12 +00:00
Mohammad Sharief Baig 21878784a8 chore: improve --output help text and deprecate --file (#2187)
Signed-off-by: Mohammad Sharief Baig <shariefmohammad007@gmail.com>
2023-10-03 11:13:07 -04:00
dependabot[bot] 86005d1593 chore(deps): bump modernc.org/sqlite from 1.25.0 to 1.26.0 (#2189)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.25.0 to 1.26.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.25.0...v1.26.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>
2023-10-02 12:34:59 -04:00
dependabot[bot] 45625dae94 chore(deps): bump github.com/gkampitakis/go-snaps from 0.4.10 to 0.4.11 (#2191)
Bumps [github.com/gkampitakis/go-snaps](https://github.com/gkampitakis/go-snaps) from 0.4.10 to 0.4.11.
- [Release notes](https://github.com/gkampitakis/go-snaps/releases)
- [Commits](https://github.com/gkampitakis/go-snaps/compare/v0.4.10...v0.4.11)

---
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>
2023-10-02 12:33:42 -04:00
dependabot[bot] 38d5ef2c84 chore(deps): bump github/codeql-action from 2.21.8 to 2.21.9 (#2182)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.8 to 2.21.9.
- [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/6a28655e3dcb49cb0840ea372fd6d17733edd8a4...ddccb873888234080b77e9bc2d4764d5ccaaccf9)

---
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>
2023-09-28 10:56:08 -04:00
anchore-actions-token-generator[bot]andspiffcs 44e5480238 chore(deps): update bootstrap tools to latest versions (#2178)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: spiffcs <spiffcs@users.noreply.github.com>
2023-09-27 15:05:15 -04:00
dependabot[bot] 7b1af8721d chore(deps): bump github.com/saferwall/pe from 1.4.5 to 1.4.6 (#2180)
Bumps [github.com/saferwall/pe](https://github.com/saferwall/pe) from 1.4.5 to 1.4.6.
- [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.5...v1.4.6)

---
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>
2023-09-27 15:04:52 -04:00
anchore-actions-token-generator[bot]andspiffcs 8f57d22f63 chore(deps): update bootstrap tools to latest versions (#2171)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: spiffcs <spiffcs@users.noreply.github.com>
2023-09-26 11:14:25 -04:00
dependabot[bot] 351c683cb4 chore(deps): bump actions/checkout from 4.0.0 to 4.1.0 (#2172)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.0.0 to 4.1.0.
- [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/3df4ab11eba7bda6032a0b82a6bb43b11571feac...8ade135a41bc03ea155e62e844d188df1ea18608)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2023-09-26 07:49:13 -04:00
dependabot[bot] 534a5f54b0 chore(deps): bump github.com/spf13/afero from 1.9.5 to 1.10.0 (#2174)
Bumps [github.com/spf13/afero](https://github.com/spf13/afero) from 1.9.5 to 1.10.0.
- [Release notes](https://github.com/spf13/afero/releases)
- [Commits](https://github.com/spf13/afero/compare/v1.9.5...v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/afero
  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>
2023-09-25 15:07:19 -04:00
William Murphy 8a414b5366 chore: bump stereoscope to fix data race in UI code (#2173)
Pulls in a fix in go-progress that prevents a race in the UI code when
scanning large images.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2023-09-25 10:29:56 -04:00
William Murphy e34adea749 fix: deterministic java purls (#2170)
Previously, which PURL was generated depended on the order of key iteration
in maps. Also update an integ test that was apparently only passing because
of the previous issue.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2023-09-25 09:28:18 -04:00
Alex Goodman 8314c0d2cb Correcting behavior based on Syft release v0.91.0 run (#2162)
* dont show the title in the release notes

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

* dont upload assets on the release pipeline

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

* bump action-slack action to v3.15.1

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

* remove custom go mod and build cache

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-09-20 20:18:44 +00:00
Đỗ Trọng HảiandAlex Goodman b7fa75d7f8 chore: switch to stdlib's slices pkg (#2148)
* chore: switch to stdlib's slices pkg

Signed-off-by: hainenber <dotronghai96@gmail.com>

* fix linting

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

---------

Signed-off-by: hainenber <dotronghai96@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-09-20 18:38:37 +00:00
Keith Zantow 7d0d3e1977 fix: prevent errors from clobbering terminal (#2161)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-09-20 14:35:41 -04:00
Alex Goodman 58f8c852df Require ordering of relationships when comparing parser output (#2160)
* require ordering of relationships when comparing parser output

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

* [wip] fix cataloger test

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

* change method of relationship sort to simple string dump

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-09-20 17:39:18 +00:00
William Murphy b8f52d570e chore: stop unit test switch on host arch (#2156)
Now that the test fixture pins to a particular digest, there's no need
for platform specific architecture switches in this test.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2023-09-20 11:45:13 -04:00
dependabot[bot] ba00f3328d chore(deps): bump github.com/github/go-spdx/v2 from 2.1.2 to 2.2.0 (#2158)
Bumps [github.com/github/go-spdx/v2](https://github.com/github/go-spdx) from 2.1.2 to 2.2.0.
- [Release notes](https://github.com/github/go-spdx/releases)
- [Commits](https://github.com/github/go-spdx/compare/v2.1.2...v2.2.0)

---
updated-dependencies:
- dependency-name: github.com/github/go-spdx/v2
  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>
2023-09-20 10:12:33 -04:00
dependabot[bot] 962ff1ec49 chore(deps): bump tibdex/github-app-token from 2.0.0 to 2.1.0 (#2157)
Bumps [tibdex/github-app-token](https://github.com/tibdex/github-app-token) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/tibdex/github-app-token/releases)
- [Commits](https://github.com/tibdex/github-app-token/compare/0914d50df753bbc42180d982a6550f195390069f...3beb63f4bd073e61482598c45c71c1019b59b73a)

---
updated-dependencies:
- dependency-name: tibdex/github-app-token
  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>
2023-09-20 10:12:13 -04:00
Alex Goodman 40899adb87 use annotated tags, update chronicle, fix cache keys (#2154)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-09-20 10:11:44 -04:00
Christopher Angelo Phillips 650f71cbe0 chore: update to latest stereoscope (#2151)
* chore: update to latest stereoscope

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

* chore: go mod tidy

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

---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-09-19 15:22:10 -04:00
dependabot[bot] 30885ed92e chore(deps): bump github/codeql-action from 2.21.7 to 2.21.8 (#2150)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.7 to 2.21.8.
- [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/04daf014b50eaf774287bf3f0f1869d4b4c4b913...6a28655e3dcb49cb0840ea372fd6d17733edd8a4)

---
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>
2023-09-19 14:37:54 -04:00
anchore-actions-token-generator[bot]andkzantow 51243aa65f chore(deps): update stereoscope to 41288870305034fade27388afa7326c44eb8ff17 (#2149)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: kzantow <kzantow@users.noreply.github.com>
2023-09-19 09:07:15 -04:00
23e3de75e3 Add containerd support (#1793)
* [wip] add containerd UI handlers

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* Add containerd support

- Add UI handlers (done by @wagoodman)
- Add containerd types and wrappers (done by @wagoodman)
- Add flag for specifying containerd address

Closes #201

Signed-off-by: Shane Dell <shanedell100@gmail.com>

* Fix lint

Signed-off-by: Shane Dell <shanedell100@gmail.com>

* add containerd ui handler

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

* add containerd scheme to readme

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

* add test for scheme detection

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

---------

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Signed-off-by: Shane Dell <shanedell100@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-09-18 11:33:43 -04:00
Christopher Angelo Phillips 594ba5f295 chore: pin workflow checkout for cpe update-cpe-dictionary-index (#2141)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-09-15 16:00:15 -04:00
Alex Goodman 5d48882a78 Add GitHub actions and shared workflow usage catalogers (#2140)
* add github actions usage cataloger

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

* update integration and cli tests with github actions sample

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

* add support for shared workflows

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

* split github actions usage cataloger

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

* add source explanation for github action types

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

* a github purl does not always mean the package is a github action

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

* keep github action catalogers as dir only catalogers

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

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-09-15 18:51:21 +00:00
Stefan Profanter ec4d595920 feat: add dependency information to conan lockfile parser (#2131)
Signed-off-by: Stefan Profanter <stefan.profanter@agile-robots.com>
2023-09-15 14:31:08 -04:00
Christopher Angelo Phillips 094b41b301 chore: pin and update all workflow dependencies; add permission scopes (#2138)
---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-09-15 14:18:42 -04:00
William Murphy 2eb2d55551 chore: pin all cli test FROM lines to linux/amd64 (#2137)
Many of these images have a slightly different sets of packages when the
arm64 variant is pulled, so that leaving this digest unpinned causes the
tests to fail on arm64 hosts. Pin the FROM lines to force stable
platform values regardless of host architecture.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2023-09-15 12:49:02 -04:00
Keith Zantow a46d12270f fix: encode and decode FileLicenses and FileContents in Syft JSON (#2083)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-09-13 16:14:20 -04:00
Christopher Angelo Phillips 3e16c6813f feat: add cyclonedx schema version selection (#2123)
---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-09-13 14:50:22 -04:00
Ahmet Taha 5035d9ca1a fix: allow cyclonedx json input with no components (#2127)
Signed-off-by: Ahmet Taha Özdemir <me@ahoz.de>
2023-09-13 13:14:14 -04:00
dependabot[bot] c21b16d924 chore(deps): bump docker/login-action from 2 to 3 (#2119)
Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  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>
2023-09-13 10:34:19 -04:00
dependabot[bot] 4a2fc226dd chore(deps): bump github.com/go-git/go-git/v5 from 5.8.1 to 5.9.0 (#2125)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.8.1 to 5.9.0.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.8.1...v5.9.0)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  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>
2023-09-13 10:33:47 -04:00
Alex Goodman 7de5643227 fix source-version typo in flag description (#2126)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2023-09-13 10:05:24 -04:00
William Murphy 9de4129638 chore: enforce race detector (#2122)
Previously, there were some data races in syft. Right now, none are
detected, so check for data races on the overall command, and on unit
tests. (Checking for races on integration tests triples the time needed
for those tests, from ~1 minute to ~3 minutes on my workstation, so that
was not done at this time.)

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2023-09-12 13:09:18 -04:00
anchore-actions-token-generator[bot]andkzantow 3a45653cfa chore(deps): update stereoscope to 2fc2d6c2503b6e2212e04c64ceffd57c3395ae70 (#2117)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: kzantow <kzantow@users.noreply.github.com>
2023-09-12 11:49:20 -04:00
195 changed files with 12582 additions and 1012 deletions
+1
View File
@@ -1 +1,2 @@
enforce-v0: true # don't make breaking-change label bump major version before 1.0.
title: ""
+5 -32
View File
@@ -1,14 +1,11 @@
name: "Bootstrap"
description: "Bootstrap all tools and dependencies"
inputs:
go-version:
description: "Go version to install"
required: true
default: "1.21.x"
use-go-cache:
description: "Restore go cache"
required: true
default: "true"
cache-key-prefix:
description: "Prefix all cache keys with this value"
required: true
@@ -24,49 +21,25 @@ inputs:
runs:
using: "composite"
steps:
- uses: actions/setup-go@v4
# note: go mod and build is automatically cached on default with v4+
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
with:
go-version: ${{ inputs.go-version }}
- name: Restore tool cache
id: tool-cache
uses: actions/cache@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: ${{ github.workspace }}/.tmp
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
# note: we need to keep restoring the go mod cache before bootstrapping tools since `go install` is used in
# some installations of project tools.
- name: Restore go module cache
id: go-mod-cache
if: inputs.use-go-cache == 'true'
uses: actions/cache@v3
with:
path: |
~/go/pkg/mod
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ inputs.cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-
- name: (cache-miss) Bootstrap project tools
shell: bash
if: steps.tool-cache.outputs.cache-hit != 'true'
run: make bootstrap-tools
- name: Restore go build cache
id: go-cache
if: inputs.use-go-cache == 'true'
uses: actions/cache@v3
with:
path: |
~/.cache/go-build
key: ${{ inputs.cache-key-prefix }}-${{ inputs.build-cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ inputs.cache-key-prefix }}-${{ inputs.build-cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-
- name: (cache-miss) Bootstrap go dependencies
- name: Bootstrap go dependencies
shell: bash
if: steps.go-mod-cache.outputs.cache-hit != 'true' && inputs.use-go-cache == 'true'
run: make bootstrap-go
- name: Install apt packages
+7 -5
View File
@@ -1,10 +1,12 @@
version: 2
updates:
- package-ecosystem: gomod
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: daily
interval: "daily"
open-pull-requests-limit: 10
+224
View File
@@ -0,0 +1,224 @@
from __future__ import annotations
import sys
import glob
import subprocess
import os
import re
DRY_RUN = False
def main(changed_files: str | None = None, merge_base_schema_files: str | None = None):
global DRY_RUN
pr_number = os.environ.get("GITHUB_PR_NUMBER")
comment_file_path = os.environ.get("CI_COMMENT_FILE")
if not comment_file_path:
print("CI_COMMENT_FILE not set")
sys.exit(1)
if not pr_number:
DRY_RUN = True
if changed_files:
DRY_RUN = True
# read lines from file... this is useful for local testing
with open(changed_files) as f:
pr_changed_files = f.read().splitlines()
with open(merge_base_schema_files) as f:
og_json_schema_files = sort_json_schema_files(f.read().splitlines())
else:
if not is_ci():
print("Not in CI")
sys.exit(1)
if not pr_number:
print("Not a PR")
sys.exit(1)
pr_changed_files = get_pr_changed_files(pr_number)
# since we are running this in the context of the pull_request_target, the checkout is the merge base..
# that is the main branch of the original repo, NOT the branch in the forked repo (or branch in the target
# repo for non-forked PRs). This means we just need to list the current checkedout files to get a sense of
# the changes before a merge.
og_json_schema_files = list_json_schema_files()
pr_json_schema_files = filter_to_schema_files(pr_changed_files)
# print("schema files in pr: ", summarize_schema_files(pr_json_schema_files))
# print("og schema files: ", summarize_schema_files(og_json_schema_files))
if not og_json_schema_files:
print("No schema files found in merge base")
sys.exit(1)
# pr_json_schema_files = set of PR files are added, removed, and changed files
new_schema_files = set(pr_json_schema_files) - set(og_json_schema_files)
removed_or_modified_schema_files = set(pr_json_schema_files) - set(new_schema_files)
print("new schemas: ", summarize_schema_files(new_schema_files))
print("removed or modified schemas:", summarize_schema_files(removed_or_modified_schema_files))
# if there is a new or modified schema, we should add the "json-schema" label to the PR...
if new_schema_files or removed_or_modified_schema_files:
print("\nAdding json-schema label...")
add_label(pr_number, "json-schema")
else:
remove_label(pr_number, "json-schema")
# new schema files should be scrutinized, comparing the latest and added versions to see if it's a breaking
# change (major version bump). Warn about it on the PR via adding a breaking-change label...
if is_breaking_change(new_schema_files, og_json_schema_files[-1]):
print("\nBreaking change detected...")
add_label(pr_number, "breaking-change")
else:
remove_label(pr_number, "breaking-change")
# modifying an existing schema could be a breaking change, we should warn about it on the PR via a comment...
# removing schema files should never be allowed, we should warn about it on the PR via a comment...
if removed_or_modified_schema_files:
print("\nRemoved or modified schema detected...")
schemas = sort_json_schema_files(list(removed_or_modified_schema_files))
schemas_str = "\n".join([f" - {schema}" for schema in schemas])
add_comment(comment_file_path, f"Detected modification or removal of existing json schemas:\n{schemas_str}", warning=True)
def add_comment(comment_file_path: str, comment: str, warning: bool = False, important: bool = False):
if warning or important:
comment_lines = comment.splitlines()
comment = "\n".join([f"> {line}" for line in comment_lines])
if warning:
comment = f"> [!WARNING]\n{comment}"
elif important:
comment = f"> [!IMPORTANT]\n{comment}"
# create any parent directories if they don't exist
os.makedirs(os.path.dirname(comment_file_path), exist_ok=True)
with open(comment_file_path, "w") as f:
f.write(comment)
print(f"Comment file contents: {comment_file_path}")
print(comment)
def add_label(pr_number: str, label: str):
# run "gh pr edit --add-label <label>"
result = run(f"gh pr edit {pr_number} --add-label {label}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode != 0:
print(f"Unable to add {label!r} label to PR with")
print(str(result.stderr))
sys.exit(1)
def remove_label(pr_number: str, label: str):
# run "gh pr edit --remove-label <label>"
result = run(f"gh pr edit {pr_number} --remove-label {label}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode != 0:
print(f"Unable to label PR with {label!r}")
print(str(result.stderr))
sys.exit(1)
def major_version(semver: str) -> int:
return int(semver.split(".")[0])
def is_breaking_change(new_schema_files: set[str], latest_schema_file: str) -> bool:
latest_major_version = major_version(get_semver(latest_schema_file))
for file in new_schema_files:
change_major_version = major_version(get_semver(file))
if change_major_version > latest_major_version:
return True
return False
def summarize_schema_files(files: list[str]) -> list[str]:
return [get_semver(file) for file in files]
def is_ci() -> bool:
return "CI" in os.environ
def get_pr_changed_files(pr_number: str) -> list[str]:
result = run(f"gh pr view {pr_number} --json files --jq '.files.[].path'", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if result.returncode != 0:
print("Unable to get list of changed files in PR")
print(str(result.stderr))
sys.exit(1)
list_of_files = result.stdout.splitlines()
return list_of_files
def filter_to_schema_files(list_of_files: list[str]) -> list[str]:
# get files matching "schema/json/schema-*.json"
files = []
for file in list_of_files:
if re.match(r"^schema/json/schema-\d+\.\d+\.\d+\.json$", file):
files.append(file)
return sort_json_schema_files(files)
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")))
def run(command: str, **kwargs) -> subprocess.CompletedProcess:
if DRY_RUN:
print(f"[DRY RUN] {command}")
return subprocess.CompletedProcess(args=[command], returncode=0)
print(f"[RUN] {command}")
return subprocess.run(command, **kwargs)
def get_semver(input_file: str) -> str:
return input_file.split("-")[1].split(".json")[0]
def sort_json_schema_files(files: list[str]) -> list[str]:
# sort files by schema version, where the input looks like "schema/json/schema-1.12.1.json"
# we should sort by the semantic version embedded within the basename, not the string
# 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('.')])
return [f"schema/json/schema-{version}.json" for version in versions]
# allow for test files that have line-by-line list of files:
# .binny.yaml
# .github/actions/bootstrap/action.yaml
# .github/scripts/goreleaser-install.sh
# .github/workflows/release.yaml
# .github/workflows/update-bootstrap-tools.yml
# .github/workflows/update-cpe-dictionary-index.yml
# .github/workflows/update-stereoscope-release.yml
# .github/workflows/validations.yaml
# .gitignore
# .goreleaser.yaml
# Makefile
# Taskfile.yaml
# schema/cyclonedx/Makefile
if __name__ == "__main__":
# these are variables for a single file name that contains a list of files (line separated)
changed_files = None
merge_base_schema_files = None
if len(sys.argv) > 2:
changed_files = sys.argv[1]
merge_base_schema_files = sys.argv[2]
main(changed_files, merge_base_schema_files)
+65
View File
@@ -0,0 +1,65 @@
import unittest
from unittest.mock import patch
import subprocess
import labeler
class Labeler(unittest.TestCase):
def test_major_version(self):
self.assertEqual(labeler.major_version("1.2.3"), 1)
self.assertEqual(labeler.major_version("2.0.0"), 2)
def test_is_breaking_change(self):
new_schema_files = ["schema/json/schema-2.0.0.json"]
latest_schema_file = "schema/json/schema-1.2.0.json"
self.assertTrue(labeler.is_breaking_change(new_schema_files, latest_schema_file))
new_schema_files = ["schema/json/schema-1.3.0.json"]
latest_schema_file = "schema/json/schema-1.2.0.json"
self.assertFalse(labeler.is_breaking_change(new_schema_files, latest_schema_file))
def test_summarize_schema_files(self):
files = ["schema/json/schema-1.0.0.json", "schema/json/schema-2.0.0.json"]
expected = ["1.0.0", "2.0.0"]
self.assertEqual(labeler.summarize_schema_files(files), expected)
def test_is_ci(self):
# Mock os.environ to simulate CI environment
with patch.dict("os.environ", {"CI": "true"}):
self.assertTrue(labeler.is_ci())
def test_get_pr_changed_files(self):
expected_command = "gh pr view 123 --json files --jq '.files.[].path'"
expected_output = "file1.json\nfile2.json\n"
subprocess.CompletedProcess.returncode = 0
subprocess.CompletedProcess.stdout = expected_output
with patch("labeler.run", return_value=subprocess.CompletedProcess) as mock_run:
result = labeler.get_pr_changed_files("123")
mock_run.assert_called_with(expected_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
self.assertEqual(result, ["file1.json", "file2.json"])
def test_filter_to_schema_files(self):
input_files = ["schema/json/schema-1.0.0.json", "not_schema.txt", "schema/json/schema-2.0.0.json"]
expected_files = ["schema/json/schema-1.0.0.json", "schema/json/schema-2.0.0.json"]
self.assertEqual(labeler.filter_to_schema_files(input_files), expected_files)
# we should be strict about what files are allowed to be processed
input_files = ["schema/json/schema-1.0.0extracontent.json", "schema/json/schema-1.0.0.md", "schema/json/schema-1.0.0.json.extracontent"]
expected_files = []
self.assertEqual(labeler.filter_to_schema_files(input_files), expected_files)
def test_get_semver(self):
input_file = "schema/json/schema-1.0.0.json"
expected_semver = "1.0.0"
self.assertEqual(labeler.get_semver(input_file), expected_semver)
def test_sort_json_schema_files(self):
files = ["schema/json/schema-1.12.1.json", "schema/json/schema-1.2.1.json"]
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)
if __name__ == "__main__":
unittest.main()
+8 -4
View File
@@ -4,6 +4,9 @@ on:
workflow_dispatch:
pull_request:
permissions:
contents: read
jobs:
Benchmark-Test:
@@ -13,13 +16,14 @@ jobs:
# we also want to run on push such that merges to main are recorded to the cache. For this reason we don't filter
# the job by event.
steps:
- uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
- name: Restore base benchmark result
uses: actions/cache@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: test/results/benchmark-main.txt
# use base sha for PR or new commit hash for main push in benchmark result key
@@ -35,13 +39,13 @@ jobs:
OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
echo "result=$OUTPUT" >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: benchmark-test-results
path: test/results/**/*
- name: Update PR benchmark results comment
uses: marocchino/sticky-pull-request-comment@v2
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
continue-on-error: true
with:
header: benchmark
+11 -5
View File
@@ -14,11 +14,17 @@ on:
schedule:
- cron: '0 0 * * 3'
permissions:
contents: read
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
security-events: write
strategy:
fail-fast: false
matrix:
@@ -30,16 +36,16 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Install Go
uses: actions/setup-go@v4
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
with:
go-version-file: go.mod
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 #v2.22.3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -50,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@v2
uses: github/codeql-action/autobuild@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 #v2.22.3
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -64,4 +70,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 #v2.22.3
+54
View File
@@ -0,0 +1,54 @@
name: "Detect schema changes"
on:
# IMPORTANT! This workflow is triggered by the `pull_request_target` event
# which means that forked PRs will run with access secrets from the repo
# it's forked from (the "target" repo).
#
# For this reason we only NEVER checkout the code from the pull request
# (e.g. "ref: ${{ github.event.pull_request.head.sha }}") to prevent
# accidentally running potentially untrusted code.
#
# By default the checkout will be:
# - GITHUB_SHA: Last commit on the PR base branch
# - GITHUB_REF: PR base branch
#
# ...unlike a typical PR where:
# - GITHUB_SHA: Last merge commit on the GITHUB_REF branch
# - GITHUB_REF: PR merge branch refs/pull/:prNumber/merge
pull_request_target:
env:
# note: this is used within hashFiles() so must be within the GITHUB_WORKSPACE path (or will silently fail)
CI_COMMENT_FILE: .tmp/labeler-comment.txt
# needs to be any string to uniquely identify the comment on a PR across multiple runs
COMMENT_HEADER: "label-commentary"
jobs:
label:
name: "Label changes"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- run: python .github/scripts/labeler.py
env:
# note: this token has write access to the repo
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_PR_NUMBER: ${{ github.event.number }}
- name: Delete existing comment
if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }}
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
with:
header: ${{ env.COMMENT_HEADER }}
hide: true
hide_classify: "OUTDATED"
- name: Add comment
if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }}
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
with:
header: ${{ env.COMMENT_HEADER }}
path: ${{ env.CI_COMMENT_FILE }}
+3 -1
View File
@@ -1,5 +1,8 @@
name: Add to OSS board
permissions:
contents: read
on:
issues:
types:
@@ -9,7 +12,6 @@ on:
- labeled
jobs:
run:
uses: "anchore/workflows/.github/workflows/oss-project-board-add.yaml@main"
secrets:
+25
View File
@@ -0,0 +1,25 @@
name: "Release Homebrew"
on:
release:
types: [published]
jobs:
homebrew:
runs-on: ubuntu-20.04
steps:
- name: Update Homebrew formula
uses: dawidd6/action-homebrew-bump-formula@d3667e5ae14df19579e4414897498e3e88f2f458 # v3.10.0
with:
token: ${{ secrets.HOMEBREW_TOKEN }}
org: anchore
formula: syft
- uses: 8398a7/action-slack@fbd6aa58ba854a740e11a35d0df80cb5d12101d8 #v3.15.1
if: ${{ failure() }}
with:
status: ${{ job.status }}
fields: repo,workflow,action,eventName
text: "Post-release homebrew publish workflow has failed: https://github.com/anchore/syft/actions/workflows/release-homebrew.yaml"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
+19 -22
View File
@@ -1,4 +1,8 @@
name: "Release"
permissions:
contents: read
on:
workflow_dispatch:
inputs:
@@ -6,15 +10,12 @@ on:
description: tag the latest commit on main with the given version (prefixed with v)
required: true
env:
GO_VERSION: "1.21.x"
jobs:
quality-gate:
environment: release
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Check if tag already exists
# note: this will fail if the tag already exists
@@ -23,7 +24,7 @@ jobs:
git tag ${{ github.event.inputs.version }}
- name: Check static analysis results
uses: fountainhead/action-wait-for-check@v1.1.0
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
id: static-analysis
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -32,7 +33,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Check unit test results
uses: fountainhead/action-wait-for-check@v1.1.0
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
id: unit
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -41,7 +42,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Check integration test results
uses: fountainhead/action-wait-for-check@v1.1.0
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
id: integration
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -50,7 +51,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Check acceptance test results (linux)
uses: fountainhead/action-wait-for-check@v1.1.0
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
id: acceptance-linux
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -59,7 +60,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Check acceptance test results (mac)
uses: fountainhead/action-wait-for-check@v1.1.0
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
id: acceptance-mac
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -68,7 +69,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Check cli test results (linux)
uses: fountainhead/action-wait-for-check@v1.1.0
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
id: cli-linux
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -94,7 +95,7 @@ jobs:
contents: write
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
with:
fetch-depth: 0
@@ -105,13 +106,13 @@ jobs:
build-cache-key-prefix: "snapshot"
- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d #v3.0.0
with:
username: ${{ secrets.TOOLBOX_DOCKER_USER }}
password: ${{ secrets.TOOLBOX_DOCKER_PASS }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d #v3.0.0
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -119,7 +120,9 @@ jobs:
- name: Tag release
run: |
git tag ${{ github.event.inputs.version }}
git config --global user.name "anchoreci"
git config --global user.email "anchoreci@users.noreply.github.com"
git tag -a ${{ github.event.inputs.version }} -m "Release ${{ github.event.inputs.version }}"
git push origin --tags
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -141,12 +144,12 @@ 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@v0
- uses: anchore/sbom-action@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 #v0.14.3
continue-on-error: true
with:
artifact-name: sbom.spdx.json
- uses: 8398a7/action-slack@v3
- uses: 8398a7/action-slack@fbd6aa58ba854a740e11a35d0df80cb5d12101d8 #v3.15.1
continue-on-error: true
with:
status: ${{ job.status }}
@@ -155,9 +158,3 @@ jobs:
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
if: ${{ success() }}
- uses: actions/upload-artifact@v3
with:
name: artifacts
path: dist/**/*
+7 -4
View File
@@ -9,14 +9,17 @@ env:
GO_VERSION: "1.21.x"
GO_STABLE_VERSION: true
permissions:
contents: read
jobs:
update-bootstrap-tools:
runs-on: ubuntu-latest
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/setup-go@v4
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
with:
go-version: ${{ env.GO_VERSION }}
stable: ${{ env.GO_STABLE_VERSION }}
@@ -55,13 +58,13 @@ jobs:
echo "GLOW=GLOW_LATEST_VERSION" >> $GITHUB_OUTPUT
id: latest-versions
- uses: tibdex/github-app-token@v2
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
id: generate-token
with:
app_id: ${{ secrets.TOKEN_APP_ID }}
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@v5
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
with:
signoff: true
delete-branch: true
@@ -5,6 +5,9 @@ on:
workflow_dispatch:
permissions:
contents: read
env:
GO_VERSION: "1.21.x"
GO_STABLE_VERSION: true
@@ -14,9 +17,9 @@ jobs:
runs-on: ubuntu-latest
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/setup-go@v4
- uses: actions/setup-go@3df4ab11eba7bda6032a0b82a6bb43b11571feac #v4.0.0
with:
go-version: ${{ env.GO_VERSION }}
stable: ${{ env.GO_STABLE_VERSION }}
@@ -24,13 +27,13 @@ jobs:
- run: |
make generate-cpe-dictionary-index
- uses: tibdex/github-app-token@v2
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
id: generate-token
with:
app_id: ${{ secrets.TOKEN_APP_ID }}
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@v5
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
with:
signoff: true
delete-branch: true
@@ -9,14 +9,17 @@ env:
GO_VERSION: "1.21.x"
GO_STABLE_VERSION: true
permissions:
contents: read
jobs:
upgrade-stereoscope:
runs-on: ubuntu-latest
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- uses: actions/setup-go@v4
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
with:
go-version: ${{ env.GO_VERSION }}
stable: ${{ env.GO_STABLE_VERSION }}
@@ -32,13 +35,13 @@ jobs:
echo "LATEST_VERSION=$LATEST_VERSION" >> $GITHUB_OUTPUT
id: latest-version
- uses: tibdex/github-app-token@v2
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
id: generate-token
with:
app_id: ${{ secrets.TOKEN_APP_ID }}
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@v5
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
with:
signoff: true
delete-branch: true
+23 -21
View File
@@ -7,14 +7,16 @@ on:
branches:
- main
jobs:
permissions:
contents: read
jobs:
Static-Analysis:
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
name: "Static analysis"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -28,37 +30,37 @@ jobs:
name: "Unit tests"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
- name: Restore Java test-fixture cache
uses: actions/cache@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
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@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: syft/pkg/cataloger/rpm/test-fixtures/rpms
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/rpm/test-fixtures/rpms.fingerprint' ) }}
- name: Restore go binary test-fixture cache
uses: actions/cache@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
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@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: syft/pkg/cataloger/binary/test-fixtures/classifiers/dynamic
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@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: syft/pkg/cataloger/kernel/test-fixtures/cache
key: ${{ runner.os }}-unit-kernel-cache-${{ hashFiles( 'syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint' ) }}
@@ -72,7 +74,7 @@ jobs:
name: "Integration tests"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -81,7 +83,7 @@ jobs:
run: make validate-cyclonedx-schema
- name: Restore integration test cache
uses: actions/cache@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: ${{ github.workspace }}/test/integration/test-fixtures/cache
key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('test/integration/test-fixtures/cache.fingerprint') }}
@@ -94,7 +96,7 @@ jobs:
name: "Build snapshot artifacts"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
@@ -113,7 +115,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@v3
uses: actions/cache/save@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: snapshot
key: snapshot-build-${{ github.run_id }}
@@ -125,10 +127,10 @@ jobs:
needs: [Build-Snapshot-Artifacts]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Download snapshot build
uses: actions/cache/restore@v3
uses: actions/cache/restore@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: snapshot
key: snapshot-build-${{ github.run_id }}
@@ -138,7 +140,7 @@ jobs:
- name: Restore install.sh test image cache
id: install-test-image-cache
uses: actions/cache@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: ${{ github.workspace }}/test/install/cache
key: ${{ runner.os }}-install-test-image-cache-${{ hashFiles('test/install/cache.fingerprint') }}
@@ -161,17 +163,17 @@ jobs:
needs: [Build-Snapshot-Artifacts]
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Download snapshot build
uses: actions/cache/restore@v3
uses: actions/cache/restore@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: snapshot
key: snapshot-build-${{ github.run_id }}
- name: Restore docker image cache for compare testing
id: mac-compare-testing-cache
uses: actions/cache@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: image.tar
key: ${{ runner.os }}-${{ hashFiles('test/compare/mac.sh') }}
@@ -189,19 +191,19 @@ jobs:
needs: [Build-Snapshot-Artifacts]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
- name: Restore CLI test-fixture cache
uses: actions/cache@v3
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
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
uses: actions/cache/restore@v3
uses: actions/cache/restore@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with:
path: snapshot
key: snapshot-build-${{ github.run_id }}
+6
View File
@@ -30,6 +30,7 @@ VERSION
/test/results
coverage.txt
*.log
test/integration/test-fixtures/**/go.sum
# probable archives
.images
@@ -63,3 +64,8 @@ coverage.txt
# attestation
cosign.key
cosign.pub
# Byte-compiled object files for python
__pycache__/
*.py[cod]
*$py.class
+28 -36
View File
@@ -6,6 +6,7 @@ In order to test and develop in this repo you will need the following dependenci
- Golang
- docker
- make
- Python (>= 3.9)
### Docker settings for getting started
Make sure you've updated your docker settings so the default docker socket path is available.
@@ -153,56 +154,47 @@ sequenceDiagram
### Syft Catalogers
##### Summary
Catalogers are the way in which syft is able to identify and construct packages given some amount of source metadata.
For example, Syft can locate and process `package-lock.json` files when performing filesystem scans.
See: [how to specify file globs](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/javascript/cataloger.go#L16-L21)
and an implementation of the [package-lock.json parser](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/javascript/cataloger.go#L16-L21) for a quick review.
Catalogers are the way in which syft is able to identify and construct packages given a set a targeted list of files.
For example, a cataloger can ask syft for all `package-lock.json` files in order to parse and raise up javascript packages
(see [how file globs](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/javascript/cataloger.go#L16-L21) and
[file parser functions](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/javascript/cataloger.go#L16-L21) are used
for a quick example).
From a high level catalogers have the following properties:
- They are independent from one another. The java cataloger has no idea of the processes, assumptions, or results of the python cataloger, for example.
- _They are independent from one another_. The java cataloger has no idea of the processes, assumptions, or results of the python cataloger, for example.
- They do not know what source is being analyzed. Are we analyzing a local directory? an image? if so, the squashed representation or all layers? The catalogers do not know the answers to these questions. Only that there is an interface to query for file paths and contents from an underlying "source" being scanned.
- _They do not know what source is being analyzed_. Are we analyzing a local directory? an image? if so, the squashed representation or all layers? The catalogers do not know the answers to these questions. Only that there is an interface to query for file paths and contents from an underlying "source" being scanned.
- _Packages created by the cataloger should not be mutated after they are created_. There is one exception made for adding CPEs to a package after the cataloging phase, but that will most likely be moved back into the cataloger in the future.
- Packages created by the cataloger should not be mutated after they are created. There is one exception made for adding CPEs to a package after the cataloging phase, but that will most likely be moved back into the cataloger in the future.
#### Building a new Cataloger
Catalogers must fulfill the interface [found here](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger.go).
This means that when building a new cataloger, the new struct must implement both method signatures of `Catalog` and `Name`.
Catalogers must fulfill the [`pkg.Cataloger` interface](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger.go) in order to add packages to the SBOM.
All catalogers should be added to:
- the [global list of catalogers](https://github.com/anchore/syft/blob/9995950c70e849f9921919faffbfcf46401f71f3/syft/pkg/cataloger/cataloger.go#L92-L125)
- at least one source-specific list, today the two lists are [directory catalogers and image catalogers](https://github.com/anchore/syft/blob/9995950c70e849f9921919faffbfcf46401f71f3/syft/pkg/cataloger/cataloger.go#L39-L89)
A top level view of the functions that construct all the catalogers can be found [here](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/cataloger.go).
When an author has finished writing a new cataloger this is the spot to plug in the new catalog constructor.
For reference, catalogers are [invoked within syft](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/catalog.go#L41-L100) one after the other, and can be invoked in parallel.
For a top level view of how the catalogers are used see [this function](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/catalog.go#L41-L100) as a reference. It ranges over all catalogers passed as an argument and invokes the `Catalog` method:
`generic.NewCataloger` is an abstraction syft used to make writing common components easier (see the [apkdb cataloger](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/cataloger.go) for example usage).
It takes the following information as input:
- A `catalogerName` to identify the cataloger uniquely among all other catalogers.
- Pairs of file globs as well as parser functions to parse those files. These parser functions return a slice of [`pkg.Package`](https://github.com/anchore/syft/blob/9995950c70e849f9921919faffbfcf46401f71f3/syft/pkg/package.go#L19) as well as a slice of [`artifact.Relationship`](https://github.com/anchore/syft/blob/9995950c70e849f9921919faffbfcf46401f71f3/syft/artifact/relationship.go#L31) to describe how the returned packages are related. See this [the apkdb cataloger parser function](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/parse_apk_db.go#L22-L102) as an example.
Each cataloger has its own `Catalog` method, but this does not mean that they are all vastly different.
Take a look at the `apkdb` cataloger for alpine to see how it [constructs a generic.NewCataloger](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/cataloger.go).
`generic.NewCataloger` is an abstraction syft uses to make writing common components easier. First, it takes the `catalogerName` to identify the cataloger.
On the other side of the call it uses two key pieces which inform the cataloger how to identify and return packages, the `globPatterns` and the `parseFunction`:
- The first piece is a `parseByGlob` matching pattern used to identify the files that contain the package metadata.
See [here for the APK example](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/apk_metadata.go#L16-L41).
- The other is a `parseFunction` which informs the cataloger what to do when it has found one of the above matches files.
See this [link for an example](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/parse_apk_db.go#L22-L102).
If you're unsure about using the `Generic Cataloger` and think the use case being filled requires something more custom
just file an issue or ask in our slack, and we'd be more than happy to help on the design.
Identified packages share a common struct so be sure that when the new cataloger is constructing a new package it is using the [`Package` struct](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/package.go#L16-L31).
Metadata Note: Identified packages are also assigned specific metadata that can be unique to their environment.
See [this folder](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg) for examples of the different metadata types.
Identified packages share a common `pkg.Package` struct so be sure that when the new cataloger is constructing a new package it is using the [`Package` struct](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/package.go#L16-L31).
If you want to return more information than what is available on the `pkg.Package` struct then you can do so in the `pkg.Package.Metadata` section of the struct, which is unique for each [`pkg.Type`](https://github.com/anchore/syft/blob/v0.70.0/syft/pkg/type.go).
See [the `pkg` package](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg) for examples of the different metadata types that are supported today.
These are plugged into the `MetadataType` and `Metadata` fields in the above struct. `MetadataType` informs which type is being used. `Metadata` is an interface converted to that type.
Finally, here is an example of where the package construction is done in the apk cataloger. The first link is where `newPackage` is called in the `parseFunction`. The second link shows the package construction:
- [Call for new package](https://github.com/anchore/syft/blob/v0.70.0/syft/pkg/cataloger/apkdb/parse_apk_db.go#L106)
- [APK Package Constructor](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/package.go#L12-L27)
Finally, here is an example of where the package construction is done within the apk cataloger:
- [Calling the APK package constructor from the parser function](https://github.com/anchore/syft/blob/v0.70.0/syft/pkg/cataloger/apkdb/parse_apk_db.go#L106)
- [The APK package constructor itself](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/package.go#L12-L27)
Interested in building a new cataloger? Checkout the [list of issues with the `new-cataloger` label](https://github.com/anchore/syft/issues?q=is%3Aopen+is%3Aissue+label%3Anew-cataloger+no%3Aassignee)!
If you have questions about implementing a cataloger feel free to file an issue or reach out to us [on slack](https://anchore.com/slack)!
If you have more questions about implementing a cataloger or questions about one you might be currently working
always feel free to file an issue or reach out to us [on slack](https://anchore.com/slack).
#### Searching for files
+1 -1
View File
@@ -1,4 +1,4 @@
FROM gcr.io/distroless/static-debian11:debug AS build
FROM gcr.io/distroless/static-debian11:debug@sha256:a0a404776dec98be120089ae42bbdfbe48c177921d856937d124d48eb8c0b951 AS build
FROM scratch
# needed for version check HTTPS request
+1 -1
View File
@@ -1,4 +1,4 @@
FROM gcr.io/distroless/static-debian11:debug
FROM gcr.io/distroless/static-debian11:debug@sha256:a0a404776dec98be120089ae42bbdfbe48c177921d856937d124d48eb8c0b951
# create the /tmp dir, which is needed for image content cache
WORKDIR /tmp
+9 -4
View File
@@ -13,8 +13,8 @@ GLOW_CMD = $(TEMP_DIR)/glow
GOLANGCILINT_VERSION := v1.54.2
GOSIMPORTS_VERSION := v0.3.8
BOUNCER_VERSION := v0.4.0
CHRONICLE_VERSION := v0.7.0
GORELEASER_VERSION := v1.20.0
CHRONICLE_VERSION := v0.8.0
GORELEASER_VERSION := v1.21.2
YAJSV_VERSION := v1.4.1
COSIGN_VERSION := v2.2.0
QUILL_VERSION := v0.4.1
@@ -70,7 +70,7 @@ all: static-analysis test ## Run all linux-based checks (linting, license check,
static-analysis: check-go-mod-tidy lint check-licenses check-json-schema-drift ## Run all static analysis checks
.PHONY: test
test: unit integration validate-cyclonedx-schema benchmark cli ## Run all tests (currently unit, integration, linux compare, and cli tests)
test: unit integration validate-cyclonedx-schema benchmark test-utils cli ## Run all tests (currently unit, integration, linux compare, and cli tests)
## Bootstrapping targets #################################
@@ -147,13 +147,14 @@ check-json-schema-drift:
.PHONY: unit
unit: $(TEMP_DIR) fixtures ## Run unit tests (with coverage)
$(call title,Running unit tests)
go test -coverprofile $(TEMP_DIR)/unit-coverage-details.txt $(shell go list ./... | grep -v anchore/syft/test)
go test -race -coverprofile $(TEMP_DIR)/unit-coverage-details.txt $(shell go list ./... | grep -v anchore/syft/test)
@.github/scripts/coverage.py $(COVERAGE_THRESHOLD) $(TEMP_DIR)/unit-coverage-details.txt
.PHONY: integration
integration: ## Run integration tests
$(call title,Running integration tests)
go test -v ./test/integration
go run -race cmd/syft/main.go alpine:latest
.PHONY: validate-cyclonedx-schema
validate-cyclonedx-schema:
@@ -166,6 +167,10 @@ cli: $(SNAPSHOT_DIR) ## Run CLI tests
SYFT_BINARY_LOCATION='$(SNAPSHOT_BIN)' \
go test -count=1 -timeout=15m -v ./test/cli
.PHONY: test-utils
test-utils:
python .github/scripts/labeler_test.py
## Benchmark test targets #################################
+7 -6
View File
@@ -139,6 +139,7 @@ Sources can be explicitly provided with a scheme:
```
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)
@@ -389,11 +390,11 @@ syft convert <ORIGINAL-SBOM-FILE> -o <NEW-SBOM-FORMAT>[=<NEW-SBOM-FILE>]
This feature is experimental and data might be lost when converting formats. Packages are the main SBOM component easily transferable across formats, whereas files and relationships, as well as other information Syft doesn't support, are more likely to be lost.
We support formats with wide community usage AND good encode/decode support by Syft. The supported formats are:
- Syft JSON
- SPDX 2.2 JSON
- SPDX 2.2 tag-value
- CycloneDX 1.4 JSON
- CycloneDX 1.4 XML
- Syft JSON (```-o syft-json```)
- SPDX 2.2 JSON (```-o spdx-json```)
- SPDX 2.2 tag-value (```-o spdx-tag-value```)
- CycloneDX 1.4 JSON (```-o cyclonedx-json```)
- CycloneDX 1.4 XML (```-o cyclonedx-xml```)
Conversion example:
```sh
@@ -671,7 +672,7 @@ source:
# the file digest algorithms to use on the scanned file (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")
digests: ["sha256"]
# options when pulling directly from a registry via the "registry:" scheme
# options when pulling directly from a registry via the "registry:" or "containerd:" scheme
registry:
# skip TLS verification when communicating with the registry
# SYFT_REGISTRY_INSECURE_SKIP_TLS_VERIFY env var
+5 -3
View File
@@ -46,10 +46,10 @@ func create(id clio.Identification) (clio.Application, *cobra.Command) {
return []clio.UI{noUI}, nil
}
h := handler.New(handler.DefaultHandlerConfig())
return []clio.UI{
ui.New(h, false, cfg.Log.Quiet),
ui.New(cfg.Log.Quiet,
handler.New(handler.DefaultHandlerConfig()),
),
noUI,
}, nil
},
@@ -60,7 +60,9 @@ func create(id clio.Identification) (clio.Application, *cobra.Command) {
// 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)
+4 -4
View File
@@ -7,10 +7,10 @@ import (
"github.com/iancoleman/strcase"
"github.com/mitchellh/go-homedir"
"github.com/scylladb/go-set/strset"
"github.com/anchore/clio"
"github.com/anchore/fangs"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/pkg/cataloger"
golangCataloger "github.com/anchore/syft/syft/pkg/cataloger/golang"
@@ -88,7 +88,7 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
"set the name of the target being analyzed")
flags.StringVarP(&cfg.Source.Version, "source-version", "",
"set the name of the target being analyzed")
"set the version of the target being analyzed")
flags.StringVarP(&cfg.BasePath, "base-path", "",
"base directory for scanning, no links will be followed above this directory, and all paths will be reported relative to this directory")
@@ -147,8 +147,8 @@ func (cfg Catalog) ToCatalogerConfig() cataloger.Config {
var validDefaultSourceValues = []string{"registry", "docker", "podman", ""}
func checkDefaultSourceValues(source string) error {
validValues := internal.NewStringSet(validDefaultSourceValues...)
if !validValues.Contains(source) {
validValues := strset.New(validDefaultSourceValues...)
if !validValues.Has(source) {
validValuesString := strings.Join(validDefaultSourceValues, ", ")
return fmt.Errorf("%s is not a valid default source; please use one of the following: %s''", source, validValuesString)
}
+9 -4
View File
@@ -2,10 +2,10 @@ package options
import (
"fmt"
"golang.org/x/exp/slices"
"slices"
"github.com/anchore/clio"
"github.com/anchore/fangs"
"github.com/anchore/syft/syft/formats"
"github.com/anchore/syft/syft/formats/table"
"github.com/anchore/syft/syft/formats/template"
@@ -31,7 +31,7 @@ func DefaultOutput() MultiOutput {
func (o *MultiOutput) AddFlags(flags clio.FlagSet) {
flags.StringArrayVarP(&o.Outputs, "output", "o",
fmt.Sprintf("report output format, options=%v", formats.AllIDs()))
fmt.Sprintf("report output format (<format>=<file> to output to a file), formats=%v", formats.AllIDs()))
flags.StringVarP(&o.OutputTemplatePath, "template", "t",
"specify the path to a Go template file")
@@ -64,7 +64,7 @@ func (o *SingleOutput) SBOMWriter(file string) (sbom.Writer, error) {
return makeSBOMWriter([]string{o.Output}, file, o.OutputTemplatePath)
}
// OutputFile is only the --file argument
// Deprecated: OutputFile is only the --file argument
type OutputFile struct {
File string `yaml:"file" json:"file" mapstructure:"file"` // --file, the file to write report output to
}
@@ -77,6 +77,11 @@ var _ interface {
func (o *OutputFile) AddFlags(flags clio.FlagSet) {
flags.StringVarP(&o.File, "file", "",
"file to write the default report output to (default is STDOUT)")
if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
flagSet := pfp.PFlagSet()
flagSet.Lookup("file").Deprecated = "use: output"
}
}
func (o *OutputFile) PostLoad() error {
+1 -5
View File
@@ -183,11 +183,7 @@ func Test_newSBOMMultiWriter(t *testing.T) {
switch w := mw.writers[i].(type) {
case *sbomStreamWriter:
assert.Equal(t, string(w.format.ID()), e.format)
if e.file != "" {
assert.NotNil(t, w.out)
} else {
assert.NotNil(t, w.out)
}
assert.NotNil(t, w.out)
if e.file != "" {
assert.FileExists(t, tmp+e.file)
}
@@ -0,0 +1,190 @@
package ui
import (
"fmt"
"strings"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/dustin/go-humanize"
"github.com/wagoodman/go-partybus"
"github.com/wagoodman/go-progress"
"github.com/anchore/bubbly/bubbles/taskprogress"
stereoscopeParsers "github.com/anchore/stereoscope/pkg/event/parsers"
"github.com/anchore/stereoscope/pkg/image/containerd"
"github.com/anchore/syft/internal/log"
)
var _ interface {
progress.Stager
progress.Progressable
} = (*containerdPullProgressAdapter)(nil)
type containerdPullStatus interface {
Complete() bool
Layers() []containerd.LayerID
Current(containerd.LayerID) progress.Progressable
}
type containerdPullProgressAdapter struct {
status containerdPullStatus
formatter containerdPullStatusFormatter
}
type containerdPullStatusFormatter struct {
auxInfoStyle lipgloss.Style
pullCompletedStyle lipgloss.Style
pullDownloadStyle lipgloss.Style
pullStageChars []string
layerCaps []string
}
func (m *Handler) handlePullContainerdImage(e partybus.Event) []tea.Model {
_, pullStatus, err := stereoscopeParsers.ParsePullContainerdImage(e)
if err != nil {
log.WithFields("error", err).Warn("unable to parse event")
return nil
}
if pullStatus == nil {
return nil
}
tsk := m.newTaskProgress(
taskprogress.Title{
Default: "Pull image",
Running: "Pulling image",
Success: "Pulled image",
},
taskprogress.WithStagedProgressable(
newContainerdPullProgressAdapter(pullStatus),
),
)
tsk.HintStyle = lipgloss.NewStyle()
tsk.HintEndCaps = nil
return []tea.Model{tsk}
}
func newContainerdPullProgressAdapter(status *containerd.PullStatus) *containerdPullProgressAdapter {
return &containerdPullProgressAdapter{
status: status,
formatter: newContainerdPullStatusFormatter(),
}
}
func newContainerdPullStatusFormatter() containerdPullStatusFormatter {
return containerdPullStatusFormatter{
auxInfoStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("#777777")),
pullCompletedStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("#fcba03")),
pullDownloadStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("#777777")),
pullStageChars: strings.Split("▁▃▄▅▆▇█", ""),
layerCaps: strings.Split("▕▏", ""),
}
}
func (d containerdPullProgressAdapter) Size() int64 {
return -1
}
func (d containerdPullProgressAdapter) Current() int64 {
return 1
}
func (d containerdPullProgressAdapter) Error() error {
if d.status.Complete() {
return progress.ErrCompleted
}
// TODO: return intermediate error indications
return nil
}
func (d containerdPullProgressAdapter) Stage() string {
return d.formatter.Render(d.status)
}
// Render crafts the given docker image pull status summarized into a single line.
func (f containerdPullStatusFormatter) Render(pullStatus containerdPullStatus) string {
var size, current uint64
layers := pullStatus.Layers()
status := make(map[containerd.LayerID]progress.Progressable)
completed := make([]string, len(layers))
// fetch the current state
for idx, layer := range layers {
completed[idx] = " "
status[layer] = pullStatus.Current(layer)
}
numCompleted := 0
for idx, layer := range layers {
prog := status[layer]
curN := prog.Current()
curSize := prog.Size()
if progress.IsCompleted(prog) {
input := f.pullStageChars[len(f.pullStageChars)-1]
completed[idx] = f.formatPullPhase(prog.Error() != nil, input)
} else if curN != 0 {
var ratio float64
switch {
case curN == 0 || curSize < 0:
ratio = 0
case curN >= curSize:
ratio = 1
default:
ratio = float64(curN) / float64(curSize)
}
i := int(ratio * float64(len(f.pullStageChars)-1))
input := f.pullStageChars[i]
completed[idx] = f.formatPullPhase(status[layer].Error() != nil, input)
}
if progress.IsErrCompleted(status[layer].Error()) {
numCompleted++
}
}
for _, layer := range layers {
prog := status[layer]
size += uint64(prog.Size())
current += uint64(prog.Current())
}
var progStr, auxInfo string
if len(layers) > 0 {
render := strings.Join(completed, "")
prefix := f.pullCompletedStyle.Render(fmt.Sprintf("%d Layers", len(layers)))
auxInfo = f.auxInfoStyle.Render(fmt.Sprintf("[%s / %s]", humanize.Bytes(current), humanize.Bytes(size)))
if len(layers) == numCompleted {
auxInfo = f.auxInfoStyle.Render(fmt.Sprintf("[%s] Extracting...", humanize.Bytes(size)))
}
progStr = fmt.Sprintf("%s%s%s%s", prefix, f.layerCap(false), render, f.layerCap(true))
}
return progStr + auxInfo
}
// formatPullPhase returns a single character that represents the status of a layer pull.
func (f containerdPullStatusFormatter) formatPullPhase(completed bool, inputStr string) string {
if completed {
return f.pullCompletedStyle.Render(f.pullStageChars[len(f.pullStageChars)-1])
}
return f.pullDownloadStyle.Render(inputStr)
}
func (f containerdPullStatusFormatter) layerCap(end bool) string {
l := len(f.layerCaps)
if l == 0 {
return ""
}
if end {
return f.layerCaps[l-1]
}
return f.layerCaps[0]
}
+1
View File
@@ -49,6 +49,7 @@ func New(cfg HandlerConfig) *Handler {
// register all supported event types with the respective handler functions
d.AddHandlers(map[partybus.EventType]bubbly.EventHandlerFn{
stereoscopeEvent.PullDockerImage: h.handlePullDockerImage,
stereoscopeEvent.PullContainerdImage: h.handlePullContainerdImage,
stereoscopeEvent.ReadImage: h.handleReadImage,
stereoscopeEvent.FetchImage: h.handleFetchImage,
syftEvent.PackageCatalogerStarted: h.handlePackageCatalogerStarted,
-36
View File
@@ -1,36 +0,0 @@
//go:build linux || darwin || netbsd
// +build linux darwin netbsd
package ui
import (
"os"
"runtime"
"golang.org/x/term"
"github.com/anchore/clio"
handler "github.com/anchore/syft/cmd/syft/cli/ui"
)
// Select is responsible for determining the specific UI function given select user option, the current platform
// config values, and environment status (such as a TTY being present). The first UI in the returned slice of UIs
// is intended to be used and the UIs that follow are meant to be attempted only in a fallback posture when there
// are environmental problems (e.g. cannot write to the terminal). A writer is provided to capture the output of
// the final SBOM report.
func Select(verbose, quiet bool) (uis []clio.UI) {
isStdoutATty := term.IsTerminal(int(os.Stdout.Fd()))
isStderrATty := term.IsTerminal(int(os.Stderr.Fd()))
notATerminal := !isStderrATty && !isStdoutATty
switch {
case runtime.GOOS == "windows" || verbose || quiet || notATerminal || !isStderrATty:
uis = append(uis, None(quiet))
default:
// TODO: it may make sense in the future to pass handler options into select
h := handler.New(handler.DefaultHandlerConfig())
uis = append(uis, New(h, verbose, quiet))
}
return uis
}
-15
View File
@@ -1,15 +0,0 @@
//go:build windows
// +build windows
package ui
import "github.com/anchore/clio"
// Select is responsible for determining the specific UI function given select user option, the current platform
// config values, and environment status (such as a TTY being present). The first UI in the returned slice of UIs
// is intended to be used and the UIs that follow are meant to be attempted only in a fallback posture when there
// are environmental problems (e.g. cannot write to the terminal). A writer is provided to capture the output of
// the final SBOM report.
func Select(verbose, quiet bool) (uis []clio.UI) {
return append(uis, None(quiet))
}
+33 -7
View File
@@ -1,16 +1,18 @@
package ui
import (
"fmt"
"os"
"sync"
"time"
tea "github.com/charmbracelet/bubbletea"
"github.com/wagoodman/go-partybus"
"github.com/anchore/bubbly"
"github.com/anchore/bubbly/bubbles/frame"
"github.com/anchore/clio"
"github.com/anchore/go-logger"
handler "github.com/anchore/syft/cmd/syft/cli/ui"
"github.com/anchore/syft/internal/bus"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/event"
@@ -29,13 +31,13 @@ type UI struct {
subscription partybus.Unsubscribable
finalizeEvents []partybus.Event
handler *handler.Handler
handler *bubbly.HandlerCollection
frame tea.Model
}
func New(h *handler.Handler, _, quiet bool) *UI {
func New(quiet bool, handlers ...bubbly.EventHandler) *UI {
return &UI{
handler: h,
handler: bubbly.NewHandlerCollection(handlers...),
frame: frame.New(),
running: &sync.WaitGroup{},
quiet: quiet,
@@ -72,7 +74,7 @@ func (m *UI) Handle(e partybus.Event) error {
func (m *UI) Teardown(force bool) error {
if !force {
m.handler.Running.Wait()
m.handler.Wait()
m.program.Quit()
// typically in all cases we would want to wait for the UI to finish. However there are still error cases
// that are not accounted for, resulting in hangs. For now, we'll just wait for the UI to finish in the
@@ -80,9 +82,19 @@ func (m *UI) Teardown(force bool) error {
// string from the worker (outside of the UI after teardown).
m.running.Wait()
} else {
_ = runWithTimeout(250*time.Millisecond, func() error {
m.handler.Wait()
return nil
})
// it may be tempting to use Kill() however it has been found that this can cause the terminal to be left in
// a bad state (where Ctrl+C and other control characters no longer works for future processes in that terminal).
m.program.Quit()
_ = runWithTimeout(250*time.Millisecond, func() error {
m.running.Wait()
return nil
})
}
// TODO: allow for writing out the full log output to the screen (only a partial log is shown currently)
@@ -119,7 +131,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
// today we treat esc and ctrl+c the same, but in the future when the syft worker has a graceful way to
// today we treat esc and ctrl+c the same, but in the future when the worker has a graceful way to
// cancel in-flight work via a context, we can wire up esc to this path with bus.Exit()
case "esc", "ctrl+c":
bus.ExitWithInterrupt()
@@ -135,7 +147,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.finalizeEvents = append(m.finalizeEvents, msg)
// why not return tea.Quit here for exit events? because there may be UI components that still need the update-render loop.
// for this reason we'll let the syft event loop call Teardown() which will explicitly wait for these components
// for this reason we'll let the event loop call Teardown() which will explicitly wait for these components
return m, nil
}
@@ -159,3 +171,17 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (m UI) View() string {
return m.frame.View()
}
func runWithTimeout(timeout time.Duration, fn func() error) (err error) {
c := make(chan struct{}, 1)
go func() {
err = fn()
c <- struct{}{}
}()
select {
case <-c:
case <-time.After(timeout):
return fmt.Errorf("timed out after %v", timeout)
}
return err
}
+56 -30
View File
@@ -3,40 +3,38 @@ module github.com/anchore/syft
go 1.21.0
require (
github.com/CycloneDX/cyclonedx-go v0.7.1
github.com/CycloneDX/cyclonedx-go v0.7.2
github.com/Masterminds/semver v1.5.0
github.com/Masterminds/sprig/v3 v3.2.3
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/acobaugh/osrelease v0.1.0
github.com/adrg/xdg v0.4.0 // indirect
github.com/anchore/bubbly v0.0.0-20230801194016-acdb4981b461
github.com/anchore/clio v0.0.0-20230823172630-c42d666061af
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc
github.com/anchore/fangs v0.0.0-20230818131516-2186b10924fe
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.0-20230907152702-057dda3667e7
github.com/anchore/stereoscope v0.0.0-20230925132944-bf05af58eb44
// 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/andybalholm/brotli v1.0.4 // indirect
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
github.com/bmatcuk/doublestar/v4 v4.6.0
github.com/charmbracelet/bubbletea v0.24.2
github.com/charmbracelet/lipgloss v0.8.0
github.com/charmbracelet/lipgloss v0.9.1
github.com/dave/jennifer v1.7.0
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da
github.com/docker/distribution v2.8.2+incompatible
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v24.0.6+incompatible
github.com/dustin/go-humanize v1.0.1
github.com/facebookincubator/nvdtools v0.1.5
github.com/github/go-spdx/v2 v2.1.2
github.com/gkampitakis/go-snaps v0.4.10
github.com/go-git/go-billy/v5 v5.4.1
github.com/go-git/go-git/v5 v5.8.1
github.com/github/go-spdx/v2 v2.2.0
github.com/gkampitakis/go-snaps v0.4.11
github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git/v5 v5.9.0
github.com/go-test/deep v1.1.0
github.com/google/go-cmp v0.5.9
github.com/google/go-cmp v0.6.0
github.com/google/go-containerregistry v0.16.1
github.com/google/licensecheck v0.3.1
github.com/google/uuid v1.3.1
@@ -47,7 +45,6 @@ require (
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/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
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
@@ -56,58 +53,69 @@ require (
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/pkg/errors v0.9.1 // indirect
github.com/saferwall/pe v1.4.5
github.com/saferwall/pe v1.4.7
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
github.com/sassoftware/go-rpmutils v0.2.0
// pinned to pull in 386 arch fix: https://github.com/scylladb/go-set/commit/cc7b2070d91ebf40d233207b633e28f5bd8f03a5
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
github.com/sergi/go-diff v1.3.1
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spdx/tools-golang v0.5.3
github.com/spf13/afero v1.9.5
github.com/spf13/afero v1.10.0
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/stretchr/testify v1.8.4
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
github.com/wagoodman/go-progress v0.0.0-20230301185719-21920a456ad5
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0
github.com/xeipuuv/gojsonschema v1.2.0
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
golang.org/x/mod v0.12.0
golang.org/x/net v0.15.0
golang.org/x/term v0.12.0
golang.org/x/mod v0.13.0
golang.org/x/net v0.17.0
golang.org/x/term v0.13.0 // indirect
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.25.0
modernc.org/sqlite v1.26.0
)
require (
github.com/distribution/reference v0.5.0
github.com/sanity-io/litter v1.5.5
)
require (
dario.cat/mergo v1.0.0 // indirect
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/DataDog/zstd v1.4.5 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
github.com/Microsoft/hcsshim v0.10.0-rc.7 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/adrg/xdg v0.4.0 // indirect
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/becheran/wildmatch-go v1.0.0 // indirect
github.com/charmbracelet/bubbles v0.16.1 // indirect
github.com/charmbracelet/harmonica v0.2.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/containerd/containerd v1.7.0 // indirect
github.com/containerd/continuity v0.3.0 // indirect
github.com/containerd/fifo v1.1.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/containerd/ttrpc v1.2.1 // indirect
github.com/containerd/typeurl/v2 v2.1.0 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v24.0.0+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
@@ -118,6 +126,8 @@ require (
github.com/gkampitakis/ciinfo v0.2.5 // indirect
github.com/gkampitakis/go-diff v1.3.2 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-restruct/restruct v1.2.0-alpha // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@@ -143,28 +153,40 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
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/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/runtime-spec v1.1.0-rc.1 // indirect
github.com/opencontainers/selinux v1.11.0 // indirect
github.com/pborman/indent v1.2.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/profile v1.7.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/sylabs/sif/v2 v2.11.5 // indirect
github.com/sylabs/squashfs v0.6.1 // indirect
@@ -181,10 +203,14 @@ require (
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
golang.org/x/tools v0.13.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.55.0 // indirect
+128 -50
View File
@@ -51,14 +51,18 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 h1:+vTEFqeoeur6XSq06bs+roX3YiT49gUniJK7Zky7Xjg=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652/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/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=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CycloneDX/cyclonedx-go v0.7.1 h1:5w1SxjGm9MTMNTuRbEPyw21ObdbaagTWF/KfF0qHTRE=
github.com/CycloneDX/cyclonedx-go v0.7.1/go.mod h1:N/nrdWQI2SIjaACyyDs/u7+ddCkyl/zkNs8xFsHF2Ps=
github.com/CycloneDX/cyclonedx-go v0.7.2 h1:kKQ0t1dPOlugSIYVOMiMtFqeXI2wp/f5DBIdfux8gnQ=
github.com/CycloneDX/cyclonedx-go v0.7.2/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
@@ -73,9 +77,11 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/hcsshim v0.10.0-rc.7 h1:HBytQPxcv8Oy4244zbQbe6hnOnx544eL5QPUqhJldz8=
github.com/Microsoft/hcsshim v0.10.0-rc.7/go.mod h1:ILuwjA+kNW+MrN/w5un7n3mTqkwsFu4Bp05/okFUZlE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs=
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE=
@@ -90,8 +96,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anchore/bubbly v0.0.0-20230801194016-acdb4981b461 h1:xGu4/uMWucwWV0YV3fpFIQZ6KVfS/Wfhmma8t0s0vRo=
github.com/anchore/bubbly v0.0.0-20230801194016-acdb4981b461/go.mod h1:Ger02eh5NpPm2IqkPAy396HU1KlK3BhOeCljDYXySSk=
github.com/anchore/clio v0.0.0-20230823172630-c42d666061af h1:dBVKZyMZeA0oZK0+aCCRoqxhxUvx/7xy/VEaLMMMnb0=
github.com/anchore/clio v0.0.0-20230823172630-c42d666061af/go.mod h1:XryJ3CIF1T7SbacQV+OPykfKKIbfXnBssYfpjy2peUg=
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/fangs v0.0.0-20230818131516-2186b10924fe h1:pVpLCGWdNeskAw7vGNdCAcGMezrNljHIqOc9HaOja5M=
github.com/anchore/fangs v0.0.0-20230818131516-2186b10924fe/go.mod h1:82EGoxZTfBXSW0/zollEP+Qs3wkiKmip5yBT5j+eZpY=
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw=
@@ -106,8 +112,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV
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.0-20230907152702-057dda3667e7 h1:mbYk+Cvvlfr/kRUz7LqATmjOT4+mV0YufNtj3aqU2fw=
github.com/anchore/stereoscope v0.0.0-20230907152702-057dda3667e7/go.mod h1:bEbCTAbTx/Ot+kSWVfXgInyU+88+0gP+G8L+LPgrunw=
github.com/anchore/stereoscope v0.0.0-20230925132944-bf05af58eb44 h1:dKMvcpgqsRrX1ZWyqG53faVW+BahlaAO1RUEc7/rOjA=
github.com/anchore/stereoscope v0.0.0-20230925132944-bf05af58eb44/go.mod h1:RtbeDCho0pxkPqrB1QNf/Jlxfc9juLmtYZAf2UbpJfk=
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=
@@ -150,11 +156,13 @@ github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06
github.com/charmbracelet/bubbletea v0.24.2/go.mod h1:XdrNrV4J8GiyshTtx3DNuYkR1FDaJmO3l2nejekbsgg=
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.8.0 h1:IS00fk4XAHcf8uZKc3eHeMUTCxUH6NkaTrdyCQk84RU=
github.com/charmbracelet/lipgloss v0.8.0/go.mod h1:p4eYUZZJ/0oXTuCQKFF8mqyKCz0ja6y+7DniDDw5KKU=
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/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=
@@ -170,36 +178,56 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
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.0 h1:G/ZQr3gMZs6ZT0qPUZ15znx5QSdQdASW11nXTLTM2Pg=
github.com/containerd/containerd v1.7.0/go.mod h1:QfR7Efgb/6X2BDpTPJRvPTYDE9rsF0FsXX9J8sIs/sc=
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/containerd/ttrpc v1.2.1 h1:VWv/Rzx023TBLv4WQ+9WPXlBG/s3rsRjY3i9AJ2BJdE=
github.com/containerd/ttrpc v1.2.1/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
github.com/containerd/typeurl/v2 v2.1.0 h1:yNAhJvbNEANt7ck48IlEGOxP7YAp6LLpGn5jZACDNIE=
github.com/containerd/typeurl/v2 v2.1.0/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/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=
github.com/dave/jennifer v1.7.0/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da h1:ZOjWpVsFZ06eIhnh4mkaceTiVoktdU67+M7KDHJ268M=
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4imdLi4Asdha1Sc6feLMTfPLXh9IUYmysk=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qeXMx3O0wqM=
github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
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 v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
github.com/docker/docker v24.0.6+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=
@@ -209,8 +237,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0=
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -234,6 +262,7 @@ github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA=
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
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=
@@ -242,26 +271,26 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS
github.com/gabriel-vasile/mimetype v1.4.0 h1:Cn9dkdYsMIu56tGho+fqzh7XmvY2YyGU0FnbhiOsEro=
github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/github/go-spdx/v2 v2.1.2 h1:p+Tv0yMgcuO0/vnMe9Qh4tmUgYhI6AsLVlakZ/Sx+DM=
github.com/github/go-spdx/v2 v2.1.2/go.mod h1:hMCrsFgT0QnCwn7G8gxy/MxMpy67WgZrwFeISTn0o6w=
github.com/github/go-spdx/v2 v2.2.0 h1:yBBLMasHA70Ujd35OpL/OjJOWWVNXcJGbars0GinGRI=
github.com/github/go-spdx/v2 v2.2.0/go.mod h1:hMCrsFgT0QnCwn7G8gxy/MxMpy67WgZrwFeISTn0o6w=
github.com/gkampitakis/ciinfo v0.2.5 h1:K0mac90lGguc1conc46l0YEsB7/nioWCqSnJp/6z8Eo=
github.com/gkampitakis/ciinfo v0.2.5/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.4.10 h1:rUcTH4k6+rzw6ylDALMifzw2c/f9cG3NZe/n+7Ygdr4=
github.com/gkampitakis/go-snaps v0.4.10/go.mod h1:N4TpqxI4CqKUfHzDFqrqZ5UP0I0ESz2g2NMslh7MiJw=
github.com/gkampitakis/go-snaps v0.4.11 h1:7qKaozbTQEvHeG0bt6osdjdTDTnWYdIrLx43a7DEDu4=
github.com/gkampitakis/go-snaps v0.4.11/go.mod h1:N4TpqxI4CqKUfHzDFqrqZ5UP0I0ESz2g2NMslh7MiJw=
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=
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A=
github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo=
github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY=
github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -269,6 +298,11 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSrdV7Nv3/gkvc=
github.com/go-restruct/restruct v1.2.0-alpha/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
@@ -276,6 +310,7 @@ 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=
@@ -331,8 +366,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ=
github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -498,8 +534,8 @@ github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 h1:P8UmIzZ
github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -529,6 +565,15 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
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/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=
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -538,6 +583,7 @@ 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=
@@ -547,15 +593,24 @@ 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
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=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
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/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=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/indent v1.2.1 h1:lFiviAbISHv3Rf0jcuh489bi06hj98JsVMtIDZQb9yM=
@@ -579,6 +634,7 @@ github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
@@ -595,6 +651,9 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
@@ -609,11 +668,13 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz
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.5 h1:ACIe9QnLTdiRIbuN3BbEUI8SqCQmNrPBb7O2lJTmsK4=
github.com/saferwall/pe v1.4.5/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7GZ25s=
github.com/saferwall/pe v1.4.7 h1:A+G3DxX49paJ5OsxBfHKskhyDtmTjShlDmBd81IsHlQ=
github.com/saferwall/pe v1.4.7/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7GZ25s=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
github.com/sassoftware/go-rpmutils v0.2.0 h1:pKW0HDYMFWQ5b4JQPiI3WI12hGsVoW0V8+GMoZiI/JE=
github.com/sassoftware/go-rpmutils v0.2.0/go.mod h1:TJJQYtLe/BeEmEjelI3b7xNZjzAukEkeWKmoakvaOoI=
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ=
@@ -621,6 +682,7 @@ 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=
@@ -631,6 +693,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@@ -642,8 +705,8 @@ github.com/spdx/tools-golang v0.5.3 h1:ialnHeEYUC4+hkm5vJm4qz2x+oEJbS0mAMFrNXdQr
github.com/spdx/tools-golang v0.5.3/go.mod h1:/ETOahiAo96Ob0/RAIBmFZw6XN0yTnyr/uFZm2NTMhI=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
@@ -663,6 +726,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
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/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=
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -683,6 +747,9 @@ 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=
github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
@@ -700,6 +767,7 @@ 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.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/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=
@@ -708,10 +776,12 @@ 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-20230301185719-21920a456ad5 h1:lwgTsTy18nYqASnH58qyfRW/ldj7Gt2zzBvgYPzdA4s=
github.com/wagoodman/go-progress v0.0.0-20230301185719-21920a456ad5/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA=
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 h1:0KGbf+0SMg+UFy4e1A/CPVvXn21f1qtWdeJwxZFoQG8=
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -745,10 +815,17 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -769,8 +846,8 @@ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/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.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
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=
@@ -781,8 +858,6 @@ 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-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
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=
@@ -796,7 +871,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -812,8 +886,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.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.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=
@@ -862,8 +936,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.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
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=
@@ -909,6 +983,7 @@ 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=
@@ -916,6 +991,7 @@ 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=
@@ -959,10 +1035,12 @@ 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=
@@ -977,16 +1055,16 @@ 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.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
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.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
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=
@@ -1064,8 +1142,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.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
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=
@@ -1274,8 +1352,8 @@ modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o=
modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA=
modernc.org/sqlite v1.25.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU=
modernc.org/sqlite v1.26.0 h1:SocQdLRSYlA8W99V8YH0NES75thx19d9sB/aFc4R8Lw=
modernc.org/sqlite v1.26.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU=
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=
+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 = "10.0.1"
JSONSchemaVersion = "11.0.1"
)
+4 -3
View File
@@ -6,7 +6,8 @@ import (
"sort"
"strings"
"github.com/anchore/syft/internal"
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/internal/log"
)
@@ -40,7 +41,7 @@ func (z ZipFileManifest) Add(entry string, info os.FileInfo) {
// GlobMatch returns the path keys that match the given value(s).
func (z ZipFileManifest) GlobMatch(patterns ...string) []string {
uniqueMatches := internal.NewStringSet()
uniqueMatches := strset.New()
for _, pattern := range patterns {
for entry := range z {
@@ -54,7 +55,7 @@ func (z ZipFileManifest) GlobMatch(patterns ...string) []string {
}
}
results := uniqueMatches.ToSlice()
results := uniqueMatches.List()
sort.Strings(results)
return results
+9 -8
View File
@@ -1,23 +1,26 @@
package licenses
import "github.com/anchore/syft/internal"
// all of these taken from https://github.com/golang/pkgsite/blob/8996ff632abee854aef1b764ca0501f262f8f523/internal/licenses/licenses.go#L338
// which unfortunately is not exported. But fortunately is under BSD-style license.
// which unfortunately is not exported. But fortunately is under BSD-style license. Take note that this list has
// been manually updated to include more license filenames (see https://github.com/anchore/syft/pull/2227).
var (
FileNames = []string{
func FileNames() []string {
return []string{
"AL2.0",
"COPYING",
"COPYING.md",
"COPYING.markdown",
"COPYING.txt",
"LGPL2.1",
"LICENCE",
"LICENCE.md",
"LICENCE.markdown",
"licence.txt",
"LICENCE.txt",
"LICENSE",
"LICENSE.md",
"LICENSE.markdown",
"license.txt",
"LICENSE.txt",
"LICENSE-2.0.txt",
"LICENCE-2.0.txt",
@@ -48,6 +51,4 @@ var (
"UNLICENSE",
"UNLICENCE",
}
FileNameSet = internal.NewStringSet(FileNames...)
)
}
+53 -2
View File
@@ -1,9 +1,9 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at 2023-07-11 11:55:35.533815 -0400 EDT m=+0.695308614
// This file was generated by robots at 2023-10-05 22:45:16.827263 -0400 EDT m=+0.138031521
// using data from https://spdx.org/licenses/licenses.json
package spdxlicense
const Version = "3.21"
const Version = "3.22"
var licenseIDs = map[string]string{
"0bsd": "0BSD",
@@ -14,6 +14,7 @@ var licenseIDs = map[string]string{
"adobe2006.0": "Adobe-2006",
"adobe2006.0.0": "Adobe-2006",
"adobeglyph": "Adobe-Glyph",
"adobeutopia": "Adobe-Utopia",
"adsl": "ADSL",
"afl1": "AFL-1.1",
"afl1.1": "AFL-1.1",
@@ -145,6 +146,8 @@ var licenseIDs = map[string]string{
"bsd3.0.0clause": "BSD-3-Clause",
"bsd3.0.0clauseattribution": "BSD-3-Clause-Attribution",
"bsd3.0.0clauseclear": "BSD-3-Clause-Clear",
"bsd3.0.0clauseflex": "BSD-3-Clause-flex",
"bsd3.0.0clausehp": "BSD-3-Clause-HP",
"bsd3.0.0clauselbnl": "BSD-3-Clause-LBNL",
"bsd3.0.0clausemodification": "BSD-3-Clause-Modification",
"bsd3.0.0clausenomilitarylicense": "BSD-3-Clause-No-Military-License",
@@ -152,9 +155,12 @@ var licenseIDs = map[string]string{
"bsd3.0.0clausenonuclearlicense2014": "BSD-3-Clause-No-Nuclear-License-2014",
"bsd3.0.0clausenonuclearwarranty": "BSD-3-Clause-No-Nuclear-Warranty",
"bsd3.0.0clauseopenmpi": "BSD-3-Clause-Open-MPI",
"bsd3.0.0clausesun": "BSD-3-Clause-Sun",
"bsd3.0clause": "BSD-3-Clause",
"bsd3.0clauseattribution": "BSD-3-Clause-Attribution",
"bsd3.0clauseclear": "BSD-3-Clause-Clear",
"bsd3.0clauseflex": "BSD-3-Clause-flex",
"bsd3.0clausehp": "BSD-3-Clause-HP",
"bsd3.0clauselbnl": "BSD-3-Clause-LBNL",
"bsd3.0clausemodification": "BSD-3-Clause-Modification",
"bsd3.0clausenomilitarylicense": "BSD-3-Clause-No-Military-License",
@@ -162,9 +168,12 @@ var licenseIDs = map[string]string{
"bsd3.0clausenonuclearlicense2014": "BSD-3-Clause-No-Nuclear-License-2014",
"bsd3.0clausenonuclearwarranty": "BSD-3-Clause-No-Nuclear-Warranty",
"bsd3.0clauseopenmpi": "BSD-3-Clause-Open-MPI",
"bsd3.0clausesun": "BSD-3-Clause-Sun",
"bsd3clause": "BSD-3-Clause",
"bsd3clauseattribution": "BSD-3-Clause-Attribution",
"bsd3clauseclear": "BSD-3-Clause-Clear",
"bsd3clauseflex": "BSD-3-Clause-flex",
"bsd3clausehp": "BSD-3-Clause-HP",
"bsd3clauselbnl": "BSD-3-Clause-LBNL",
"bsd3clausemodification": "BSD-3-Clause-Modification",
"bsd3clausenomilitarylicense": "BSD-3-Clause-No-Military-License",
@@ -172,6 +181,7 @@ var licenseIDs = map[string]string{
"bsd3clausenonuclearlicense2014": "BSD-3-Clause-No-Nuclear-License-2014",
"bsd3clausenonuclearwarranty": "BSD-3-Clause-No-Nuclear-Warranty",
"bsd3clauseopenmpi": "BSD-3-Clause-Open-MPI",
"bsd3clausesun": "BSD-3-Clause-Sun",
"bsd4.0.0clause": "BSD-4-Clause",
"bsd4.0.0clauseshortened": "BSD-4-Clause-Shortened",
"bsd4.0.0clauseuc": "BSD-4-Clause-UC",
@@ -189,8 +199,10 @@ var licenseIDs = map[string]string{
"bsd4tahoe": "BSD-4.3TAHOE",
"bsdadvertisingacknowledgement": "BSD-Advertising-Acknowledgement",
"bsdattributionhpnddisclaimer": "BSD-Attribution-HPND-disclaimer",
"bsdinfernonettverk": "BSD-Inferno-Nettverk",
"bsdprotection": "BSD-Protection",
"bsdsourcecode": "BSD-Source-Code",
"bsdsystemics": "BSD-Systemics",
"bsl1": "BSL-1.0",
"bsl1.0": "BSL-1.0",
"bsl1.0.0": "BSL-1.0",
@@ -403,6 +415,7 @@ var licenseIDs = map[string]string{
"cernohlw2.0": "CERN-OHL-W-2.0",
"cernohlw2.0.0": "CERN-OHL-W-2.0",
"cfitsio": "CFITSIO",
"checkcvs": "check-cvs",
"checkmk": "checkmk",
"clartistic": "ClArtistic",
"clips": "Clips",
@@ -432,6 +445,7 @@ var licenseIDs = map[string]string{
"cpol1": "CPOL-1.02",
"cpol1.02": "CPOL-1.02",
"cpol1.02.0": "CPOL-1.02",
"cronyx": "Cronyx",
"crossword": "Crossword",
"crystalstacker": "CrystalStacker",
"cuaopl1": "CUA-OPL-1.0",
@@ -449,6 +463,9 @@ var licenseIDs = map[string]string{
"dldeby2": "DL-DE-BY-2.0",
"dldeby2.0": "DL-DE-BY-2.0",
"dldeby2.0.0": "DL-DE-BY-2.0",
"dldezero2": "DL-DE-ZERO-2.0",
"dldezero2.0": "DL-DE-ZERO-2.0",
"dldezero2.0.0": "DL-DE-ZERO-2.0",
"doc": "DOC",
"dotseqn": "Dotseqn",
"drl1": "DRL-1.0",
@@ -500,7 +517,9 @@ var licenseIDs = map[string]string{
"eupl1.2.0": "EUPL-1.2",
"eurosym": "Eurosym",
"fair": "Fair",
"fbm": "FBM",
"fdkaac": "FDK-AAC",
"fergusontwofish": "Ferguson-Twofish",
"frameworx1": "Frameworx-1.0",
"frameworx1.0": "Frameworx-1.0",
"frameworx1.0.0": "Frameworx-1.0",
@@ -511,6 +530,8 @@ var licenseIDs = map[string]string{
"fsfullr": "FSFULLR",
"fsfullrwd": "FSFULLRWD",
"ftl": "FTL",
"furuseth": "Furuseth",
"fwlw": "fwlw",
"gd": "GD",
"gfdl1": "GFDL-1.1-only",
"gfdl1+": "GFDL-1.1-or-later",
@@ -658,11 +679,21 @@ var licenseIDs = map[string]string{
"hp1986": "HP-1986",
"hp1986.0": "HP-1986",
"hp1986.0.0": "HP-1986",
"hp1989": "HP-1989",
"hp1989.0": "HP-1989",
"hp1989.0.0": "HP-1989",
"hpnd": "HPND",
"hpnddec": "HPND-DEC",
"hpnddoc": "HPND-doc",
"hpnddocsell": "HPND-doc-sell",
"hpndexportus": "HPND-export-US",
"hpndexportusmodify": "HPND-export-US-modify",
"hpndmarkuskuhn": "HPND-Markus-Kuhn",
"hpndpbmplus": "HPND-Pbmplus",
"hpndsellregexpr": "HPND-sell-regexpr",
"hpndsellvariant": "HPND-sell-variant",
"hpndsellvariantmitdisclaimer": "HPND-sell-variant-MIT-disclaimer",
"hpnduc": "HPND-UC",
"htmltidy": "HTMLTIDY",
"ibmpibs": "IBM-pibs",
"icu": "ICU",
@@ -695,6 +726,7 @@ var licenseIDs = map[string]string{
"jplimage": "JPL-image",
"jpnic": "JPNIC",
"json": "JSON",
"kastrup": "Kastrup",
"kazlib": "Kazlib",
"knuthctan": "Knuth-CTAN",
"lal1": "LAL-1.2",
@@ -788,14 +820,18 @@ var licenseIDs = map[string]string{
"lppl1.3c": "LPPL-1.3c",
"lppl1a": "LPPL-1.3a",
"lppl1c": "LPPL-1.3c",
"lsof": "lsof",
"lucidabitmapfonts": "Lucida-Bitmap-Fonts",
"lzmasdk9": "LZMA-SDK-9.22",
"lzmasdk9.11.0to9.20": "LZMA-SDK-9.11-to-9.20",
"lzmasdk9.11to9.20": "LZMA-SDK-9.11-to-9.20",
"lzmasdk9.22": "LZMA-SDK-9.22",
"lzmasdk9.22.0": "LZMA-SDK-9.22",
"lzmasdk9to9.20": "LZMA-SDK-9.11-to-9.20",
"magaz": "magaz",
"makeindex": "MakeIndex",
"martinbirgmeier": "Martin-Birgmeier",
"mcpheeslideshow": "McPhee-slideshow",
"metamail": "metamail",
"minpack": "Minpack",
"miros": "MirOS",
@@ -809,8 +845,11 @@ var licenseIDs = map[string]string{
"mitmodernvariant": "MIT-Modern-Variant",
"mitnfa": "MITNFA",
"mitopengroup": "MIT-open-group",
"mittestregex": "MIT-testregex",
"mitwu": "MIT-Wu",
"mmixware": "MMIXware",
"motosoto": "Motosoto",
"mpegssg": "MPEG-SSG",
"mpich2": "mpich2",
"mpich2.0": "mpich2",
"mpich2.0.0": "mpich2",
@@ -997,6 +1036,7 @@ var licenseIDs = map[string]string{
"ouda1": "O-UDA-1.0",
"ouda1.0": "O-UDA-1.0",
"ouda1.0.0": "O-UDA-1.0",
"padl": "PADL",
"parity6": "Parity-6.0.0",
"parity6.0": "Parity-6.0.0",
"parity6.0.0": "Parity-6.0.0",
@@ -1012,6 +1052,7 @@ var licenseIDs = map[string]string{
"php3.01": "PHP-3.01",
"php3.01.0": "PHP-3.01",
"plexus": "Plexus",
"pnmstitch": "pnmstitch",
"polyformnoncommercial1": "PolyForm-Noncommercial-1.0.0",
"polyformnoncommercial1.0": "PolyForm-Noncommercial-1.0.0",
"polyformnoncommercial1.0.0": "PolyForm-Noncommercial-1.0.0",
@@ -1028,6 +1069,7 @@ var licenseIDs = map[string]string{
"python2.0": "Python-2.0",
"python2.0.0": "Python-2.0",
"python2.0.1": "Python-2.0.1",
"pythonldap": "python-ldap",
"qhull": "Qhull",
"qpl1": "QPL-1.0",
"qpl1.0": "QPL-1.0",
@@ -1066,6 +1108,7 @@ var licenseIDs = map[string]string{
"sgib2": "SGI-B-2.0",
"sgib2.0": "SGI-B-2.0",
"sgib2.0.0": "SGI-B-2.0",
"sgiopengl": "SGI-OpenGL",
"sgp4": "SGP4",
"sgp4.0": "SGP4",
"sgp4.0.0": "SGP4",
@@ -1080,11 +1123,13 @@ var licenseIDs = map[string]string{
"sissl1": "SISSL-1.2",
"sissl1.2": "SISSL-1.2",
"sissl1.2.0": "SISSL-1.2",
"sl": "SL",
"sleepycat": "Sleepycat",
"smlnj": "SMLNJ",
"smppl": "SMPPL",
"snia": "SNIA",
"snprintf": "snprintf",
"soundex": "Soundex",
"spencer86": "Spencer-86",
"spencer86.0": "Spencer-86",
"spencer86.0.0": "Spencer-86",
@@ -1097,6 +1142,7 @@ var licenseIDs = map[string]string{
"spl1": "SPL-1.0",
"spl1.0": "SPL-1.0",
"spl1.0.0": "SPL-1.0",
"sshkeyscan": "ssh-keyscan",
"sshopenssh": "SSH-OpenSSH",
"sshshort": "SSH-short",
"sspl1": "SSPL-1.0",
@@ -1108,6 +1154,7 @@ var licenseIDs = map[string]string{
"sugarcrm1.1.3": "SugarCRM-1.1.3",
"sunpro": "SunPro",
"swl": "SWL",
"swrule": "swrule",
"symlinks": "Symlinks",
"taprohl1": "TAPR-OHL-1.0",
"taprohl1.0": "TAPR-OHL-1.0",
@@ -1125,6 +1172,7 @@ var licenseIDs = map[string]string{
"tpl1.0": "TPL-1.0",
"tpl1.0.0": "TPL-1.0",
"ttwl": "TTWL",
"ttyp0": "TTYP0",
"tuberlin1": "TU-Berlin-1.0",
"tuberlin1.0": "TU-Berlin-1.0",
"tuberlin1.0.0": "TU-Berlin-1.0",
@@ -1135,6 +1183,7 @@ var licenseIDs = map[string]string{
"ucl1": "UCL-1.0",
"ucl1.0": "UCL-1.0",
"ucl1.0.0": "UCL-1.0",
"ulem": "ulem",
"unicodedfs2015": "Unicode-DFS-2015",
"unicodedfs2015.0": "Unicode-DFS-2015",
"unicodedfs2015.0.0": "Unicode-DFS-2015",
@@ -1147,6 +1196,7 @@ var licenseIDs = map[string]string{
"upl1": "UPL-1.0",
"upl1.0": "UPL-1.0",
"upl1.0.0": "UPL-1.0",
"urtrle": "URT-RLE",
"vim": "Vim",
"vostrom": "VOSTROM",
"vsl1": "VSL-1.0",
@@ -1196,6 +1246,7 @@ var licenseIDs = map[string]string{
"ypl1.1": "YPL-1.1",
"ypl1.1.0": "YPL-1.1",
"zed": "Zed",
"zeeff": "Zeeff",
"zend2": "Zend-2.0",
"zend2.0": "Zend-2.0",
"zend2.0.0": "Zend-2.0",
+1 -1
View File
@@ -1,6 +1,6 @@
# CycloneDX Schemas
`syft` generates a CycloneDX BOm output. We want to be able to validate the CycloneDX schemas
`syft` generates a CycloneDX Bom output. We want to be able to validate the CycloneDX schemas
(and dependent schemas) against generated syft output. The best way to do this is with `xmllint`,
however, this tool does not know how to deal with references from HTTP, only the local filesystem.
For this reason we've included a copy of all schemas needed to validate `syft` output, modified
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
@@ -27,7 +27,8 @@ func GetValidator(format cyclonedx.BOMFileFormat) sbom.Validator {
}
xmlWithoutNS := format == cyclonedx.BOMFileFormatXML && !strings.Contains(bom.XMLNS, cycloneDXXmlSchema)
if (cyclonedx.BOM{} == *bom || bom.Components == nil || xmlWithoutNS) {
xmlWithoutComponents := format == cyclonedx.BOMFileFormatXML && bom.Components == nil
if (cyclonedx.BOM{} == *bom || xmlWithoutComponents || xmlWithoutNS) {
return fmt.Errorf("not a valid CycloneDX document")
}
return nil
@@ -97,7 +97,7 @@ func toCycloneDXAlgorithm(algorithm string) cyclonedx.HashAlgorithm {
"sha256": cyclonedx.HashAlgorithm("SHA-256"),
}
return validMap[algorithm]
return validMap[strings.ToLower(algorithm)]
}
func decodeExternalReferences(c *cyclonedx.Component, metadata interface{}) {
@@ -173,3 +173,27 @@ func Test_isValidExternalRef(t *testing.T) {
})
}
}
func Test_toCycloneDXAlgorithm(t *testing.T) {
tests := []struct {
name string
input string
expected cyclonedx.HashAlgorithm
}{
{
name: "valid algorithm name in upper case",
input: "SHA1",
expected: cyclonedx.HashAlgorithm("SHA-1"),
},
{
name: "valid algorithm name in lower case",
input: "sha1",
expected: cyclonedx.HashAlgorithm("SHA-1"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
assert.Equal(t, test.expected, toCycloneDXAlgorithm(test.input))
})
}
}
@@ -1,12 +1,12 @@
package cyclonedxhelpers
import (
"slices"
"strings"
"time"
"github.com/CycloneDX/cyclonedx-go"
"github.com/google/uuid"
"golang.org/x/exp/slices"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
@@ -95,7 +95,7 @@ func separateLicenses(p pkg.Package) (spdx, other cyclonedx.Licenses, expression
// singular expression case
// only ID field here since we guarantee that the license is valid
if value, exists := spdxlicense.ID(l.SPDXExpression); exists {
if !l.URLs.Empty() {
if len(l.URLs) > 0 {
processLicenseURLs(l, value, &spdxc)
continue
}
@@ -123,7 +123,7 @@ func separateLicenses(p pkg.Package) (spdx, other cyclonedx.Licenses, expression
// license string that are not valid spdx expressions or ids
// we only use license Name here since we cannot guarantee that the license is a valid SPDX expression
if !l.URLs.Empty() {
if len(l.URLs) > 0 {
processLicenseURLs(l, "", &otherc)
continue
}
@@ -137,7 +137,7 @@ func separateLicenses(p pkg.Package) (spdx, other cyclonedx.Licenses, expression
}
func processLicenseURLs(l pkg.License, spdxID string, populate *cyclonedx.Licenses) {
for _, url := range l.URLs.ToSlice() {
for _, url := range l.URLs {
if spdxID == "" {
*populate = append(*populate, cyclonedx.LicenseChoice{
License: &cyclonedx.License{
@@ -4,9 +4,9 @@ import (
"testing"
"github.com/CycloneDX/cyclonedx-go"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/syft/license"
"github.com/anchore/syft/syft/pkg"
)
@@ -191,7 +191,9 @@ func Test_encodeLicense(t *testing.T) {
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
assert.Equal(t, test.expected, encodeLicenses(test.input))
if d := cmp.Diff(test.expected, encodeLicenses(test.input)); d != "" {
t.Errorf("unexpected license (-want +got):\n%s", d)
}
})
}
}
@@ -223,7 +225,7 @@ func TestDecodeLicenses(t *testing.T) {
Value: "RandomLicense",
// CycloneDX specification doesn't give a field for determining the license type
Type: license.Declared,
URLs: internal.NewStringSet(),
URLs: []string{},
},
},
},
@@ -243,7 +245,7 @@ func TestDecodeLicenses(t *testing.T) {
Value: "MIT",
SPDXExpression: "MIT",
Type: license.Declared,
URLs: internal.NewStringSet(),
URLs: []string{},
},
},
},
@@ -262,7 +264,7 @@ func TestDecodeLicenses(t *testing.T) {
Value: "MIT AND GPL-3.0-only WITH Classpath-exception-2.0",
SPDXExpression: "MIT AND GPL-3.0-only WITH Classpath-exception-2.0",
Type: license.Declared,
URLs: internal.NewStringSet(),
URLs: []string{},
},
},
},
@@ -20,6 +20,8 @@ func DownloadLocation(p pkg.Package) string {
return NoneIfEmpty(metadata.URL)
case pkg.NpmPackageJSONMetadata:
return NoneIfEmpty(metadata.URL)
case pkg.NpmPackageLockJSONMetadata:
return NoneIfEmpty(metadata.Resolved)
}
}
return NOASSERTION
@@ -46,6 +46,24 @@ func Test_DownloadLocation(t *testing.T) {
},
expected: NONE,
},
{
name: "from npm package-lock should include resolved",
input: pkg.Package{
Metadata: pkg.NpmPackageLockJSONMetadata{
Resolved: "http://package-lock.test",
},
},
expected: "http://package-lock.test",
},
{
name: "from npm package-lock empty should be NONE",
input: pkg.Package{
Metadata: pkg.NpmPackageLockJSONMetadata{
Resolved: "",
},
},
expected: NONE,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
@@ -56,6 +56,8 @@ func SourceInfo(p pkg.Package) string {
answer = "acquired package info from R-package DESCRIPTION file"
case pkg.SwiftPkg:
answer = "acquired package info from resolved Swift package manifest"
case pkg.GithubActionPkg, pkg.GithubActionWorkflowPkg:
answer = "acquired package info from GitHub Actions workflow file or composite action file"
default:
answer = "acquired package info from the following paths"
}
@@ -239,6 +239,22 @@ func Test_SourceInfo(t *testing.T) {
"from resolved Swift package manifest",
},
},
{
input: pkg.Package{
Type: pkg.GithubActionPkg,
},
expected: []string{
"from GitHub Actions workflow file or composite action file",
},
},
{
input: pkg.Package{
Type: pkg.GithubActionWorkflowPkg,
},
expected: []string{
"from GitHub Actions workflow file or composite action file",
},
},
}
var pkgTypes []pkg.Type
for _, test := range tests {
@@ -5,14 +5,13 @@ import (
"crypto/sha1"
"fmt"
"path"
"slices"
"sort"
"strings"
"time"
"github.com/docker/distribution/reference"
"github.com/distribution/reference"
"github.com/spdx/tools-golang/spdx"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/internal"
@@ -722,7 +721,11 @@ func toOtherLicenses(catalog *pkg.Collection) []*spdx.OtherLicense {
var result []*spdx.OtherLicense
ids := maps.Keys(licenses)
var ids []string
for licenseID := range licenses {
ids = append(ids, licenseID)
}
slices.Sort(ids)
for _, id := range ids {
license := licenses[id]
+32 -3
View File
@@ -9,11 +9,40 @@ import (
"github.com/anchore/syft/syft/sbom"
)
func encoder(output io.Writer, s sbom.SBOM) error {
func encoderV1_0(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_0)
}
func encoderV1_1(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_1)
}
func encoderV1_2(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_2)
}
func encoderV1_3(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_3)
}
func encoderV1_4(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_4)
}
func encoderV1_5(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_5)
}
func buildEncoder(output io.Writer, s sbom.SBOM) (cyclonedx.BOMEncoder, *cyclonedx.BOM) {
bom := cyclonedxhelpers.ToFormatModel(s)
enc := cyclonedx.NewBOMEncoder(output, cyclonedx.BOMFileFormatJSON)
enc.SetPretty(true)
enc.SetEscapeHTML(false)
err := enc.Encode(bom)
return err
return enc, bom
}
+55 -3
View File
@@ -9,10 +9,62 @@ import (
const ID sbom.FormatID = "cyclonedx-json"
func Format() sbom.Format {
var Format = Format1_4
func Format1_0() sbom.Format {
return sbom.NewFormat(
sbom.AnyVersion,
encoder,
cyclonedx.SpecVersion1_0.String(),
encoderV1_0,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
ID,
)
}
func Format1_1() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_1.String(),
encoderV1_1,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
ID,
)
}
func Format1_2() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_2.String(),
encoderV1_2,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
ID,
)
}
func Format1_3() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_3.String(),
encoderV1_3,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
ID,
)
}
func Format1_4() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_4.String(),
encoderV1_4,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
ID,
)
}
func Format1_5() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_5.String(),
encoderV1_5,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
ID,
+34
View File
@@ -0,0 +1,34 @@
package cyclonedxjson
import (
"testing"
"github.com/CycloneDX/cyclonedx-go"
)
func TestFormatVersions(t *testing.T) {
tests := []struct {
name string
expectedVersion string
}{
{
"cyclonedx-json should default to v1.4",
cyclonedx.SpecVersion1_4.String(),
},
}
for _, c := range tests {
c := c
t.Run(c.name, func(t *testing.T) {
sbomFormat := Format()
if sbomFormat.ID() != ID {
t.Errorf("expected ID %q, got %q", ID, sbomFormat.ID())
}
if sbomFormat.Version() != c.expectedVersion {
t.Errorf("expected version %q, got %q", c.expectedVersion, sbomFormat.Version())
}
})
}
}
+33 -4
View File
@@ -9,11 +9,40 @@ import (
"github.com/anchore/syft/syft/sbom"
)
func encoder(output io.Writer, s sbom.SBOM) error {
func encoderV1_0(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_0)
}
func encoderV1_1(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_1)
}
func encoderV1_2(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_2)
}
func encoderV1_3(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_3)
}
func encoderV1_4(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_4)
}
func encoderV1_5(output io.Writer, s sbom.SBOM) error {
enc, bom := buildEncoder(output, s)
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_5)
}
func buildEncoder(output io.Writer, s sbom.SBOM) (cyclonedx.BOMEncoder, *cyclonedx.BOM) {
bom := cyclonedxhelpers.ToFormatModel(s)
enc := cyclonedx.NewBOMEncoder(output, cyclonedx.BOMFileFormatXML)
enc.SetPretty(true)
err := enc.Encode(bom)
return err
enc.SetEscapeHTML(false)
return enc, bom
}
+1 -1
View File
@@ -57,7 +57,7 @@ func redactor(values ...string) testutils.Redactor {
`sha256:[A-Za-z0-9]{64}`: `sha256:redacted`,
// BOM refs
`bom-ref="[a-zA-Z0-9\-:]+"`: `bom-ref:redacted`,
`bom-ref="[a-zA-Z0-9\-:]+"`: `bom-ref="redacted"`,
},
)
}
+55 -3
View File
@@ -9,10 +9,62 @@ import (
const ID sbom.FormatID = "cyclonedx-xml"
func Format() sbom.Format {
var Format = Format1_4
func Format1_0() sbom.Format {
return sbom.NewFormat(
sbom.AnyVersion,
encoder,
cyclonedx.SpecVersion1_0.String(),
encoderV1_0,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
ID, "cyclonedx", "cyclone",
)
}
func Format1_1() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_1.String(),
encoderV1_1,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
ID, "cyclonedx", "cyclone",
)
}
func Format1_2() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_2.String(),
encoderV1_2,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
ID, "cyclonedx", "cyclone",
)
}
func Format1_3() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_3.String(),
encoderV1_3,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
ID, "cyclonedx", "cyclone",
)
}
func Format1_4() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_4.String(),
encoderV1_4,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
ID, "cyclonedx", "cyclone",
)
}
func Format1_5() sbom.Format {
return sbom.NewFormat(
cyclonedx.SpecVersion1_5.String(),
encoderV1_5,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
ID, "cyclonedx", "cyclone",
@@ -32,7 +32,7 @@
<property name="syft:location:0:path">/some/path/pkg1</property>
</properties>
</component>
<component bom-ref="pkg:deb/debian/package-2@2.0.1?package-id=db4abfe497c180d3" type="library">
<component bom-ref="pkg:deb/debian/package-2@2.0.1?package-id=ad5013466727018f" type="library">
<name>package-2</name>
<version>2.0.1</version>
<cpe>cpe:2.3:*:some:package:2:*:*:*:*:*:*:*</cpe>
@@ -34,7 +34,7 @@
<property name="syft:location:0:path">/somefile-1.txt</property>
</properties>
</component>
<component bom-ref="pkg:deb/debian/package-2@2.0.1?package-id=958443e2d9304af4" type="library">
<component bom-ref="pkg:deb/debian/package-2@2.0.1?package-id=f27313b22a5ba330" type="library">
<name>package-2</name>
<version>2.0.1</version>
<cpe>cpe:2.3:*:some:package:2:*:*:*:*:*:*:*</cpe>
+27 -8
View File
@@ -6,10 +6,9 @@ import (
"fmt"
"io"
"regexp"
"slices"
"strings"
"golang.org/x/exp/slices"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/formats/cyclonedxjson"
"github.com/anchore/syft/syft/formats/cyclonedxxml"
@@ -26,17 +25,27 @@ import (
func Formats() []sbom.Format {
return []sbom.Format{
syftjson.Format(),
cyclonedxxml.Format(),
cyclonedxjson.Format(),
github.Format(),
table.Format(),
text.Format(),
template.Format(),
cyclonedxxml.Format1_0(),
cyclonedxxml.Format1_1(),
cyclonedxxml.Format1_2(),
cyclonedxxml.Format1_3(),
cyclonedxxml.Format1_4(),
cyclonedxxml.Format1_5(),
cyclonedxjson.Format1_0(),
cyclonedxjson.Format1_1(),
cyclonedxjson.Format1_2(),
cyclonedxjson.Format1_3(),
cyclonedxjson.Format1_4(),
cyclonedxjson.Format1_5(),
spdxtagvalue.Format2_1(),
spdxtagvalue.Format2_2(),
spdxtagvalue.Format2_3(),
spdxjson.Format2_2(),
spdxjson.Format2_3(),
table.Format(),
text.Format(),
template.Format(),
}
}
@@ -55,7 +64,7 @@ func Identify(by []byte) sbom.Format {
// ByName accepts a name@version string, such as:
//
// spdx-json@2.1 or cyclonedx@2
// spdx-json@2.1 or cyclonedx@1.5
func ByName(name string) sbom.Format {
parts := strings.SplitN(name, "@", 2)
version := sbom.AnyVersion
@@ -71,6 +80,16 @@ func ByNameAndVersion(name string, version string) sbom.Format {
for _, f := range Formats() {
for _, n := range f.IDs() {
if cleanFormatName(string(n)) == name && versionMatches(f.Version(), version) {
// if the version is not specified and the format is cyclonedx, then we want to return the most recent version up to 1.4
// If more aliases like cdx are added this will not catch those - we want to eventually provide a way for
// formats to inform this function what their default version is
// TODO: remove this check when 1.5 is stable or default formats are designed. PR below should be merged.
// https://github.com/CycloneDX/cyclonedx-go/pull/90
if version == sbom.AnyVersion && strings.Contains(string(n), "cyclone") {
if f.Version() == "1.5" {
continue
}
}
if mostRecentFormat == nil || f.Version() > mostRecentFormat.Version() {
mostRecentFormat = f
}
-1
View File
@@ -70,7 +70,6 @@ func TestFormats_EmptyInput(t *testing.T) {
}
func TestByName(t *testing.T) {
tests := []struct {
name string
want sbom.FormatID
@@ -39,7 +39,7 @@
},
{
"name": "package-2",
"SPDXID": "SPDXRef-Package-deb-package-2-db4abfe497c180d3",
"SPDXID": "SPDXRef-Package-deb-package-2-ad5013466727018f",
"versionInfo": "2.0.1",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
@@ -78,7 +78,7 @@
},
{
"spdxElementId": "SPDXRef-DocumentRoot-Directory-some-path",
"relatedSpdxElement": "SPDXRef-Package-deb-package-2-db4abfe497c180d3",
"relatedSpdxElement": "SPDXRef-Package-deb-package-2-ad5013466727018f",
"relationshipType": "CONTAINS"
},
{
@@ -39,7 +39,7 @@
},
{
"name": "package-2",
"SPDXID": "SPDXRef-Package-deb-package-2-958443e2d9304af4",
"SPDXID": "SPDXRef-Package-deb-package-2-f27313b22a5ba330",
"versionInfo": "2.0.1",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
@@ -92,7 +92,7 @@
},
{
"spdxElementId": "SPDXRef-DocumentRoot-Image-user-image-input",
"relatedSpdxElement": "SPDXRef-Package-deb-package-2-958443e2d9304af4",
"relatedSpdxElement": "SPDXRef-Package-deb-package-2-f27313b22a5ba330",
"relationshipType": "CONTAINS"
},
{
@@ -39,7 +39,7 @@
},
{
"name": "package-2",
"SPDXID": "SPDXRef-Package-deb-package-2-958443e2d9304af4",
"SPDXID": "SPDXRef-Package-deb-package-2-f27313b22a5ba330",
"versionInfo": "2.0.1",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
@@ -214,7 +214,7 @@
},
{
"spdxElementId": "SPDXRef-DocumentRoot-Image-user-image-input",
"relatedSpdxElement": "SPDXRef-Package-deb-package-2-958443e2d9304af4",
"relatedSpdxElement": "SPDXRef-Package-deb-package-2-f27313b22a5ba330",
"relationshipType": "CONTAINS"
},
{
@@ -61,7 +61,7 @@ ExternalRef: PACKAGE-MANAGER purl pkg:oci/user-image-input@sha256:2731251dc34951
##### Package: package-2
PackageName: package-2
SPDXID: SPDXRef-Package-deb-package-2-958443e2d9304af4
SPDXID: SPDXRef-Package-deb-package-2-f27313b22a5ba330
PackageVersion: 2.0.1
PackageSupplier: NOASSERTION
PackageDownloadLocation: NOASSERTION
@@ -97,6 +97,6 @@ Relationship: SPDXRef-Package-python-package-1-125840abc1c66dd7 CONTAINS SPDXRef
Relationship: SPDXRef-Package-python-package-1-125840abc1c66dd7 CONTAINS SPDXRef-File-d1-f3-c6f5b29dca12661f
Relationship: SPDXRef-Package-python-package-1-125840abc1c66dd7 CONTAINS SPDXRef-File-f2-f9e49132a4b96ccd
Relationship: SPDXRef-DocumentRoot-Image-user-image-input CONTAINS SPDXRef-Package-python-package-1-125840abc1c66dd7
Relationship: SPDXRef-DocumentRoot-Image-user-image-input CONTAINS SPDXRef-Package-deb-package-2-958443e2d9304af4
Relationship: SPDXRef-DocumentRoot-Image-user-image-input CONTAINS SPDXRef-Package-deb-package-2-f27313b22a5ba330
Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-DocumentRoot-Image-user-image-input
@@ -20,7 +20,7 @@ FilesAnalyzed: false
##### Package: package-2
PackageName: package-2
SPDXID: SPDXRef-Package-deb-package-2-db4abfe497c180d3
SPDXID: SPDXRef-Package-deb-package-2-ad5013466727018f
PackageVersion: 2.0.1
PackageSupplier: NOASSERTION
PackageDownloadLocation: NOASSERTION
@@ -50,6 +50,6 @@ ExternalRef: PACKAGE-MANAGER purl a-purl-2
##### Relationships
Relationship: SPDXRef-DocumentRoot-Directory-some-path CONTAINS SPDXRef-Package-python-package-1-9265397e5e15168a
Relationship: SPDXRef-DocumentRoot-Directory-some-path CONTAINS SPDXRef-Package-deb-package-2-db4abfe497c180d3
Relationship: SPDXRef-DocumentRoot-Directory-some-path CONTAINS SPDXRef-Package-deb-package-2-ad5013466727018f
Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-DocumentRoot-Directory-some-path
@@ -23,7 +23,7 @@ ExternalRef: PACKAGE-MANAGER purl pkg:oci/user-image-input@sha256:2731251dc34951
##### Package: package-2
PackageName: package-2
SPDXID: SPDXRef-Package-deb-package-2-958443e2d9304af4
SPDXID: SPDXRef-Package-deb-package-2-f27313b22a5ba330
PackageVersion: 2.0.1
PackageSupplier: NOASSERTION
PackageDownloadLocation: NOASSERTION
@@ -53,6 +53,6 @@ ExternalRef: PACKAGE-MANAGER purl a-purl-1
##### Relationships
Relationship: SPDXRef-DocumentRoot-Image-user-image-input CONTAINS SPDXRef-Package-python-package-1-125840abc1c66dd7
Relationship: SPDXRef-DocumentRoot-Image-user-image-input CONTAINS SPDXRef-Package-deb-package-2-958443e2d9304af4
Relationship: SPDXRef-DocumentRoot-Image-user-image-input CONTAINS SPDXRef-Package-deb-package-2-f27313b22a5ba330
Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-DocumentRoot-Image-user-image-input
+150
View File
@@ -9,8 +9,16 @@ import (
"github.com/go-test/deep"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/formats/internal/testutils"
"github.com/anchore/syft/syft/linux"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)
func TestEncodeDecodeCycle(t *testing.T) {
@@ -86,3 +94,145 @@ func TestOutOfDateParser(t *testing.T) {
})
}
}
func Test_encodeDecodeFileMetadata(t *testing.T) {
p := pkg.Package{
Name: "pkg",
Version: "version",
FoundBy: "something",
Locations: file.NewLocationSet(file.Location{
LocationData: file.LocationData{
Coordinates: file.Coordinates{
RealPath: "/somewhere",
FileSystemID: "id",
},
},
LocationMetadata: file.LocationMetadata{
Annotations: map[string]string{
"key": "value",
},
},
}),
Licenses: pkg.NewLicenseSet(pkg.License{
Value: "MIT",
SPDXExpression: "MIT",
Type: "MIT",
URLs: []string{"https://example.org/license"},
Locations: file.LocationSet{},
}),
Language: "language",
Type: "type",
CPEs: []cpe.CPE{
{
Part: "a",
Vendor: "vendor",
Product: "product",
Version: "version",
Update: "update",
},
},
PURL: "pkg:generic/pkg@version",
MetadataType: "",
Metadata: nil,
}
p.SetID()
c := file.Coordinates{
RealPath: "some-file",
FileSystemID: "some-fs-id",
}
s := sbom.SBOM{
Artifacts: sbom.Artifacts{
Packages: pkg.NewCollection(p),
FileMetadata: map[file.Coordinates]file.Metadata{
c: {
FileInfo: stereoscopeFile.ManualInfo{
NameValue: c.RealPath,
ModeValue: 0644,
SizeValue: 7,
},
Path: c.RealPath,
Type: stereoscopeFile.TypeRegular,
UserID: 1,
GroupID: 2,
MIMEType: "text/plain",
},
},
FileDigests: map[file.Coordinates][]file.Digest{
c: {
{
Algorithm: "sha1",
Value: "d34db33f",
},
},
},
FileContents: map[file.Coordinates]string{
c: "some contents",
},
FileLicenses: map[file.Coordinates][]file.License{
c: {
{
Value: "MIT",
SPDXExpression: "MIT",
Type: "MIT",
LicenseEvidence: &file.LicenseEvidence{
Confidence: 1,
Offset: 2,
Extent: 3,
},
},
},
},
LinuxDistribution: &linux.Release{
PrettyName: "some os",
Name: "os",
ID: "os-id",
IDLike: []string{"os"},
Version: "version",
VersionID: "version",
VersionCodename: "codename",
BuildID: "build-id",
ImageID: "image-id",
ImageVersion: "image-version",
Variant: "variant",
VariantID: "variant-id",
HomeURL: "https://example.org/os",
SupportURL: "https://example.org/os/support",
BugReportURL: "https://example.org/os/bugs",
PrivacyPolicyURL: "https://example.org/os/privacy",
CPEName: "os-cpe",
SupportEnd: "now",
},
},
Relationships: nil,
Source: source.Description{
ID: "some-id",
Name: "some-name",
Version: "some-version",
Metadata: source.FileSourceMetadata{
Path: "/some-file-source-path",
Digests: []file.Digest{
{
Algorithm: "sha1",
Value: "d34db33f",
},
},
MIMEType: "file/zip",
},
},
Descriptor: sbom.Descriptor{
Name: "syft",
Version: "this-version",
},
}
buf := &bytes.Buffer{}
err := encoder(buf, s)
require.NoError(t, err)
got, err := decoder(buf)
require.NoError(t, err)
require.Equal(t, s, *got)
}
+33
View File
@@ -0,0 +1,33 @@
package syftjson
import (
"testing"
"github.com/anchore/syft/internal"
)
func TestFormat(t *testing.T) {
tests := []struct {
name string
version string
}{
{
name: "default version should use latest internal version",
version: "",
},
}
for _, c := range tests {
c := c
t.Run(c.name, func(t *testing.T) {
sbomFormat := Format()
if sbomFormat.ID() != ID {
t.Errorf("expected ID %q, got %q", ID, sbomFormat.ID())
}
if sbomFormat.Version() != internal.JSONSchemaVersion {
t.Errorf("expected version %q, got %q", c.version, sbomFormat.Version())
}
})
}
}
+15
View File
@@ -2,6 +2,7 @@ package model
import (
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/license"
)
type File struct {
@@ -10,6 +11,7 @@ type File struct {
Metadata *FileMetadataEntry `json:"metadata,omitempty"`
Contents string `json:"contents,omitempty"`
Digests []file.Digest `json:"digests,omitempty"`
Licenses []FileLicense `json:"licenses,omitempty"`
}
type FileMetadataEntry struct {
@@ -21,3 +23,16 @@ type FileMetadataEntry struct {
MIMEType string `json:"mimeType"`
Size int64 `json:"size"`
}
type FileLicense struct {
Value string `json:"value"`
SPDXExpression string `json:"spdxExpression"`
Type license.Type `json:"type"`
Evidence *FileLicenseEvidence `json:"evidence,omitempty"`
}
type FileLicenseEvidence struct {
Confidence int `json:"confidence"`
Offset int `json:"offset"`
Extent int `json:"extent"`
}
@@ -41,7 +41,7 @@
}
},
{
"id": "db4abfe497c180d3",
"id": "ad5013466727018f",
"name": "package-2",
"version": "2.0.1",
"type": "deb",
@@ -36,7 +36,7 @@
}
},
{
"id": "9fd0b9f41034991d",
"id": "aa0ca2c331576dfd",
"name": "package-2",
"version": "2.0.1",
"type": "deb",
@@ -37,7 +37,7 @@
}
},
{
"id": "958443e2d9304af4",
"id": "f27313b22a5ba330",
"name": "package-2",
"version": "2.0.1",
"type": "deb",
+27 -1
View File
@@ -106,12 +106,31 @@ func toFile(s sbom.SBOM) []model.File {
contents = contentsForLocation
}
var licenses []model.FileLicense
for _, l := range artifacts.FileLicenses[coordinates] {
var evidence *model.FileLicenseEvidence
if e := l.LicenseEvidence; e != nil {
evidence = &model.FileLicenseEvidence{
Confidence: e.Confidence,
Offset: e.Offset,
Extent: e.Extent,
}
}
licenses = append(licenses, model.FileLicense{
Value: l.Value,
SPDXExpression: l.SPDXExpression,
Type: l.Type,
Evidence: evidence,
})
}
results = append(results, model.File{
ID: string(coordinates.ID()),
Location: coordinates,
Metadata: toFileMetadataEntry(coordinates, metadata),
Digests: digests,
Contents: contents,
Licenses: licenses,
})
}
@@ -195,11 +214,18 @@ func toLicenseModel(pkgLicenses []pkg.License) (modelLicenses []model.License) {
if v := l.Locations.ToSlice(); v != nil {
locations = v
}
// format model must have allocated collections
urls := l.URLs
if urls == nil {
urls = []string{}
}
modelLicenses = append(modelLicenses, model.License{
Value: l.Value,
SPDXExpression: l.SPDXExpression,
Type: l.Type,
URLs: l.URLs.ToSlice(),
URLs: urls,
Locations: locations,
})
}
+26 -2
View File
@@ -10,7 +10,6 @@ import (
"github.com/google/go-cmp/cmp"
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/cpe"
@@ -34,6 +33,8 @@ func toSyftModel(doc model.Document) (*sbom.SBOM, error) {
Packages: catalog,
FileMetadata: fileArtifacts.FileMetadata,
FileDigests: fileArtifacts.FileDigests,
FileContents: fileArtifacts.FileContents,
FileLicenses: fileArtifacts.FileLicenses,
LinuxDistribution: toSyftLinuxRelease(doc.Distro),
},
Source: *toSyftSourceData(doc.Source),
@@ -66,6 +67,8 @@ func toSyftFiles(files []model.File) sbom.Artifacts {
ret := sbom.Artifacts{
FileMetadata: make(map[file.Coordinates]file.Metadata),
FileDigests: make(map[file.Coordinates][]file.Digest),
FileContents: make(map[file.Coordinates]string),
FileLicenses: make(map[file.Coordinates][]file.License),
}
for _, f := range files {
@@ -100,6 +103,27 @@ func toSyftFiles(files []model.File) sbom.Artifacts {
Value: d.Value,
})
}
if f.Contents != "" {
ret.FileContents[coord] = f.Contents
}
for _, l := range f.Licenses {
var evidence *file.LicenseEvidence
if e := l.Evidence; e != nil {
evidence = &file.LicenseEvidence{
Confidence: e.Confidence,
Offset: e.Offset,
Extent: e.Extent,
}
}
ret.FileLicenses[coord] = append(ret.FileLicenses[coord], file.License{
Value: l.Value,
SPDXExpression: l.SPDXExpression,
Type: l.Type,
LicenseEvidence: evidence,
})
}
}
return ret
@@ -111,7 +135,7 @@ func toSyftLicenses(m []model.License) (p []pkg.License) {
Value: l.Value,
SPDXExpression: l.SPDXExpression,
Type: l.Type,
URLs: internal.NewStringSet(l.URLs...),
URLs: l.URLs,
Locations: file.NewLocationSet(l.Locations...),
})
}
@@ -312,6 +312,8 @@ func Test_toSyftFiles(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.want.FileContents = make(map[file.Coordinates]string)
tt.want.FileLicenses = make(map[file.Coordinates][]file.License)
assert.Equal(t, tt.want, toSyftFiles(tt.files))
})
}
@@ -1,9 +1,7 @@
package fileresolver
import (
"fmt"
"io"
"runtime"
"sort"
"testing"
@@ -523,11 +521,6 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) {
func TestAllLayersResolver_AllLocations(t *testing.T) {
img := imagetest.GetFixtureImage(t, "docker-archive", "image-files-deleted")
arch := "x86_64"
if runtime.GOARCH == "arm64" {
arch = "aarch64"
}
resolver, err := NewFromContainerImageAllLayers(img)
assert.NoError(t, err)
@@ -638,9 +631,9 @@ func TestAllLayersResolver_AllLocations(t *testing.T) {
"/lib/apk/db/triggers",
"/lib/apk/exec",
"/lib/firmware",
fmt.Sprintf("/lib/ld-musl-%s.so.1", arch),
"/lib/ld-musl-x86_64.so.1",
"/lib/libapk.so.3.12.0",
fmt.Sprintf("/lib/libc.musl-%s.so.1", arch),
"/lib/libc.musl-x86_64.so.1",
"/lib/libcrypto.so.3",
"/lib/libssl.so.3",
"/lib/libz.so.1",
@@ -1,4 +1,4 @@
FROM alpine:3.17.1 as tools
FROM alpine:3.17.1@sha256:93d5a28ff72d288d69b5997b8ba47396d2cbb62a72b5d87cd3351094b5d578a0 as tools
FROM scratch
COPY --from=tools /bin /bin
COPY --from=tools /lib /lib
@@ -6,6 +6,7 @@ import (
"io/fs"
"os"
"path"
"slices"
"sort"
"strings"
"time"
@@ -13,7 +14,6 @@ import (
"github.com/bmatcuk/doublestar/v4"
"github.com/mitchellh/go-homedir"
"github.com/spf13/afero"
"golang.org/x/exp/slices"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/file"
+7 -7
View File
@@ -4,8 +4,8 @@ import (
"sync"
"github.com/jinzhu/copier"
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
)
@@ -124,13 +124,13 @@ func (c *Collection) addTypeToIndex(p Package) {
}
func (c *Collection) addPathsToIndex(p Package) {
observedPaths := internal.NewStringSet()
observedPaths := strset.New()
for _, l := range p.Locations.ToSlice() {
if l.RealPath != "" && !observedPaths.Contains(l.RealPath) {
if l.RealPath != "" && !observedPaths.Has(l.RealPath) {
c.addPathToIndex(p.id, l.RealPath)
observedPaths.Add(l.RealPath)
}
if l.VirtualPath != "" && l.RealPath != l.VirtualPath && !observedPaths.Contains(l.VirtualPath) {
if l.VirtualPath != "" && l.RealPath != l.VirtualPath && !observedPaths.Has(l.VirtualPath) {
c.addPathToIndex(p.id, l.VirtualPath)
observedPaths.Add(l.VirtualPath)
}
@@ -173,13 +173,13 @@ func (c *Collection) deleteTypeFromIndex(p Package) {
}
func (c *Collection) deletePathsFromIndex(p Package) {
observedPaths := internal.NewStringSet()
observedPaths := strset.New()
for _, l := range p.Locations.ToSlice() {
if l.RealPath != "" && !observedPaths.Contains(l.RealPath) {
if l.RealPath != "" && !observedPaths.Has(l.RealPath) {
c.deletePathFromIndex(p.id, l.RealPath)
observedPaths.Add(l.RealPath)
}
if l.VirtualPath != "" && l.RealPath != l.VirtualPath && !observedPaths.Contains(l.VirtualPath) {
if l.VirtualPath != "" && l.RealPath != l.VirtualPath && !observedPaths.Has(l.VirtualPath) {
c.deletePathFromIndex(p.id, l.VirtualPath)
observedPaths.Add(l.VirtualPath)
}
@@ -1 +1 @@
FROM busybox:1.35
FROM busybox:1.35@sha256:7ae8447f3a7f5bccaa765926f25fc038e425cf1b2be6748727bbea9a13102094
+5
View File
@@ -19,6 +19,7 @@ import (
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
"github.com/anchore/syft/syft/pkg/cataloger/elixir"
"github.com/anchore/syft/syft/pkg/cataloger/erlang"
"github.com/anchore/syft/syft/pkg/cataloger/githubactions"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
"github.com/anchore/syft/syft/pkg/cataloger/haskell"
"github.com/anchore/syft/syft/pkg/cataloger/java"
@@ -74,6 +75,8 @@ func DirectoryCatalogers(cfg Config) []pkg.Cataloger {
dotnet.NewDotnetPortableExecutableCataloger(),
elixir.NewMixLockCataloger(),
erlang.NewRebarLockCataloger(),
githubactions.NewActionUsageCataloger(),
githubactions.NewWorkflowUsageCataloger(),
golang.NewGoModFileCataloger(cfg.Golang),
golang.NewGoModuleBinaryCataloger(cfg.Golang),
haskell.NewHackageCataloger(),
@@ -110,6 +113,8 @@ func AllCatalogers(cfg Config) []pkg.Cataloger {
dotnet.NewDotnetPortableExecutableCataloger(),
elixir.NewMixLockCataloger(),
erlang.NewRebarLockCataloger(),
githubactions.NewActionUsageCataloger(),
githubactions.NewWorkflowUsageCataloger(),
golang.NewGoModFileCataloger(cfg.Golang),
golang.NewGoModuleBinaryCataloger(cfg.Golang),
haskell.NewHackageCataloger(),
@@ -7,10 +7,10 @@ import (
"fmt"
"io"
"log"
"slices"
"strings"
"github.com/facebookincubator/nvdtools/wfn"
"golang.org/x/exp/slices"
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe/dictionary"
)
+2 -3
View File
@@ -13,7 +13,6 @@ import (
"github.com/facebookincubator/nvdtools/wfn"
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/pkg"
@@ -118,13 +117,13 @@ func Generate(p pkg.Package) []cpe.CPE {
return nil
}
keys := internal.NewStringSet()
keys := strset.New()
cpes := make([]cpe.CPE, 0)
for _, product := range products {
for _, vendor := range vendors {
// prevent duplicate entries...
key := fmt.Sprintf("%s|%s|%s", product, vendor, p.Version)
if keys.Contains(key) {
if keys.Has(key) {
continue
}
keys.Add(key)
+2
View File
@@ -1,6 +1,7 @@
package cpe
import (
"sort"
"strings"
"github.com/scylladb/go-set/strset"
@@ -287,6 +288,7 @@ func GetManifestFieldGroupIDs(manifest *pkg.JavaManifest, fields []string) (grou
}
}
}
sort.Strings(groupIDs)
return groupIDs
}
@@ -37,6 +37,7 @@ var DefaultArtifactIDToGroupID = map[string]string{
"ant-weblogic": "org.apache.ant",
"ant-xz": "org.apache.ant",
"commons-codec": "commons-codec",
"commons-logging": "commons-logging", // see e.g. https://mvnrepository.com/artifact/commons-logging/commons-logging/1.1.1
"okhttp": "com.squareup.okhttp3",
"okio": "com.squareup.okio",
"spring": "org.springframework",
+36 -7
View File
@@ -36,12 +36,24 @@ func parseConanlock(_ file.Resolver, _ *generic.Environment, reader file.Locatio
if err := json.NewDecoder(reader).Decode(&cl); err != nil {
return nil, nil, err
}
for _, node := range cl.GraphLock.Nodes {
// requires is a list of package indices. We first need to fill it, and then we can resolve the package
// in a second iteration
var indexToPkgMap = map[string]pkg.Package{}
// we do not want to store the index list requires in the conan metadata, because it is not useful to have it in
// the SBOM. Instead, we will store it in a map and then use it to build the relationships
// maps pkg.ID to a list of indices
var parsedPkgRequires = map[artifact.ID][]string{}
for idx, node := range cl.GraphLock.Nodes {
metadata := pkg.ConanLockMetadata{
Ref: node.Ref,
Options: parseOptions(node.Options),
Path: node.Path,
Context: node.Context,
Ref: node.Ref,
Options: parseOptions(node.Options),
Path: node.Path,
Context: node.Context,
PackageID: node.PackageID,
Prev: node.Prev,
}
p := newConanlockPackage(
@@ -50,11 +62,28 @@ func parseConanlock(_ file.Resolver, _ *generic.Environment, reader file.Locatio
)
if p != nil {
pkgs = append(pkgs, *p)
pk := *p
pkgs = append(pkgs, pk)
parsedPkgRequires[pk.ID()] = node.Requires
indexToPkgMap[idx] = pk
}
}
return pkgs, nil, nil
var relationships []artifact.Relationship
for _, p := range pkgs {
requires := parsedPkgRequires[p.ID()]
for _, r := range requires {
// this is a pkg that package "p" depends on... make a relationship
relationships = append(relationships, artifact.Relationship{
From: indexToPkgMap[r],
To: p,
Type: artifact.DependencyOfRelationship,
})
}
}
return pkgs, relationships, nil
}
func parseOptions(options string) map[string]string {
+273 -28
View File
@@ -13,56 +13,301 @@ func TestParseConanlock(t *testing.T) {
fixture := "test-fixtures/conan.lock"
expected := []pkg.Package{
{
Name: "spdlog",
Version: "1.11.0",
PURL: "pkg:conan/spdlog@1.11.0",
Name: "mfast",
Version: "1.2.2",
PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "spdlog/1.11.0",
Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39",
Options: map[string]string{
"fPIC": "True",
"header_only": "False",
"no_exceptions": "False",
"shared": "False",
"wchar_filenames": "False",
"wchar_support": "False",
"fmt:fPIC": "True",
"fmt:header_only": "False",
"fmt:shared": "False",
"fmt:with_fmt_alias": "False",
"fmt:with_os_api": "True",
"fPIC": "True",
"shared": "False",
"with_sqlite3": "False",
"boost:addr2line_location": "/usr/bin/addr2line",
"boost:asio_no_deprecated": "False",
"boost:buildid": "None",
"boost:bzip2": "True",
"boost:debug_level": "0",
"boost:diagnostic_definitions": "False",
"boost:error_code_header_only": "False",
"boost:extra_b2_flags": "None",
"boost:fPIC": "True",
"boost:filesystem_no_deprecated": "False",
"boost:header_only": "False",
"boost:i18n_backend": "deprecated",
"boost:i18n_backend_iconv": "libc",
"boost:i18n_backend_icu": "False",
"boost:layout": "system",
"boost:lzma": "False",
"boost:magic_autolink": "False",
"boost:multithreading": "True",
"boost:namespace": "boost",
"boost:namespace_alias": "False",
"boost:numa": "True",
"boost:pch": "True",
"boost:python_executable": "None",
"boost:python_version": "None",
"boost:segmented_stacks": "False",
"boost:shared": "False",
"boost:system_no_deprecated": "False",
"boost:system_use_utf8": "False",
"boost:visibility": "hidden",
"boost:with_stacktrace_backtrace": "True",
"boost:without_atomic": "False",
"boost:without_chrono": "False",
"boost:without_container": "False",
"boost:without_context": "False",
"boost:without_contract": "False",
"boost:without_coroutine": "False",
"boost:without_date_time": "False",
"boost:without_exception": "False",
"boost:without_fiber": "False",
"boost:without_filesystem": "False",
"boost:without_graph": "False",
"boost:without_graph_parallel": "True",
"boost:without_iostreams": "False",
"boost:without_json": "False",
"boost:without_locale": "False",
"boost:without_log": "False",
"boost:without_math": "False",
"boost:without_mpi": "True",
"boost:without_nowide": "False",
"boost:without_program_options": "False",
"boost:without_python": "True",
"boost:without_random": "False",
"boost:without_regex": "False",
"boost:without_serialization": "False",
"boost:without_stacktrace": "False",
"boost:without_system": "False",
"boost:without_test": "False",
"boost:without_thread": "False",
"boost:without_timer": "False",
"boost:without_type_erasure": "False",
"boost:without_wave": "False",
"boost:zlib": "True",
"boost:zstd": "False",
"bzip2:build_executable": "True",
"bzip2:fPIC": "True",
"bzip2:shared": "False",
"libbacktrace:fPIC": "True",
"libbacktrace:shared": "False",
"tinyxml2:fPIC": "True",
"tinyxml2:shared": "False",
"zlib:fPIC": "True",
"zlib:shared": "False",
},
Path: "conanfile.py",
Context: "host",
Context: "host",
PackageID: "9d1f076b471417647c2022a78d5e2c1f834289ac",
Prev: "0ca9799450422cc55a92ccc6ffd57fba",
},
},
{
Name: "fmt",
Version: "9.1.0",
PURL: "pkg:conan/my_user/fmt@9.1.0?channel=my_channel",
Name: "boost",
Version: "1.75.0",
PURL: "pkg:conan/boost@1.75.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "fmt/9.1.0@my_user/my_channel#6708c9d84f98d56a6d9f2e6c2d5639ba",
Ref: "boost/1.75.0#a9c318f067216f900900e044e7af4ab1",
Options: map[string]string{
"fPIC": "True",
"header_only": "False",
"shared": "False",
"with_fmt_alias": "False",
"with_os_api": "True",
"addr2line_location": "/usr/bin/addr2line",
"asio_no_deprecated": "False",
"buildid": "None",
"bzip2": "True",
"debug_level": "0",
"diagnostic_definitions": "False",
"error_code_header_only": "False",
"extra_b2_flags": "None",
"fPIC": "True",
"filesystem_no_deprecated": "False",
"header_only": "False",
"i18n_backend": "deprecated",
"i18n_backend_iconv": "libc",
"i18n_backend_icu": "False",
"layout": "system",
"lzma": "False",
"magic_autolink": "False",
"multithreading": "True",
"namespace": "boost",
"namespace_alias": "False",
"numa": "True",
"pch": "True",
"python_executable": "None",
"python_version": "None",
"segmented_stacks": "False",
"shared": "False",
"system_no_deprecated": "False",
"system_use_utf8": "False",
"visibility": "hidden",
"with_stacktrace_backtrace": "True",
"without_atomic": "False",
"without_chrono": "False",
"without_container": "False",
"without_context": "False",
"without_contract": "False",
"without_coroutine": "False",
"without_date_time": "False",
"without_exception": "False",
"without_fiber": "False",
"without_filesystem": "False",
"without_graph": "False",
"without_graph_parallel": "True",
"without_iostreams": "False",
"without_json": "False",
"without_locale": "False",
"without_log": "False",
"without_math": "False",
"without_mpi": "True",
"without_nowide": "False",
"without_program_options": "False",
"without_python": "True",
"without_random": "False",
"without_regex": "False",
"without_serialization": "False",
"without_stacktrace": "False",
"without_system": "False",
"without_test": "False",
"without_thread": "False",
"without_timer": "False",
"without_type_erasure": "False",
"without_wave": "False",
"zlib": "True",
"zstd": "False",
"bzip2:build_executable": "True",
"bzip2:fPIC": "True",
"bzip2:shared": "False",
"libbacktrace:fPIC": "True",
"libbacktrace:shared": "False",
"zlib:fPIC": "True",
"zlib:shared": "False",
},
Context: "host",
PackageID: "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978",
Prev: "b9d7912e6131dfa453c725593b36c808",
},
},
{
Name: "zlib",
Version: "1.2.12",
PURL: "pkg:conan/zlib@1.2.12",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a",
Options: map[string]string{
"fPIC": "True",
"shared": "False",
},
Context: "host",
PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646",
Prev: "7cd359d44f89ab08e33b5db75605002c",
},
},
{
Name: "bzip2",
Version: "1.0.8",
PURL: "pkg:conan/bzip2@1.0.8",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef",
Options: map[string]string{
"build_executable": "True",
"fPIC": "True",
"shared": "False",
},
Context: "host",
PackageID: "c32092bf4d4bb47cf962af898e02823f499b017e",
Prev: "b746948bc999d6f17f52a1f76e729e80",
},
},
{
Name: "libbacktrace",
Version: "cci.20210118",
PURL: "pkg:conan/libbacktrace@cci.20210118",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab",
Options: map[string]string{
"fPIC": "True",
"shared": "False",
},
Context: "host",
PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646",
Prev: "98a976f017e894c27e9a158b807ec0c7",
},
},
{
Name: "tinyxml2",
Version: "9.0.0",
PURL: "pkg:conan/tinyxml2@9.0.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1",
Options: map[string]string{
"fPIC": "True",
"shared": "False",
},
Context: "host",
// intentionally remove to test missing PackageID and Prev
// PackageID: "6557f18ca99c0b6a233f43db00e30efaa525e27e",
// Prev: "548bb273d2980991baa519453d68e5cd",
},
},
}
// TODO: relationships are not under test
var expectedRelationships []artifact.Relationship
// relationships require IDs to be set to be sorted similarly
for i := range expected {
expected[i].SetID()
}
var expectedRelationships = []artifact.Relationship{
{
From: expected[1], // boost
To: expected[0], // mfast
Type: artifact.DependencyOfRelationship,
Data: nil,
},
{
From: expected[5], // tinyxml2
To: expected[0], // mfast
Type: artifact.DependencyOfRelationship,
Data: nil,
},
{
From: expected[2], // zlib
To: expected[1], // boost
Type: artifact.DependencyOfRelationship,
Data: nil,
},
{
From: expected[3], // bzip2
To: expected[1], // boost
Type: artifact.DependencyOfRelationship,
Data: nil,
},
{
From: expected[4], // libbacktrace
To: expected[1], // boost
Type: artifact.DependencyOfRelationship,
Data: nil,
},
}
pkgtest.TestFileParser(t, fixture, parseConanlock, expected, expectedRelationships)
}
@@ -0,0 +1,17 @@
# Conan test data
This folder contains the test data for the Conan package manager.
## conan.lock
The conan lock file is created in the following way.
We explicitly use a package which has dependencies, which in turn also have dependendencies.
This is necessary to verify that the dependency tree is properly parsed.
1. Use `conan lock create --reference "mfast/1.2.2#c6f6387c9b99780f0ee05e25f99d0f39"`
2. Manually modify the user and channel of mfast package, to be able to test that it is properly set in SBOM:
`sed -i 's|mfast/1.2.2#c6f6387c9b99780f0ee05e25f99d0f39|mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39|g' conan.lock`
3. Manually delete the package id and prev from tinyxml2 entry to test conan lock parsing if they are missing:
`sed -i 's|\"package_id\": \"6557f18ca99c0b6a233f43db00e30efaa525e27e\",||g' conan.lock`
`sed -i 's|\"prev\": \"548bb273d2980991baa519453d68e5cd\",||g' conan.lock`
+45 -10
View File
@@ -1,20 +1,55 @@
{
"graph_lock": {
"nodes": {
"0": {
"ref": "spdlog/1.11.0",
"options": "fPIC=True\nheader_only=False\nno_exceptions=False\nshared=False\nwchar_filenames=False\nwchar_support=False\nfmt:fPIC=True\nfmt:header_only=False\nfmt:shared=False\nfmt:with_fmt_alias=False\nfmt:with_os_api=True",
"1": {
"ref": "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39",
"options": "fPIC=True\nshared=False\nwith_sqlite3=False\nboost:addr2line_location=/usr/bin/addr2line\nboost:asio_no_deprecated=False\nboost:buildid=None\nboost:bzip2=True\nboost:debug_level=0\nboost:diagnostic_definitions=False\nboost:error_code_header_only=False\nboost:extra_b2_flags=None\nboost:fPIC=True\nboost:filesystem_no_deprecated=False\nboost:header_only=False\nboost:i18n_backend=deprecated\nboost:i18n_backend_iconv=libc\nboost:i18n_backend_icu=False\nboost:layout=system\nboost:lzma=False\nboost:magic_autolink=False\nboost:multithreading=True\nboost:namespace=boost\nboost:namespace_alias=False\nboost:numa=True\nboost:pch=True\nboost:python_executable=None\nboost:python_version=None\nboost:segmented_stacks=False\nboost:shared=False\nboost:system_no_deprecated=False\nboost:system_use_utf8=False\nboost:visibility=hidden\nboost:with_stacktrace_backtrace=True\nboost:without_atomic=False\nboost:without_chrono=False\nboost:without_container=False\nboost:without_context=False\nboost:without_contract=False\nboost:without_coroutine=False\nboost:without_date_time=False\nboost:without_exception=False\nboost:without_fiber=False\nboost:without_filesystem=False\nboost:without_graph=False\nboost:without_graph_parallel=True\nboost:without_iostreams=False\nboost:without_json=False\nboost:without_locale=False\nboost:without_log=False\nboost:without_math=False\nboost:without_mpi=True\nboost:without_nowide=False\nboost:without_program_options=False\nboost:without_python=True\nboost:without_random=False\nboost:without_regex=False\nboost:without_serialization=False\nboost:without_stacktrace=False\nboost:without_system=False\nboost:without_test=False\nboost:without_thread=False\nboost:without_timer=False\nboost:without_type_erasure=False\nboost:without_wave=False\nboost:zlib=True\nboost:zstd=False\nbzip2:build_executable=True\nbzip2:fPIC=True\nbzip2:shared=False\nlibbacktrace:fPIC=True\nlibbacktrace:shared=False\ntinyxml2:fPIC=True\ntinyxml2:shared=False\nzlib:fPIC=True\nzlib:shared=False",
"package_id": "9d1f076b471417647c2022a78d5e2c1f834289ac",
"prev": "0ca9799450422cc55a92ccc6ffd57fba",
"requires": [
"1"
"2",
"6"
],
"path": "conanfile.py",
"context": "host"
},
"1": {
"ref": "fmt/9.1.0@my_user/my_channel#6708c9d84f98d56a6d9f2e6c2d5639ba",
"options": "fPIC=True\nheader_only=False\nshared=False\nwith_fmt_alias=False\nwith_os_api=True",
"package_id": "2c09c8f84c016041549fcee94e4caae5d89424b6",
"prev": "9f5ab13fc7c73e4a9f87e4e213f2cfa4",
"2": {
"ref": "boost/1.75.0#a9c318f067216f900900e044e7af4ab1",
"options": "addr2line_location=/usr/bin/addr2line\nasio_no_deprecated=False\nbuildid=None\nbzip2=True\ndebug_level=0\ndiagnostic_definitions=False\nerror_code_header_only=False\nextra_b2_flags=None\nfPIC=True\nfilesystem_no_deprecated=False\nheader_only=False\ni18n_backend=deprecated\ni18n_backend_iconv=libc\ni18n_backend_icu=False\nlayout=system\nlzma=False\nmagic_autolink=False\nmultithreading=True\nnamespace=boost\nnamespace_alias=False\nnuma=True\npch=True\npython_executable=None\npython_version=None\nsegmented_stacks=False\nshared=False\nsystem_no_deprecated=False\nsystem_use_utf8=False\nvisibility=hidden\nwith_stacktrace_backtrace=True\nwithout_atomic=False\nwithout_chrono=False\nwithout_container=False\nwithout_context=False\nwithout_contract=False\nwithout_coroutine=False\nwithout_date_time=False\nwithout_exception=False\nwithout_fiber=False\nwithout_filesystem=False\nwithout_graph=False\nwithout_graph_parallel=True\nwithout_iostreams=False\nwithout_json=False\nwithout_locale=False\nwithout_log=False\nwithout_math=False\nwithout_mpi=True\nwithout_nowide=False\nwithout_program_options=False\nwithout_python=True\nwithout_random=False\nwithout_regex=False\nwithout_serialization=False\nwithout_stacktrace=False\nwithout_system=False\nwithout_test=False\nwithout_thread=False\nwithout_timer=False\nwithout_type_erasure=False\nwithout_wave=False\nzlib=True\nzstd=False\nbzip2:build_executable=True\nbzip2:fPIC=True\nbzip2:shared=False\nlibbacktrace:fPIC=True\nlibbacktrace:shared=False\nzlib:fPIC=True\nzlib:shared=False",
"package_id": "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978",
"prev": "b9d7912e6131dfa453c725593b36c808",
"requires": [
"3",
"4",
"5"
],
"context": "host"
},
"3": {
"ref": "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a",
"options": "fPIC=True\nshared=False",
"package_id": "dfbe50feef7f3c6223a476cd5aeadb687084a646",
"prev": "7cd359d44f89ab08e33b5db75605002c",
"context": "host"
},
"4": {
"ref": "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef",
"options": "build_executable=True\nfPIC=True\nshared=False",
"package_id": "c32092bf4d4bb47cf962af898e02823f499b017e",
"prev": "b746948bc999d6f17f52a1f76e729e80",
"context": "host"
},
"5": {
"ref": "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab",
"options": "fPIC=True\nshared=False",
"package_id": "dfbe50feef7f3c6223a476cd5aeadb687084a646",
"prev": "98a976f017e894c27e9a158b807ec0c7",
"context": "host"
},
"6": {
"ref": "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1",
"options": "fPIC=True\nshared=False",
"context": "host"
}
},
+6
View File
@@ -44,6 +44,11 @@ func TestDpkgCataloger(t *testing.T) {
Contains configuration files and directories required for
authentication to work on Debian systems. This package is required
on almost all installations.`,
Depends: []string{
"debconf (>= 0.5) | debconf-2.0",
"debconf (>= 1.5.19) | cdebconf",
"libpam-modules (>= 1.0.1-6)",
},
Files: []pkg.DpkgFileRecord{
{
Path: "/etc/pam.conf",
@@ -112,6 +117,7 @@ func TestDpkgCataloger(t *testing.T) {
SQLite is a C library that implements an SQL database engine.
Programs that link with the SQLite library can have SQL database
access without running a separate RDBMS process.`,
Depends: []string{"libc6 (>= 2.29)"},
Files: []pkg.DpkgFileRecord{
{Path: "/usr/lib/aarch64-linux-gnu/libsqlite3.so.0.8.6", Digest: &file.Digest{
Algorithm: "md5",
+8 -6
View File
@@ -36,13 +36,15 @@ func newDpkgPackage(d pkg.DpkgMetadata, dbLocation file.Location, resolver file.
Metadata: d,
}
// the current entry only has what may have been listed in the status file, however, there are additional
// files that are listed in multiple other locations. We should retrieve them all and merge the file lists
// together.
mergeFileListing(resolver, dbLocation, &p)
if resolver != nil {
// the current entry only has what may have been listed in the status file, however, there are additional
// files that are listed in multiple other locations. We should retrieve them all and merge the file lists
// together.
mergeFileListing(resolver, dbLocation, &p)
// fetch additional data from the copyright file to derive the license information
addLicenses(resolver, dbLocation, &p)
// fetch additional data from the copyright file to derive the license information
addLicenses(resolver, dbLocation, &p)
}
p.SetID()
+4 -2
View File
@@ -7,6 +7,8 @@ import (
"sort"
"strings"
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/internal"
)
@@ -18,7 +20,7 @@ var (
)
func parseLicensesFromCopyright(reader io.Reader) []string {
findings := internal.NewStringSet()
findings := strset.New()
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
@@ -31,7 +33,7 @@ func parseLicensesFromCopyright(reader io.Reader) []string {
}
}
results := findings.ToSlice()
results := findings.List()
sort.Strings(results)
+124 -7
View File
@@ -35,7 +35,7 @@ func parseDpkgDB(resolver file.Resolver, env *generic.Environment, reader file.L
pkgs = append(pkgs, newDpkgPackage(m, reader.Location, resolver, env.LinuxRelease))
}
return pkgs, nil, nil
return pkgs, associateRelationships(pkgs), nil
}
// parseDpkgStatus is a parser function for Debian DB status contents, returning all Debian packages listed.
@@ -63,6 +63,22 @@ func parseDpkgStatus(reader io.Reader) ([]pkg.DpkgMetadata, error) {
return metadata, nil
}
// dpkgExtractedMetadata is an adapter struct to capture the fields from the dpkg status file, however, the final
// pkg.DpkgMetadata struct has different types for some fields (e.g. Provides, Depends, and PreDepends is []string, not a string).
type dpkgExtractedMetadata struct {
Package string `mapstructure:"Package"`
Source string `mapstructure:"Source"`
Version string `mapstructure:"Version"`
SourceVersion string `mapstructure:"SourceVersion"`
Architecture string `mapstructure:"Architecture"`
Maintainer string `mapstructure:"Maintainer"`
InstalledSize int `mapstructure:"InstalledSize"`
Description string `mapstructure:"Description"`
Provides string `mapstructure:"Provides"`
Depends string `mapstructure:"Depends"`
PreDepends string `mapstructure:"PreDepends"` // note: original doc is Pre-Depends
}
// parseDpkgStatusEntry returns an individual Dpkg entry, or returns errEndOfPackages if there are no more packages to parse from the reader.
func parseDpkgStatusEntry(reader *bufio.Reader) (*pkg.DpkgMetadata, error) {
var retErr error
@@ -77,22 +93,36 @@ func parseDpkgStatusEntry(reader *bufio.Reader) (*pkg.DpkgMetadata, error) {
retErr = err
}
entry := pkg.DpkgMetadata{}
err = mapstructure.Decode(dpkgFields, &entry)
raw := dpkgExtractedMetadata{}
err = mapstructure.Decode(dpkgFields, &raw)
if err != nil {
return nil, err
}
sourceName, sourceVersion := extractSourceVersion(entry.Source)
sourceName, sourceVersion := extractSourceVersion(raw.Source)
if sourceVersion != "" {
entry.SourceVersion = sourceVersion
entry.Source = sourceName
raw.SourceVersion = sourceVersion
raw.Source = sourceName
}
if entry.Package == "" {
if raw.Package == "" {
return nil, retErr
}
entry := pkg.DpkgMetadata{
Package: raw.Package,
Source: raw.Source,
Version: raw.Version,
SourceVersion: raw.SourceVersion,
Architecture: raw.Architecture,
Maintainer: raw.Maintainer,
InstalledSize: raw.InstalledSize,
Description: raw.Description,
Provides: splitPkgList(raw.Provides),
Depends: splitPkgList(raw.Depends),
PreDepends: splitPkgList(raw.PreDepends),
}
// there may be an optional conffiles section that we should persist as files
if conffilesSection, exists := dpkgFields["Conffiles"]; exists && conffilesSection != nil {
if sectionStr, ok := conffilesSection.(string); ok {
@@ -108,6 +138,17 @@ func parseDpkgStatusEntry(reader *bufio.Reader) (*pkg.DpkgMetadata, error) {
return &entry, retErr
}
func splitPkgList(pkgList string) (ret []string) {
fields := strings.Split(pkgList, ",")
for _, field := range fields {
field = strings.TrimSpace(field)
if field != "" {
ret = append(ret, field)
}
}
return ret
}
func extractAllFields(reader *bufio.Reader) (map[string]interface{}, error) {
dpkgFields := make(map[string]interface{})
var key string
@@ -195,3 +236,79 @@ func handleNewKeyValue(line string) (key string, val interface{}, err error) {
return "", nil, fmt.Errorf("cannot parse field from line: '%s'", line)
}
// associateRelationships will create relationships between packages based on the "Depends", "Pre-Depends", and "Provides"
// fields for installed packages. if there is an installed package that has a dependency that is (somehow) not installed,
// then that relationship (between the installed and uninstalled package) will NOT be created.
func associateRelationships(pkgs []pkg.Package) (relationships []artifact.Relationship) {
// map["provides" + "package"] -> packages that provide that package
lookup := make(map[string][]pkg.Package)
// read provided and add as keys for lookup keys as well as package names
for _, p := range pkgs {
meta, ok := p.Metadata.(pkg.DpkgMetadata)
if !ok {
log.Warnf("cataloger failed to extract dpkg 'provides' metadata for package %+v", p.Name)
continue
}
lookup[p.Name] = append(lookup[p.Name], p)
for _, provides := range meta.Provides {
k := stripVersionSpecifier(provides)
lookup[k] = append(lookup[k], p)
}
}
// read "Depends" and "Pre-Depends" and match with keys
for _, p := range pkgs {
meta, ok := p.Metadata.(pkg.DpkgMetadata)
if !ok {
log.Warnf("cataloger failed to extract dpkg 'dependency' metadata for package %+v", p.Name)
continue
}
var allDeps []string
allDeps = append(allDeps, meta.Depends...)
allDeps = append(allDeps, meta.PreDepends...)
for _, depSpecifier := range allDeps {
deps := splitPackageChoice(depSpecifier)
for _, dep := range deps {
for _, depPkg := range lookup[dep] {
relationships = append(relationships, artifact.Relationship{
From: depPkg,
To: p,
Type: artifact.DependencyOfRelationship,
})
}
}
}
}
return relationships
}
func stripVersionSpecifier(s string) string {
// examples:
// libgmp10 (>= 2:6.2.1+dfsg1) --> libgmp10
// libgmp10 --> libgmp10
// foo [i386] --> foo
// default-mta | mail-transport-agent --> default-mta | mail-transport-agent
// kernel-headers-2.2.10 [!hurd-i386] --> kernel-headers-2.2.10
items := internal.SplitAny(s, "[(<>=")
if len(items) == 0 {
return s
}
return strings.TrimSpace(items[0])
}
func splitPackageChoice(s string) (ret []string) {
fields := strings.Split(s, "|")
for _, field := range fields {
field = strings.TrimSpace(field)
if field != "" {
ret = append(ret, stripVersionSpecifier(field))
}
}
return ret
}
+156 -1
View File
@@ -11,9 +11,11 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/linux"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/generic"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
)
@@ -48,6 +50,18 @@ func Test_parseDpkgStatus(t *testing.T) {
* apt-cdrom to use removable media as a source for packages
* apt-config as an interface to the configuration settings
* apt-key as an interface to manage authentication keys`,
Provides: []string{"apt-transport-https (= 1.8.2)"},
Depends: []string{
"adduser",
"gpgv | gpgv2 | gpgv1",
"debian-archive-keyring",
"libapt-pkg5.0 (>= 1.7.0~alpha3~)",
"libc6 (>= 2.15)",
"libgcc1 (>= 1:3.0)",
"libgnutls30 (>= 3.6.6)",
"libseccomp2 (>= 1.0.1)",
"libstdc++6 (>= 5.2)",
},
Files: []pkg.DpkgFileRecord{
{
Path: "/etc/apt/apt.conf.d/01autoremove",
@@ -110,6 +124,18 @@ func Test_parseDpkgStatus(t *testing.T) {
* apt-cdrom to use removable media as a source for packages
* apt-config as an interface to the configuration settings
* apt-key as an interface to manage authentication keys`,
Provides: []string{"apt-transport-https (= 1.8.2)"},
Depends: []string{
"adduser",
"gpgv | gpgv2 | gpgv1",
"debian-archive-keyring",
"libapt-pkg5.0 (>= 1.7.0~alpha3~)",
"libc6 (>= 2.15)",
"libgcc1 (>= 1:3.0)",
"libgnutls30 (>= 3.6.6)",
"libseccomp2 (>= 1.0.1)",
"libstdc++6 (>= 5.2)",
},
Files: []pkg.DpkgFileRecord{},
},
},
@@ -135,7 +161,9 @@ func Test_parseDpkgStatus(t *testing.T) {
globe. It is updated periodically to reflect changes made by
political bodies to time zone boundaries, UTC offsets, and
daylight-saving rules.`,
Files: []pkg.DpkgFileRecord{},
Provides: []string{"tzdata-buster"},
Depends: []string{"debconf (>= 0.5) | debconf-2.0"},
Files: []pkg.DpkgFileRecord{},
},
{
Package: "util-linux",
@@ -149,6 +177,14 @@ func Test_parseDpkgStatus(t *testing.T) {
important utilities included in this package allow you to view kernel
messages, create new filesystems, view block device information,
interface with real time clock, etc.`,
Depends: []string{"fdisk", "login (>= 1:4.5-1.1~)"},
PreDepends: []string{
"libaudit1 (>= 1:2.2.1)", "libblkid1 (>= 2.31.1)", "libc6 (>= 2.25)",
"libcap-ng0 (>= 0.7.9)", "libmount1 (>= 2.25)", "libpam0g (>= 0.99.7.1)",
"libselinux1 (>= 2.6-3~)", "libsmartcols1 (>= 2.33)", "libsystemd0",
"libtinfo6 (>= 6)", "libudev1 (>= 183)", "libuuid1 (>= 2.16)",
"zlib1g (>= 1:1.1.4)",
},
Files: []pkg.DpkgFileRecord{
{
Path: "/etc/default/hwclock",
@@ -397,3 +433,122 @@ func Test_handleNewKeyValue(t *testing.T) {
})
}
}
func Test_stripVersionSpecifier(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{
name: "package name only",
input: "test",
want: "test",
},
{
name: "with version",
input: "test (1.2.3)",
want: "test",
},
{
name: "multiple packages",
input: "test | other",
want: "test | other",
},
{
name: "with architecture specifiers",
input: "test [amd64 i386]",
want: "test",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, stripVersionSpecifier(tt.input))
})
}
}
func Test_associateRelationships(t *testing.T) {
tests := []struct {
name string
fixture string
wantRelationships map[string][]string
}{
{
name: "relationships for coreutils",
fixture: "test-fixtures/status/coreutils-relationships",
wantRelationships: map[string][]string{
"coreutils": {"libacl1", "libattr1", "libc6", "libgmp10", "libselinux1"},
"libacl1": {"libc6"},
"libattr1": {"libc6"},
"libc6": {"libgcc-s1"},
"libgcc-s1": {"gcc-12-base", "libc6"},
"libgmp10": {"libc6"},
"libpcre2-8-0": {"libc6"},
"libselinux1": {"libc6", "libpcre2-8-0"},
},
},
{
name: "relationships from dpkg example docs",
fixture: "test-fixtures/status/doc-examples",
wantRelationships: map[string][]string{
"made-up-package-1": {"kernel-headers-2.2.10", "hurd-dev", "gnumach-dev"},
"made-up-package-2": {"libluajit5.1-dev", "liblua5.1-dev"},
"made-up-package-3": {"foo", "bar"},
// note that the "made-up-package-4" depends on "made-up-package-5" but not via the direct
// package name, but through the "provides" virtual package name "virtual-package-5".
"made-up-package-4": {"made-up-package-5"},
// note that though there is a "default-mta | mail-transport-agent | not-installed"
// dependency choice we raise up the packages that are installed for every choice.
// In this case that means that "default-mta" and "mail-transport-agent".
"mutt": {"libc6", "default-mta", "mail-transport-agent"},
},
},
{
name: "relationships for libpam-runtime",
fixture: "test-fixtures/status/libpam-runtime",
wantRelationships: map[string][]string{
"libpam-runtime": {"debconf1", "debconf-2.0", "debconf2", "cdebconf", "libpam-modules"},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := os.Open(tt.fixture)
require.NoError(t, err)
reader := file.NewLocationReadCloser(file.NewLocation(tt.fixture), f)
pkgs, relationships, err := parseDpkgDB(nil, &generic.Environment{}, reader)
require.NotEmpty(t, pkgs)
require.NotEmpty(t, relationships)
require.NoError(t, err)
if d := cmp.Diff(tt.wantRelationships, abstractRelationships(t, relationships)); d != "" {
t.Errorf("unexpected relationships (-want +got):\n%s", d)
}
})
}
}
func abstractRelationships(t testing.TB, relationships []artifact.Relationship) map[string][]string {
t.Helper()
abstracted := make(map[string][]string)
for _, relationship := range relationships {
fromPkg, ok := relationship.From.(pkg.Package)
if !ok {
continue
}
toPkg, ok := relationship.To.(pkg.Package)
if !ok {
continue
}
// we build this backwards since we use DependencyOfRelationship instead of DependsOn
abstracted[toPkg.Name] = append(abstracted[toPkg.Name], fromPkg.Name)
}
return abstracted
}
@@ -0,0 +1,114 @@
Package: coreutils
Essential: yes
Status: install ok installed
Priority: required
Section: utils
Installed-Size: 20272
Maintainer: Michael Stone <mstone@debian.org>
Architecture: arm64
Multi-Arch: foreign
Version: 9.1-1
Pre-Depends: libacl1 (>= 2.2.23), libattr1 (>= 1:2.4.44), libc6 (>= 2.34), libgmp10 (>= 2:6.2.1+dfsg1), libselinux1 (>= 3.1~)
Package: libacl1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 101
Maintainer: Guillem Jover <guillem@debian.org>
Architecture: arm64
Multi-Arch: same
Source: acl
Version: 2.3.1-3
Depends: libc6 (>= 2.33)
Package: libc6
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 23127
Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
Architecture: arm64
Multi-Arch: same
Source: glibc
Version: 2.36-9+deb12u1
Depends: libgcc-s1
Recommends: libidn2-0 (>= 2.0.5~)
Suggests: glibc-doc, debconf | debconf-2.0, libc-l10n, locales, libnss-nis, libnss-nisplus
Breaks: aide (<< 0.17.3-4+b3), busybox (<< 1.30.1-6), chrony (<< 4.2-3~), fakechroot (<< 2.19-3.5), firefox (<< 91~), firefox-esr (<< 91~), gnumach-image-1.8-486 (<< 2:1.8+git20210923~), gnumach-image-1.8-486-dbg (<< 2:1.8+git20210923~), gnumach-image-1.8-xen-486 (<< 2:1.8+git20210923~), gnumach-image-1.8-xen-486-dbg (<< 2:1.8+git20210923~), hurd (<< 1:0.9.git20220301-2), ioquake3 (<< 1.36+u20200211.f2c61c1~dfsg-2~), iraf-fitsutil (<< 2018.07.06-4), libgegl-0.4-0 (<< 0.4.18), libtirpc1 (<< 0.2.3), locales (<< 2.36), locales-all (<< 2.36), macs (<< 2.2.7.1-3~), nocache (<< 1.1-1~), nscd (<< 2.36), openarena (<< 0.8.8+dfsg-4~), openssh-server (<< 1:8.1p1-5), python3-iptables (<< 1.0.0-2), r-cran-later (<< 0.7.5+dfsg-2), tinydns (<< 1:1.05-14), valgrind (<< 1:3.19.0-1~), wcc (<< 0.0.2+dfsg-3)
Package: libgcc-s1
Protected: yes
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 147
Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Architecture: arm64
Multi-Arch: same
Source: gcc-12
Version: 12.2.0-14
Replaces: libgcc1 (<< 1:10)
Provides: libgcc1 (= 1:12.2.0-14)
Depends: gcc-12-base (= 12.2.0-14), libc6 (>= 2.35)
Package: gcc-12-base
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 100
Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Architecture: arm64
Multi-Arch: same
Source: gcc-12
Version: 12.2.0-14
Breaks: gnat (<< 7)
Package: libattr1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 99
Maintainer: Guillem Jover <guillem@debian.org>
Architecture: arm64
Multi-Arch: same
Source: attr
Version: 1:2.5.1-4
Depends: libc6 (>= 2.17)
Package: libgmp10
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 855
Maintainer: Debian Science Team <debian-science-maintainers@lists.alioth.debian.org>
Architecture: arm64
Multi-Arch: same
Source: gmp
Version: 2:6.2.1+dfsg1-1.1
Depends: libc6 (>= 2.17)
Breaks: libmath-gmp-perl (<< 2.20-1), libmath-prime-util-gmp-perl (<< 0.51-2), postgresql-pgmp (<< 1.0.3-1)
Package: libselinux1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 223
Maintainer: Debian SELinux maintainers <selinux-devel@lists.alioth.debian.org>
Architecture: arm64
Multi-Arch: same
Source: libselinux (3.4-1)
Version: 3.4-1+b6
Depends: libc6 (>= 2.34), libpcre2-8-0 (>= 10.22)
Package: libpcre2-8-0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 649
Maintainer: Matthew Vernon <matthew@debian.org>
Architecture: arm64
Multi-Arch: same
Source: pcre2
Version: 10.42-1
Depends: libc6 (>= 2.34)
@@ -0,0 +1,46 @@
Package: mutt
Version: 1.3.17-1
Depends: libc6 (>= 2.2.1), default-mta | mail-transport-agent | not-installed
Package: made-up-package-1
Version: 1.0.0
Source: glibc
Depends: kernel-headers-2.2.10 [!hurd-i386],
hurd-dev [hurd-i386], gnumach-dev [hurd-i386]
Package: made-up-package-2
Version: 2.0.0
Depends:
libluajit5.1-dev [i386 amd64 kfreebsd-i386 armel armhf powerpc mips],
liblua5.1-dev [hurd-i386 ia64 kfreebsd-amd64 s390x sparc],
Package: made-up-package-3
Version: 3.0.0
Depends: foo [i386], bar [amd64]
Package: made-up-package-4
Version: 3.0.0
Depends: virtual-package-5
Package: made-up-package-5
Provides: virtual-package-5 (=1.0)
Package: foo
Package: bar
Package: kernel-headers-2.2.10
Package: hurd-dev
Package: gnumach-dev
Package: default-mta
Package: mail-transport-agent
Package: libc6
Package: libluajit5.1-dev
Package: liblua5.1-dev
@@ -0,0 +1,23 @@
Package: libpam-runtime
Status: install ok installed
Priority: required
Section: admin
Installed-Size: 876
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: all
Multi-Arch: foreign
Source: pam
Version: 1.5.2-6+deb12u1
Replaces: libpam0g-dev, libpam0g-util
Depends: debconf1 (>= 0.5) | debconf-2.0, debconf2 (>= 1.5.19) | cdebconf, libpam-modules (>= 1.0.1-6)
Conflicts: libpam0g-util
Package: debconf1
Package: debconf2
Package: debconf-2.0
Package: cdebconf
Package: libpam-modules
+24 -7
View File
@@ -1,6 +1,8 @@
package dotnet
import (
"fmt"
"regexp"
"strings"
"github.com/anchore/packageurl-go"
@@ -9,13 +11,7 @@ import (
)
func newDotnetDepsPackage(nameVersion string, lib dotnetDepsLibrary, locations ...file.Location) *pkg.Package {
if lib.Type != "package" {
return nil
}
fields := strings.Split(nameVersion, "/")
name := fields[0]
version := fields[1]
name, version := extractNameAndVersion(nameVersion)
m := pkg.DotnetDepsMetadata{
Name: name,
@@ -41,6 +37,27 @@ func newDotnetDepsPackage(nameVersion string, lib dotnetDepsLibrary, locations .
return p
}
func getDepsJSONFilePrefix(p string) string {
r := regexp.MustCompile(`([^\/]+)\.deps\.json$`)
match := r.FindStringSubmatch(p)
if len(match) > 1 {
return match[1]
}
return ""
}
func extractNameAndVersion(nameVersion string) (name, version string) {
fields := strings.Split(nameVersion, "/")
name = fields[0]
version = fields[1]
return
}
func createNameAndVersion(name, version string) (nameVersion string) {
nameVersion = fmt.Sprintf("%s/%s", name, version)
return
}
func packageURL(m pkg.DotnetDepsMetadata) string {
var qualifiers packageurl.Qualifiers
+75 -8
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"sort"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
@@ -13,8 +14,18 @@ import (
var _ generic.Parser = parseDotnetDeps
type dotnetRuntimeTarget struct {
Name string `json:"name"`
}
type dotnetDepsTarget struct {
Dependencies map[string]string `json:"dependencies"`
Runtime map[string]struct{} `json:"runtime"`
}
type dotnetDeps struct {
Libraries map[string]dotnetDepsLibrary `json:"libraries"`
RuntimeTarget dotnetRuntimeTarget `json:"runtimeTarget"`
Targets map[string]map[string]dotnetDepsTarget `json:"targets"`
Libraries map[string]dotnetDepsLibrary `json:"libraries"`
}
type dotnetDepsLibrary struct {
@@ -24,27 +35,55 @@ type dotnetDepsLibrary struct {
HashPath string `json:"hashPath"`
}
//nolint:funlen
func parseDotnetDeps(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
var pkgs []pkg.Package
var pkgMap = make(map[string]pkg.Package)
var relationships []artifact.Relationship
dec := json.NewDecoder(reader)
var p dotnetDeps
if err := dec.Decode(&p); err != nil {
var depsDoc dotnetDeps
if err := dec.Decode(&depsDoc); err != nil {
return nil, nil, fmt.Errorf("failed to parse deps.json file: %w", err)
}
var names []string
rootName := getDepsJSONFilePrefix(reader.AccessPath())
if rootName == "" {
return nil, nil, fmt.Errorf("unable to determine root package name from deps.json file: %s", reader.AccessPath())
}
var rootPkg *pkg.Package
for nameVersion, lib := range depsDoc.Libraries {
name, _ := extractNameAndVersion(nameVersion)
if lib.Type == "project" && name == rootName {
rootPkg = newDotnetDepsPackage(
nameVersion,
lib,
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
)
}
}
if rootPkg == nil {
return nil, nil, fmt.Errorf("unable to determine root package from deps.json file: %s", reader.AccessPath())
}
pkgs = append(pkgs, *rootPkg)
pkgMap[createNameAndVersion(rootPkg.Name, rootPkg.Version)] = *rootPkg
for nameVersion := range p.Libraries {
var names []string
for nameVersion := range depsDoc.Libraries {
names = append(names, nameVersion)
}
// sort the names so that the order of the packages is deterministic
sort.Strings(names)
for _, nameVersion := range names {
lib := p.Libraries[nameVersion]
// skip the root package
name, version := extractNameAndVersion(nameVersion)
if name == rootPkg.Name && version == rootPkg.Version {
continue
}
lib := depsDoc.Libraries[nameVersion]
dotnetPkg := newDotnetDepsPackage(
nameVersion,
lib,
@@ -53,8 +92,36 @@ func parseDotnetDeps(_ file.Resolver, _ *generic.Environment, reader file.Locati
if dotnetPkg != nil {
pkgs = append(pkgs, *dotnetPkg)
pkgMap[nameVersion] = *dotnetPkg
}
}
return pkgs, nil, nil
for pkgNameVersion, target := range depsDoc.Targets[depsDoc.RuntimeTarget.Name] {
for depName, depVersion := range target.Dependencies {
depNameVersion := createNameAndVersion(depName, depVersion)
depPkg, ok := pkgMap[depNameVersion]
if !ok {
log.Debug("unable to find package in map", depNameVersion)
continue
}
p, ok := pkgMap[pkgNameVersion]
if !ok {
log.Debug("unable to find package in map", pkgNameVersion)
continue
}
rel := artifact.Relationship{
From: depPkg,
To: p,
Type: artifact.DependencyOfRelationship,
}
relationships = append(relationships, rel)
}
}
// sort the relationships for deterministic output
// TODO: ideally this would be replaced with artifact.SortRelationships when one exists and is type agnostic.
// this will only consider package-to-package relationships.
pkg.SortRelationships(relationships)
return pkgs, relationships, nil
}

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