feat: add ArtifactID field to uniquely identify scan targets (#9663)

Co-authored-by: knqyf263 <knqyf263@users.noreply.github.com>
This commit is contained in:
Teppei Fukuda
2025-10-15 11:04:41 +04:00
committed by GitHub
parent 804ea4aa57
commit 84a7d9a5d6
40 changed files with 76 additions and 16 deletions

View File

@@ -316,6 +316,7 @@ func TestRepository(t *testing.T) {
golden: "testdata/test-repo.json.golden",
override: func(_ *testing.T, want, _ *types.Report) {
// Clear all metadata as this is a local directory scan without git info
want.ArtifactID = ""
want.Metadata = types.Metadata{}
},
},

View File

@@ -199,6 +199,7 @@ func TestSBOM(t *testing.T) {
}
func overrideSBOMReport(_ *testing.T, want, got *types.Report) {
want.ArtifactID = ""
want.Metadata.ImageID = ""
want.Metadata.ImageConfig = v1.ConfigFile{}
want.Metadata.DiffIDs = nil

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:4ca63ce1d8a90da2ed4f2d5e93e8e9db2f32d0fabf0718a2edebbe0e70826622",
"ArtifactName": "testdata/fixtures/images/almalinux-8.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4",
"ArtifactName": "testdata/fixtures/images/alpine-310.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1",
"ArtifactName": "testdata/fixtures/images/alpine-39.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1",
"ArtifactName": "testdata/fixtures/images/alpine-39.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1",
"ArtifactName": "testdata/fixtures/images/alpine-39.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1",
"ArtifactName": "testdata/fixtures/images/alpine-39.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:22848737c0d272ad5d7c7369d8ca830a62929e63e38edcb22085139a6ae0688d",
"ArtifactName": "testdata/fixtures/images/alpine-distroless.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:961c4ee06269351d858969ea0426878675ed708d3a140246eabbc0bfc352bffa",
"ArtifactName": "testdata/fixtures/images/amazon-1.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:b94321659aca6a89cb7650a5b864bc8ec4bf62c620b8f1a01530c2e90a88c391",
"ArtifactName": "testdata/fixtures/images/amazon-2.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:88702f6b6133bf06cc46af48437d0c0fc661239155548757c65916504a0e5eee",
"ArtifactName": "testdata/fixtures/images/busybox-with-lockfile.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:5bf9684f472089d6d5cb636041d3d6dc748dbde39f1aefc374bbd367bd2aabbf",
"ArtifactName": "testdata/fixtures/images/centos-6.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:f1cb7c7d58b73eac859c395882eec49d50651244e342cd6c68a5c7809785f427",
"ArtifactName": "testdata/fixtures/images/centos-7.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:f1cb7c7d58b73eac859c395882eec49d50651244e342cd6c68a5c7809785f427",
"ArtifactName": "testdata/fixtures/images/centos-7.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:f1cb7c7d58b73eac859c395882eec49d50651244e342cd6c68a5c7809785f427",
"ArtifactName": "testdata/fixtures/images/centos-7.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:c2c03a296d2329a4f3ab72a7bf38b78a8a80108204d326b0139d6af700e152d1",
"ArtifactName": "testdata/fixtures/images/debian-buster.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:c2c03a296d2329a4f3ab72a7bf38b78a8a80108204d326b0139d6af700e152d1",
"ArtifactName": "testdata/fixtures/images/debian-buster.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:f26939cc87ef44a6fc554eedd0a976ab30b5bc2769d65d2e986b6c5f1fd4053d",
"ArtifactName": "testdata/fixtures/images/debian-stretch.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:7f04a8d247173b1f2546d22913af637bbab4e7411e00ae6207da8d94c445750d",
"ArtifactName": "testdata/fixtures/images/distroless-base.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:6fcac2cc8a710f21577b5bbd534e0bfc841c0cca569b57182ba19054696cddda",
"ArtifactName": "testdata/fixtures/images/distroless-python27.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -3,18 +3,6 @@
"CreatedAt": "2024-09-09T13:21:09.230231+06:00",
"ArtifactName": "package-lock.json",
"ArtifactType": "filesystem",
"Metadata": {
"ImageConfig": {
"architecture": "",
"created": "0001-01-01T00:00:00Z",
"os": "",
"rootfs": {
"type": "",
"diff_ids": null
},
"config": {}
}
},
"Results": [
{
"Target": "package-lock.json",
@@ -33,7 +21,6 @@
"DependsOn": [
"ms@2.0.0"
],
"Layer": {},
"Locations": [
{
"StartLine": 11,
@@ -51,7 +38,6 @@
"Version": "2.0.0",
"Indirect": true,
"Relationship": "indirect",
"Layer": {},
"Locations": [
{
"StartLine": 20,
@@ -72,7 +58,6 @@
"InstalledVersion": "3.0.1",
"FixedVersion": "3.1.0, 2.6.9",
"Status": "fixed",
"Layer": {},
"SeveritySource": "ghsa",
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2017-20165",
"DataSource": {
@@ -132,7 +117,6 @@
"InstalledVersion": "3.0.1",
"FixedVersion": "2.6.9, 3.1.0, 3.2.7, 4.3.1",
"Status": "fixed",
"Layer": {},
"SeveritySource": "ghsa",
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2017-16137",
"DataSource": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:5a992077baba51b97f27591a10d54d2f2723dc9c81a3fe419e261023f2554933",
"ArtifactName": "testdata/fixtures/images/fluentd-multiple-lockfiles.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:8cdcbf18341ed8afa5322e7b0077f8ef3f46896882c921df5f97c51b369f6767",
"ArtifactName": "testdata/fixtures/images/mariner-1.0.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:fef5ad254f6378f08071cfa2daaf05a1ce9857141c944b67a40742e63e65cecc",
"ArtifactName": "testdata/fixtures/images/opensuse-leap-151.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:580e73f5c823232e6587136e9f5428a89afdf77a123bb8575d08208e0cc34b12",
"ArtifactName": "testdata/fixtures/images/opensuse-tumbleweed.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:8988c7081e1f7b6c2928cbc4832b8a05968bb589d45d444ca1e3027c68f97f56",
"ArtifactName": "testdata/fixtures/images/oraclelinux-8.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:5ccb5186b75cd13ff0d028f5b5b2bdf7ef7ca2b3d56eb2c6eb6c136077a6991a",
"ArtifactName": "testdata/fixtures/images/photon-30.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:210996f98b856d7cd00496ddbe9412e73f1c714c95de09661e07b4e43648f9ab",
"ArtifactName": "testdata/fixtures/images/rockylinux-8.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:c45ec974938acac29c893b5d273d73e4ebdd7e6a97b6fa861dfbd8dd430b9016",
"ArtifactName": "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:ed8f0747d483b60657982f0ef1ba74482aed08795cf0eb774b00bc53022a8351",
"ArtifactName": "testdata/fixtures/images/spring4shell-jre11.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:b88bc3d2f0b5aacf1d36efa498f427d923b01c854dac090acf5368c55ac04fda",
"ArtifactName": "testdata/fixtures/images/spring4shell-jre8.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:4f8b4cb139bdac63ad60b7382a80cd0414c55018e2f80d4163f59e40f71766cc",
"ArtifactName": "testdata/fixtures/repo/trivy-ci-test",
"ArtifactType": "repository",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:6fecccc91c83e11ae4fede6793e9410841221d4779520c2b9e9fb7f7b3830264",
"ArtifactName": "testdata/fixtures/images/ubi-7.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:6fecccc91c83e11ae4fede6793e9410841221d4779520c2b9e9fb7f7b3830264",
"ArtifactName": "testdata/fixtures/images/ubi-7.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:a2a15febcdf362f6115e801d37b5e60d6faaeedcb9896155e5fe9d754025be12",
"ArtifactName": "testdata/fixtures/images/ubuntu-1804.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -1,6 +1,7 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactID": "sha256:a2a15febcdf362f6115e801d37b5e60d6faaeedcb9896155e5fe9d754025be12",
"ArtifactName": "testdata/fixtures/images/ubuntu-1804.tar.gz",
"ArtifactType": "container_image",
"Metadata": {

View File

@@ -2,12 +2,15 @@ package scan
import (
"context"
"crypto/sha256"
"fmt"
"github.com/samber/lo"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/clock"
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/report"
"github.com/aquasecurity/trivy/pkg/types"
@@ -76,6 +79,7 @@ func (s Service) ScanArtifact(ctx context.Context, options types.ScanOptions) (t
return types.Report{
SchemaVersion: report.SchemaVersion,
CreatedAt: clock.Now(ctx),
ArtifactID: s.generateArtifactID(artifactInfo),
ArtifactName: artifactInfo.Name,
ArtifactType: artifactInfo.Type,
Metadata: types.Metadata{
@@ -103,3 +107,37 @@ func (s Service) ScanArtifact(ctx context.Context, options types.ScanOptions) (t
BOM: artifactInfo.BOM,
}, nil
}
// generateArtifactID generates a unique ID for the artifact based on its type
func (s Service) generateArtifactID(artifactInfo artifact.Reference) string {
switch artifactInfo.Type {
case ftypes.TypeContainerImage:
// Use image ID directly
return artifactInfo.ImageMetadata.ID
case ftypes.TypeRepository:
// Generate ID from repository URL and commit hash combination
if artifactInfo.RepoMetadata.RepoURL != "" && artifactInfo.RepoMetadata.Commit != "" {
// Calculate SHA256 of URL + commit hash
data := artifactInfo.RepoMetadata.RepoURL + "@" + artifactInfo.RepoMetadata.Commit
hash := sha256.Sum256([]byte(data))
return fmt.Sprintf("sha256:%x", hash)
}
// For local repositories without URL, use path and commit hash
if artifactInfo.RepoMetadata.Commit != "" {
data := artifactInfo.Name + "@" + artifactInfo.RepoMetadata.Commit
hash := sha256.Sum256([]byte(data))
return fmt.Sprintf("sha256:%x", hash)
}
// Empty string for non-Git directories
return ""
case ftypes.TypeFilesystem:
// Empty string for filesystem scans (as per requirement)
return ""
default:
// Empty string for other types
return ""
}
}

View File

@@ -53,6 +53,7 @@ func TestScanner_ScanArtifact(t *testing.T) {
want: tTypes.Report{
SchemaVersion: 2,
CreatedAt: time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC),
ArtifactID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
ArtifactName: "../fanal/test/testdata/alpine-311.tar.gz",
ArtifactType: ftypes.TypeContainerImage,
Metadata: tTypes.Metadata{

View File

@@ -13,6 +13,7 @@ import (
type Report struct {
SchemaVersion int `json:",omitempty"`
CreatedAt time.Time `json:",omitzero"`
ArtifactID string `json:",omitempty"` // Unique identifier for the artifact (e.g., image config hash)
ArtifactName string `json:",omitempty"`
ArtifactType ftypes.ArtifactType `json:",omitempty"`
Metadata Metadata `json:",omitzero"`