From 0b570bc79b3a7dd4c54d9ec92d466c244b38b4e9 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Thu, 25 Aug 2022 18:07:53 +0600 Subject: [PATCH 01/13] add lines from dockerfile to secrets --- pkg/fanal/applier/docker.go | 11 ++--- pkg/fanal/applier/docker_test.go | 7 +++- pkg/fanal/artifact/image/image.go | 57 +++++++++++++++++++------- pkg/fanal/artifact/image/image_test.go | 11 +++++ pkg/fanal/types/artifact.go | 1 + pkg/fanal/types/secret.go | 2 +- pkg/report/table/secret.go | 12 +++--- pkg/report/table/secret_test.go | 6 ++- pkg/rpc/convert.go | 4 +- rpc/common/service.pb.go | 50 +++++++++++----------- rpc/common/service.proto | 2 +- 11 files changed, 102 insertions(+), 61 deletions(-) diff --git a/pkg/fanal/applier/docker.go b/pkg/fanal/applier/docker.go index ac5f00be7dc..237bcfb1ec6 100644 --- a/pkg/fanal/applier/docker.go +++ b/pkg/fanal/applier/docker.go @@ -137,7 +137,7 @@ func ApplyLayers(layers []types.BlobInfo) types.ArtifactDetail { Digest: layer.Digest, DiffID: layer.DiffID, } - secretsMap = mergeSecrets(secretsMap, secret, l) + secretsMap = mergeSecrets(secretsMap, secret, l, layer.CreatedBy) } // Apply license files @@ -178,13 +178,7 @@ func ApplyLayers(layers []types.BlobInfo) types.ArtifactDetail { return nil }) - lastDiffID := layers[len(layers)-1].DiffID for _, s := range secretsMap { - for i, finding := range s.Findings { - if finding.Layer.DiffID != lastDiffID { - s.Findings[i].Deleted = true // This secret is deleted in the upper layer - } - } mergedLayer.Secrets = append(mergedLayer.Secrets, s) } @@ -271,9 +265,10 @@ func aggregate(detail *types.ArtifactDetail) { // We must save secrets from all layers even though they are removed in the uppler layer. // If the secret was changed at the top level, we need to overwrite it. -func mergeSecrets(secretsMap map[string]types.Secret, newSecret types.Secret, layer types.Layer) map[string]types.Secret { +func mergeSecrets(secretsMap map[string]types.Secret, newSecret types.Secret, layer types.Layer, createdBy string) map[string]types.Secret { for i := range newSecret.Findings { // add layer to the Findings from the new secret newSecret.Findings[i].Layer = layer + newSecret.Findings[i].CreatedBy = createdBy } secret, ok := secretsMap[newSecret.FilePath] diff --git a/pkg/fanal/applier/docker_test.go b/pkg/fanal/applier/docker_test.go index 60d4c724ad8..c78235a55ba 100644 --- a/pkg/fanal/applier/docker_test.go +++ b/pkg/fanal/applier/docker_test.go @@ -335,6 +335,7 @@ func TestApplyLayers(t *testing.T) { SchemaVersion: 2, Digest: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", DiffID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72", + CreatedBy: "Line_1", Secrets: []types.Secret{ { FilePath: "usr/secret.txt", @@ -368,6 +369,7 @@ func TestApplyLayers(t *testing.T) { SchemaVersion: 2, Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7", DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819", + CreatedBy: "Line_2", Secrets: []types.Secret{ { FilePath: "usr/secret.txt", @@ -422,6 +424,7 @@ func TestApplyLayers(t *testing.T) { SchemaVersion: 2, Digest: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", DiffID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72", + CreatedBy: "Line_3", WhiteoutFiles: []string{ "usr/secret.txt", }, @@ -437,7 +440,7 @@ func TestApplyLayers(t *testing.T) { Category: "GitHub", Severity: "CRITICAL", Title: "GitHub Personal Access Token", - Deleted: true, + CreatedBy: "Line_2", StartLine: 1, EndLine: 1, Match: "GITHUB_PAT=****************************************", @@ -463,7 +466,7 @@ func TestApplyLayers(t *testing.T) { Category: "AWS", Severity: "CRITICAL", Title: "AWS Access Key ID", - Deleted: true, + CreatedBy: "Line_2", StartLine: 2, EndLine: 2, Match: "AWS_ACCESS_KEY_ID=********************", diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index 43049d5f2ef..5f8f350b7a4 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -39,6 +39,11 @@ type Artifact struct { artifactOption artifact.Option } +type LayerInfo struct { + DiffID string + CreatedBy string +} + func NewArtifact(img types.Image, c cache.ArtifactCache, opt artifact.Option) (artifact.Artifact, error) { misconf := opt.MisconfScannerOption // Register config analyzers @@ -93,7 +98,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) log.Logger.Debugf("Base Layers: %v", baseDiffIDs) // Convert image ID and layer IDs to cache keys - imageKey, layerKeys, layerKeyMap, err := a.calcCacheKeys(imageID, diffIDs) + imageKey, layerKeys, layerKeyMap, err := a.calcCacheKeys(imageID, diffIDs, configFile) if err != nil { return types.ArtifactReference{}, err } @@ -133,45 +138,66 @@ func (Artifact) Clean(_ types.ArtifactReference) error { return nil } -func (a Artifact) calcCacheKeys(imageID string, diffIDs []string) (string, []string, map[string]string, error) { +func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1.ConfigFile) (string, []string, map[string]LayerInfo, error) { // Pass an empty config scanner option so that the cache key can be the same, even when policies are updated. imageKey, err := cache.CalcKey(imageID, a.analyzer.ImageConfigAnalyzerVersions(), nil, artifact.Option{}) if err != nil { return "", nil, nil, err } - layerKeyMap := map[string]string{} + var createdBy []string + // save createdBy fields in order of layers + for i := 0; i < len(configFile.History); i++ { + h := configFile.History[i] + // Detect and skip CMD instruction in base image + if strings.HasPrefix(h.CreatedBy, "/bin/sh -c #(nop) CMD") || + strings.HasPrefix(h.CreatedBy, "ENTRYPOINT") || + strings.HasPrefix(h.CreatedBy, "CMD") { // BuildKit + continue + } + c := strings.TrimPrefix(strings.TrimPrefix(h.CreatedBy, "/bin/sh -c "), "#(nop) ") + createdBy = append(createdBy, c) + } + + if len(createdBy) != len(diffIDs) { + return "", nil, nil, xerrors.Errorf("incorrect definition of layer history") + } + + layerKeyMap := map[string]LayerInfo{} hookVersions := a.handlerManager.Versions() var layerKeys []string - for _, diffID := range diffIDs { + for i, diffID := range diffIDs { blobKey, err := cache.CalcKey(diffID, a.analyzer.AnalyzerVersions(), hookVersions, a.artifactOption) if err != nil { return "", nil, nil, err } layerKeys = append(layerKeys, blobKey) - layerKeyMap[blobKey] = diffID + layerKeyMap[blobKey] = LayerInfo{ + DiffID: diffID, + CreatedBy: createdBy[i], + } } return imageKey, layerKeys, layerKeyMap, nil } -func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, baseDiffIDs []string, layerKeyMap map[string]string) error { +func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, baseDiffIDs []string, layerKeyMap map[string]LayerInfo) error { done := make(chan struct{}) errCh := make(chan error) var osFound types.OS for _, k := range layerKeys { go func(ctx context.Context, layerKey string) { - diffID := layerKeyMap[layerKey] + lInfo := layerKeyMap[layerKey] // If it is a base layer, secret scanning should not be performed. var disabledAnalyers []analyzer.Type - if slices.Contains(baseDiffIDs, diffID) { + if slices.Contains(baseDiffIDs, lInfo.DiffID) { disabledAnalyers = append(disabledAnalyers, analyzer.TypeSecret) } - layerInfo, err := a.inspectLayer(ctx, diffID, disabledAnalyers) + layerInfo, err := a.inspectLayer(ctx, lInfo, disabledAnalyers) if err != nil { - errCh <- xerrors.Errorf("failed to analyze layer: %s : %w", diffID, err) + errCh <- xerrors.Errorf("failed to analyze layer: %s : %w", layerInfo.DiffID, err) return } if err = a.cache.PutBlob(layerKey, layerInfo); err != nil { @@ -205,12 +231,12 @@ func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, b } -func (a Artifact) inspectLayer(ctx context.Context, diffID string, disabled []analyzer.Type) (types.BlobInfo, error) { - log.Logger.Debugf("Missing diff ID in cache: %s", diffID) +func (a Artifact) inspectLayer(ctx context.Context, layerInfo LayerInfo, disabled []analyzer.Type) (types.BlobInfo, error) { + log.Logger.Debugf("Missing diff ID in cache: %s", layerInfo.DiffID) - layerDigest, r, err := a.uncompressedLayer(diffID) + layerDigest, r, err := a.uncompressedLayer(layerInfo.DiffID) if err != nil { - return types.BlobInfo{}, xerrors.Errorf("unable to get uncompressed layer %s: %w", diffID, err) + return types.BlobInfo{}, xerrors.Errorf("unable to get uncompressed layer %s: %w", layerInfo.DiffID, err) } // Prepare variables @@ -239,7 +265,8 @@ func (a Artifact) inspectLayer(ctx context.Context, diffID string, disabled []an blobInfo := types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: layerDigest, - DiffID: diffID, + DiffID: layerInfo.DiffID, + CreatedBy: layerInfo.CreatedBy, OS: result.OS, Repository: result.Repository, PackageInfos: result.PackageInfos, diff --git a/pkg/fanal/artifact/image/image_test.go b/pkg/fanal/artifact/image/image_test.go index 786704f6f0e..f33774c6c39 100644 --- a/pkg/fanal/artifact/image/image_test.go +++ b/pkg/fanal/artifact/image/image_test.go @@ -63,6 +63,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203", + CreatedBy: "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ", OS: &types.OS{ Family: "alpine", Name: "3.11.5", @@ -273,6 +274,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + CreatedBy: "bazel build ...", OS: &types.OS{ Family: "debian", Name: "9.9", @@ -340,6 +342,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", + CreatedBy: "bazel build ...", PackageInfos: []types.PackageInfo{ { FilePath: "var/lib/dpkg/status.d/libc6", @@ -406,6 +409,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7", + CreatedBy: "COPY file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ", Applications: []types.Application{ { Type: "composer", FilePath: "php-app/composer.lock", @@ -438,6 +442,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566", + CreatedBy: "COPY file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ", Applications: []types.Application{ { Type: types.Bundler, FilePath: "ruby-app/Gemfile.lock", @@ -623,6 +628,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + CreatedBy: "bazel build ...", }, }, }, @@ -633,6 +639,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", + CreatedBy: "bazel build ...", }, }, }, @@ -643,6 +650,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7", + CreatedBy: "COPY file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ", OpaqueDirs: []string{"php-app/"}, }, }, @@ -654,6 +662,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566", + CreatedBy: "COPY file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ", OpaqueDirs: []string{"ruby-app/"}, }, }, @@ -778,6 +787,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203", + CreatedBy: "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ", OS: &types.OS{ Family: "alpine", Name: "3.11.5", @@ -909,6 +919,7 @@ func TestArtifact_Inspect(t *testing.T) { SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203", + CreatedBy: "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ", OS: &types.OS{ Family: "alpine", Name: "3.11.5", diff --git a/pkg/fanal/types/artifact.go b/pkg/fanal/types/artifact.go index c2699a014dc..2f1fadd95b1 100644 --- a/pkg/fanal/types/artifact.go +++ b/pkg/fanal/types/artifact.go @@ -135,6 +135,7 @@ type BlobInfo struct { SchemaVersion int Digest string `json:",omitempty"` DiffID string `json:",omitempty"` + CreatedBy string `json:",omitempty"` OS *OS `json:",omitempty"` Repository *Repository `json:",omitempty"` PackageInfos []PackageInfo `json:",omitempty"` diff --git a/pkg/fanal/types/secret.go b/pkg/fanal/types/secret.go index 3d2e3ca5f70..04548131f3f 100644 --- a/pkg/fanal/types/secret.go +++ b/pkg/fanal/types/secret.go @@ -16,6 +16,6 @@ type SecretFinding struct { EndLine int Code Code Match string - Deleted bool Layer Layer `json:",omitempty"` + CreatedBy string } diff --git a/pkg/report/table/secret.go b/pkg/report/table/secret.go index ee8804108e7..edc57276ef1 100644 --- a/pkg/report/table/secret.go +++ b/pkg/report/table/secret.go @@ -119,12 +119,14 @@ func (r *secretRenderer) renderCode(secret types.SecretFinding) { lineInfo = tml.Sprintf("%s-%d", lineInfo, secret.EndLine) } } - var note string - if secret.Deleted { - note = " (deleted in the intermediate layer)" - } - r.printf(" %s%s%s\r\n", r.target, lineInfo, note) + + r.printf(" %s%s\r\n", r.target, lineInfo) r.printSingleDivider() + if secret.CreatedBy != "" { + r.printf(" This secret is added in '%s'\r\n", secret.CreatedBy) + r.printSingleDivider() + } + for i, line := range lines { if line.Truncated { r.printf("%4s ", strings.Repeat(".", len(fmt.Sprintf("%d", line.Number)))) diff --git a/pkg/report/table/secret_test.go b/pkg/report/table/secret_test.go index a853c34d9ed..a3370b9c1c7 100644 --- a/pkg/report/table/secret_test.go +++ b/pkg/report/table/secret_test.go @@ -68,7 +68,7 @@ this is a title Category: ftypes.SecretRuleCategory("category"), Title: "this is a title", Severity: "HIGH", - Deleted: true, + CreatedBy: "COPY my-file my-file", StartLine: 3, EndLine: 4, Code: ftypes.Code{ @@ -115,7 +115,9 @@ HIGH: category (rule-id) ════════════════════════════════════════ this is a title ──────────────────────────────────────── - my-file:3-4 (deleted in the intermediate layer) + my-file:3-4 +──────────────────────────────────────── + This secret is added in 'COPY my-file my-file' ──────────────────────────────────────── 1 #!/bin/bash 2 diff --git a/pkg/rpc/convert.go b/pkg/rpc/convert.go index 78110f74af4..22313da6d9c 100644 --- a/pkg/rpc/convert.go +++ b/pkg/rpc/convert.go @@ -102,7 +102,7 @@ func ConvertToRPCSecretFindings(findings []ftypes.SecretFinding) []*common.Secre StartLine: int32(f.StartLine), Code: ConvertToRPCCode(f.Code), Match: f.Match, - Deleted: f.Deleted, + CreatedBy: f.CreatedBy, Layer: ConvertToRPCLayer(f.Layer), }) } @@ -313,7 +313,7 @@ func ConvertFromRPCSecretFindings(rpcFindings []*common.SecretFinding) []ftypes. EndLine: int(finding.EndLine), Code: ConvertFromRPCCode(finding.Code), Match: finding.Match, - Deleted: finding.Deleted, + CreatedBy: finding.CreatedBy, Layer: ftypes.Layer{ Digest: finding.Layer.Digest, DiffID: finding.Layer.DiffId, diff --git a/rpc/common/service.pb.go b/rpc/common/service.pb.go index 7fc194607e4..faa5c04e385 100644 --- a/rpc/common/service.pb.go +++ b/rpc/common/service.pb.go @@ -1415,7 +1415,7 @@ type SecretFinding struct { EndLine int32 `protobuf:"varint,6,opt,name=end_line,json=endLine,proto3" json:"end_line,omitempty"` Code *Code `protobuf:"bytes,7,opt,name=code,proto3" json:"code,omitempty"` Match string `protobuf:"bytes,8,opt,name=match,proto3" json:"match,omitempty"` - Deleted bool `protobuf:"varint,9,opt,name=deleted,proto3" json:"deleted,omitempty"` + CreatedBy string `protobuf:"bytes,9,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"` Layer *Layer `protobuf:"bytes,10,opt,name=layer,proto3" json:"layer,omitempty"` } @@ -1507,11 +1507,11 @@ func (x *SecretFinding) GetMatch() string { return "" } -func (x *SecretFinding) GetDeleted() bool { +func (x *SecretFinding) GetCreatedBy() string { if x != nil { - return x.Deleted + return x.CreatedBy } - return false + return "" } func (x *SecretFinding) GetLayer() *Layer { @@ -1803,7 +1803,7 @@ var file_rpc_common_service_proto_rawDesc = []byte{ 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0xb3, 0x02, + 0x6e, 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0xb8, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, @@ -1818,26 +1818,26 @@ var file_rpc_common_service_proto_rawDesc = []byte{ 0x12, 0x26, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x18, - 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, - 0x79, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x69, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, - 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x73, 0x2a, 0x44, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x0b, - 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c, - 0x4f, 0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x44, 0x49, 0x55, 0x4d, 0x10, 0x02, - 0x12, 0x08, 0x0a, 0x04, 0x48, 0x49, 0x47, 0x48, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, - 0x49, 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x04, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x29, 0x0a, + 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, + 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, + 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x12, 0x37, + 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, + 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2a, 0x44, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x74, 0x79, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x44, + 0x49, 0x55, 0x4d, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x49, 0x47, 0x48, 0x10, 0x03, 0x12, + 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x04, 0x42, 0x31, 0x5a, + 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, + 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/rpc/common/service.proto b/rpc/common/service.proto index f29706795db..e5559dc30ca 100644 --- a/rpc/common/service.proto +++ b/rpc/common/service.proto @@ -165,7 +165,7 @@ message SecretFinding { int32 end_line = 6; Code code = 7; string match = 8; - bool deleted = 9; + string created_by = 9; Layer layer = 10; } From 91d7cef21b45ab5c45009f3e112b661f948494ee Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 26 Aug 2022 13:48:21 +0600 Subject: [PATCH 02/13] refactor --- pkg/fanal/artifact/image/image.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index 5f8f350b7a4..96760ca7140 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -149,10 +149,8 @@ func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1 // save createdBy fields in order of layers for i := 0; i < len(configFile.History); i++ { h := configFile.History[i] - // Detect and skip CMD instruction in base image - if strings.HasPrefix(h.CreatedBy, "/bin/sh -c #(nop) CMD") || - strings.HasPrefix(h.CreatedBy, "ENTRYPOINT") || - strings.HasPrefix(h.CreatedBy, "CMD") { // BuildKit + // skip histories for empty layers + if h.EmptyLayer { continue } c := strings.TrimPrefix(strings.TrimPrefix(h.CreatedBy, "/bin/sh -c "), "#(nop) ") @@ -160,7 +158,7 @@ func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1 } if len(createdBy) != len(diffIDs) { - return "", nil, nil, xerrors.Errorf("incorrect definition of layer history") + return "", nil, nil, xerrors.Errorf("incorrect detection of layer history") } layerKeyMap := map[string]LayerInfo{} From ab8ea1af9d8f630ba0ee9cb8f5eb53aa5d991270 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 26 Aug 2022 14:51:01 +0600 Subject: [PATCH 03/13] refactor --- pkg/fanal/artifact/image/image.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index 96760ca7140..4b06ae58dba 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -157,10 +157,6 @@ func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1 createdBy = append(createdBy, c) } - if len(createdBy) != len(diffIDs) { - return "", nil, nil, xerrors.Errorf("incorrect detection of layer history") - } - layerKeyMap := map[string]LayerInfo{} hookVersions := a.handlerManager.Versions() var layerKeys []string From 67c70da200ee0d60f78e5449c34710ccd18e34b7 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 26 Aug 2022 17:18:41 +0600 Subject: [PATCH 04/13] add skip empty history --- pkg/fanal/artifact/image/image.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index 4b06ae58dba..80dc26c4ba7 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -166,9 +166,14 @@ func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1 return "", nil, nil, err } layerKeys = append(layerKeys, blobKey) + + c := "" + if len(createdBy) > 0 { + c = createdBy[i] + } layerKeyMap[blobKey] = LayerInfo{ DiffID: diffID, - CreatedBy: createdBy[i], + CreatedBy: c, } } return imageKey, layerKeys, layerKeyMap, nil From 70384d9dd04290e2cf0a04e5004ecf5849b3e61b Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 29 Aug 2022 10:33:54 +0600 Subject: [PATCH 05/13] move createdby to layer --- pkg/fanal/applier/docker.go | 10 +-- pkg/fanal/applier/docker_test.go | 12 +-- pkg/fanal/artifact/image/image.go | 3 +- pkg/fanal/types/artifact.go | 5 +- pkg/fanal/types/secret.go | 1 - pkg/report/table/secret.go | 14 ++-- pkg/report/table/secret_test.go | 16 ++-- pkg/rpc/convert.go | 12 +-- rpc/common/service.pb.go | 132 +++++++++++++++--------------- rpc/common/service.proto | 8 +- 10 files changed, 108 insertions(+), 105 deletions(-) diff --git a/pkg/fanal/applier/docker.go b/pkg/fanal/applier/docker.go index 237bcfb1ec6..712b8ae0311 100644 --- a/pkg/fanal/applier/docker.go +++ b/pkg/fanal/applier/docker.go @@ -134,10 +134,11 @@ func ApplyLayers(layers []types.BlobInfo) types.ArtifactDetail { // Apply secrets for _, secret := range layer.Secrets { l := types.Layer{ - Digest: layer.Digest, - DiffID: layer.DiffID, + Digest: layer.Digest, + DiffID: layer.DiffID, + CreatedBy: layer.CreatedBy, } - secretsMap = mergeSecrets(secretsMap, secret, l, layer.CreatedBy) + secretsMap = mergeSecrets(secretsMap, secret, l) } // Apply license files @@ -265,10 +266,9 @@ func aggregate(detail *types.ArtifactDetail) { // We must save secrets from all layers even though they are removed in the uppler layer. // If the secret was changed at the top level, we need to overwrite it. -func mergeSecrets(secretsMap map[string]types.Secret, newSecret types.Secret, layer types.Layer, createdBy string) map[string]types.Secret { +func mergeSecrets(secretsMap map[string]types.Secret, newSecret types.Secret, layer types.Layer) map[string]types.Secret { for i := range newSecret.Findings { // add layer to the Findings from the new secret newSecret.Findings[i].Layer = layer - newSecret.Findings[i].CreatedBy = createdBy } secret, ok := secretsMap[newSecret.FilePath] diff --git a/pkg/fanal/applier/docker_test.go b/pkg/fanal/applier/docker_test.go index c78235a55ba..dbee2bd3b0f 100644 --- a/pkg/fanal/applier/docker_test.go +++ b/pkg/fanal/applier/docker_test.go @@ -440,13 +440,13 @@ func TestApplyLayers(t *testing.T) { Category: "GitHub", Severity: "CRITICAL", Title: "GitHub Personal Access Token", - CreatedBy: "Line_2", StartLine: 1, EndLine: 1, Match: "GITHUB_PAT=****************************************", Layer: types.Layer{ - Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7", - DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819", + Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7", + DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819", + CreatedBy: "Line_2", }, Code: types.Code{ Lines: []types.Line{ @@ -466,13 +466,13 @@ func TestApplyLayers(t *testing.T) { Category: "AWS", Severity: "CRITICAL", Title: "AWS Access Key ID", - CreatedBy: "Line_2", StartLine: 2, EndLine: 2, Match: "AWS_ACCESS_KEY_ID=********************", Layer: types.Layer{ - Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7", - DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819", + Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7", + DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819", + CreatedBy: "Line_2", }, Code: types.Code{ Lines: []types.Line{ diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index 80dc26c4ba7..a7a6f244a87 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -147,8 +147,7 @@ func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1 var createdBy []string // save createdBy fields in order of layers - for i := 0; i < len(configFile.History); i++ { - h := configFile.History[i] + for _, h := range configFile.History { // skip histories for empty layers if h.EmptyLayer { continue diff --git a/pkg/fanal/types/artifact.go b/pkg/fanal/types/artifact.go index 2f1fadd95b1..c93b94ed642 100644 --- a/pkg/fanal/types/artifact.go +++ b/pkg/fanal/types/artifact.go @@ -18,8 +18,9 @@ type Repository struct { } type Layer struct { - Digest string `json:",omitempty"` - DiffID string `json:",omitempty"` + Digest string `json:",omitempty"` + DiffID string `json:",omitempty"` + CreatedBy string `json:",omitempty"` } type Package struct { diff --git a/pkg/fanal/types/secret.go b/pkg/fanal/types/secret.go index 04548131f3f..a2747cad75f 100644 --- a/pkg/fanal/types/secret.go +++ b/pkg/fanal/types/secret.go @@ -17,5 +17,4 @@ type SecretFinding struct { Code Code Match string Layer Layer `json:",omitempty"` - CreatedBy string } diff --git a/pkg/report/table/secret.go b/pkg/report/table/secret.go index edc57276ef1..94bfa85a9e0 100644 --- a/pkg/report/table/secret.go +++ b/pkg/report/table/secret.go @@ -120,12 +120,16 @@ func (r *secretRenderer) renderCode(secret types.SecretFinding) { } } - r.printf(" %s%s\r\n", r.target, lineInfo) - r.printSingleDivider() - if secret.CreatedBy != "" { - r.printf(" This secret is added in '%s'\r\n", secret.CreatedBy) - r.printSingleDivider() + var note string + if c := secret.Layer.CreatedBy; c != "" { + if len(c) < 40 { + note = fmt.Sprintf(" (added by '%s')", c) + } else { + note = fmt.Sprintf(" (added by '%s')", c[:40]) + } } + r.printf(" %s%s%s\r\n", r.target, lineInfo, note) + r.printSingleDivider() for i, line := range lines { if line.Truncated { diff --git a/pkg/report/table/secret_test.go b/pkg/report/table/secret_test.go index a3370b9c1c7..dc4a77e503a 100644 --- a/pkg/report/table/secret_test.go +++ b/pkg/report/table/secret_test.go @@ -64,11 +64,13 @@ this is a title name: "multiple line", input: []ftypes.SecretFinding{ { - RuleID: "rule-id", - Category: ftypes.SecretRuleCategory("category"), - Title: "this is a title", - Severity: "HIGH", - CreatedBy: "COPY my-file my-file", + RuleID: "rule-id", + Category: ftypes.SecretRuleCategory("category"), + Title: "this is a title", + Severity: "HIGH", + Layer: ftypes.Layer{ + CreatedBy: "COPY my-file my-file", + }, StartLine: 3, EndLine: 4, Code: ftypes.Code{ @@ -115,9 +117,7 @@ HIGH: category (rule-id) ════════════════════════════════════════ this is a title ──────────────────────────────────────── - my-file:3-4 -──────────────────────────────────────── - This secret is added in 'COPY my-file my-file' + my-file:3-4 (added by 'COPY my-file my-file') ──────────────────────────────────────── 1 #!/bin/bash 2 diff --git a/pkg/rpc/convert.go b/pkg/rpc/convert.go index 22313da6d9c..cae062fe1ec 100644 --- a/pkg/rpc/convert.go +++ b/pkg/rpc/convert.go @@ -102,7 +102,6 @@ func ConvertToRPCSecretFindings(findings []ftypes.SecretFinding) []*common.Secre StartLine: int32(f.StartLine), Code: ConvertToRPCCode(f.Code), Match: f.Match, - CreatedBy: f.CreatedBy, Layer: ConvertToRPCLayer(f.Layer), }) } @@ -230,8 +229,9 @@ func ConvertToRPCMisconfs(misconfs []types.DetectedMisconfiguration) []*common.D // ConvertToRPCLayer returns common.Layer func ConvertToRPCLayer(layer ftypes.Layer) *common.Layer { return &common.Layer{ - Digest: layer.Digest, - DiffId: layer.DiffID, + Digest: layer.Digest, + DiffId: layer.DiffID, + CreatedBy: layer.CreatedBy, } } @@ -313,10 +313,10 @@ func ConvertFromRPCSecretFindings(rpcFindings []*common.SecretFinding) []ftypes. EndLine: int(finding.EndLine), Code: ConvertFromRPCCode(finding.Code), Match: finding.Match, - CreatedBy: finding.CreatedBy, Layer: ftypes.Layer{ - Digest: finding.Layer.Digest, - DiffID: finding.Layer.DiffId, + Digest: finding.Layer.Digest, + DiffID: finding.Layer.DiffId, + CreatedBy: finding.Layer.CreatedBy, }, }) } diff --git a/rpc/common/service.pb.go b/rpc/common/service.pb.go index faa5c04e385..cfd71f49bea 100644 --- a/rpc/common/service.pb.go +++ b/rpc/common/service.pb.go @@ -1060,8 +1060,9 @@ type Layer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Digest string `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"` - DiffId string `protobuf:"bytes,2,opt,name=diff_id,json=diffId,proto3" json:"diff_id,omitempty"` + Digest string `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"` + DiffId string `protobuf:"bytes,2,opt,name=diff_id,json=diffId,proto3" json:"diff_id,omitempty"` + CreatedBy string `protobuf:"bytes,3,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"` } func (x *Layer) Reset() { @@ -1110,6 +1111,13 @@ func (x *Layer) GetDiffId() string { return "" } +func (x *Layer) GetCreatedBy() string { + if x != nil { + return x.CreatedBy + } + return "" +} + type CVSS struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1415,8 +1423,7 @@ type SecretFinding struct { EndLine int32 `protobuf:"varint,6,opt,name=end_line,json=endLine,proto3" json:"end_line,omitempty"` Code *Code `protobuf:"bytes,7,opt,name=code,proto3" json:"code,omitempty"` Match string `protobuf:"bytes,8,opt,name=match,proto3" json:"match,omitempty"` - CreatedBy string `protobuf:"bytes,9,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"` - Layer *Layer `protobuf:"bytes,10,opt,name=layer,proto3" json:"layer,omitempty"` + Layer *Layer `protobuf:"bytes,9,opt,name=layer,proto3" json:"layer,omitempty"` } func (x *SecretFinding) Reset() { @@ -1507,13 +1514,6 @@ func (x *SecretFinding) GetMatch() string { return "" } -func (x *SecretFinding) GetCreatedBy() string { - if x != nil { - return x.CreatedBy - } - return "" -} - func (x *SecretFinding) GetLayer() *Layer { if x != nil { return x.Layer @@ -1764,64 +1764,64 @@ var file_rpc_common_service_proto_rawDesc = []byte{ 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x38, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x57, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x66, 0x66, - 0x49, 0x64, 0x22, 0x76, 0x0a, 0x04, 0x43, 0x56, 0x53, 0x53, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x32, - 0x5f, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, - 0x32, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x33, 0x5f, 0x76, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x33, 0x56, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x32, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x76, 0x32, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, - 0x19, 0x0a, 0x08, 0x76, 0x33, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x01, 0x52, 0x07, 0x76, 0x33, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x43, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x29, - 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, - 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xf3, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, - 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x74, - 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x67, - 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, - 0x69, 0x72, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x04, 0x43, - 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0xb8, 0x02, - 0x0a, 0x0d, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, - 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, - 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, - 0x67, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, - 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6e, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x4c, 0x69, 0x6e, 0x65, - 0x12, 0x26, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, - 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1d, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x29, 0x0a, - 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, + 0x79, 0x22, 0x76, 0x0a, 0x04, 0x43, 0x56, 0x53, 0x53, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x32, 0x5f, + 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x32, + 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x33, 0x5f, 0x76, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x33, 0x56, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x32, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x76, 0x32, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x19, + 0x0a, 0x08, 0x76, 0x33, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x07, 0x76, 0x33, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x43, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x29, 0x0a, + 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, + 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, + 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x22, 0xf3, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, + 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x69, 0x73, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, + 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, + 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x67, 0x68, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x68, + 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, + 0x72, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, + 0x61, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x04, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x99, 0x02, 0x0a, + 0x0d, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x17, + 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, + 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, + 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6c, + 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x12, + 0x26, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x29, 0x0a, + 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, diff --git a/rpc/common/service.proto b/rpc/common/service.proto index e5559dc30ca..d513ee5268c 100644 --- a/rpc/common/service.proto +++ b/rpc/common/service.proto @@ -115,8 +115,9 @@ message DataSource { } message Layer { - string digest = 1; - string diff_id = 2; + string digest = 1; + string diff_id = 2; + string created_by = 3; } enum Severity { @@ -165,8 +166,7 @@ message SecretFinding { int32 end_line = 6; Code code = 7; string match = 8; - string created_by = 9; - Layer layer = 10; + Layer layer = 9; } message Secret { From c0b43d22f1ea61b93523a81abbe0b845612ac54e Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 29 Aug 2022 14:45:06 +0600 Subject: [PATCH 06/13] add history for podman and containerd --- pkg/fanal/image/daemon/containerd.go | 25 ++- pkg/fanal/image/daemon/image.go | 14 +- pkg/fanal/image/daemon/podman.go | 31 +++ pkg/fanal/image/daemon/podman_test.go | 15 +- pkg/fanal/test/integration/containerd_test.go | 189 ++++++++++++++++++ pkg/fanal/test/integration/library_test.go | 4 +- 6 files changed, 265 insertions(+), 13 deletions(-) diff --git a/pkg/fanal/image/daemon/containerd.go b/pkg/fanal/image/daemon/containerd.go index 9c95aa3bb0d..6b2ec56d4ca 100644 --- a/pkg/fanal/image/daemon/containerd.go +++ b/pkg/fanal/image/daemon/containerd.go @@ -19,6 +19,7 @@ import ( api "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" + v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/samber/lo" @@ -90,14 +91,15 @@ func ContainerdImage(ctx context.Context, imageName string) (Image, func(), erro _ = os.Remove(f.Name()) } - insp, err := inspect(ctx, img, ref) + insp, history, err := inspect(ctx, img, ref) if err != nil { return nil, nil, xerrors.Errorf("inspect error: %w", err) } return &image{ - opener: imageOpener(ctx, ref.String(), f, imageWriter(client, img)), - inspect: insp, + opener: imageOpener(ctx, ref.String(), f, imageWriter(client, img)), + inspect: insp, + convertedHistory: history, }, cleanup, nil } @@ -121,7 +123,7 @@ func readImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, } // ported from https://github.com/containerd/nerdctl/blob/d110fea18018f13c3f798fa6565e482f3ff03591/pkg/inspecttypes/dockercompat/dockercompat.go#L279-L321 -func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.ImageInspect, error) { +func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.ImageInspect, []v1.History, error) { var tag string if tagged, ok := ref.(refdocker.Tagged); ok { tag = tagged.Tag() @@ -130,7 +132,7 @@ func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.I imgConfig, imgConfigDesc, err := readImageConfig(ctx, img) if err != nil { - return api.ImageInspect{}, err + return api.ImageInspect{}, nil, err } var lastHistory ocispec.History @@ -138,6 +140,17 @@ func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.I lastHistory = imgConfig.History[len(imgConfig.History)-1] } + var history []v1.History + for _, h := range imgConfig.History { + history = append(history, v1.History{ + Author: h.Author, + Created: v1.Time{Time: *h.Created}, + CreatedBy: h.CreatedBy, + Comment: h.Comment, + EmptyLayer: h.EmptyLayer, + }) + } + portSet := make(nat.PortSet) for k := range imgConfig.Config.ExposedPorts { portSet[nat.Port(k)] = struct{}{} @@ -168,5 +181,5 @@ func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.I return d.String() }), }, - }, nil + }, history, nil } diff --git a/pkg/fanal/image/daemon/image.go b/pkg/fanal/image/daemon/image.go index 70304993d62..bf4748b22a4 100644 --- a/pkg/fanal/image/daemon/image.go +++ b/pkg/fanal/image/daemon/image.go @@ -4,6 +4,7 @@ import ( "context" "io" "os" + "strings" "sync" "time" @@ -56,9 +57,10 @@ func imageOpener(ctx context.Context, ref string, f *os.File, imageSave imageSav // To avoid entire loading, this wrapper uses ImageInspectWithRaw and checks image ID and layer IDs. type image struct { v1.Image - opener opener - inspect types.ImageInspect - history []dimage.HistoryResponseItem + opener opener + inspect types.ImageInspect + history []dimage.HistoryResponseItem + convertedHistory []v1.History } // populateImage initializes an "image" struct. @@ -145,6 +147,10 @@ func (img *image) RepoDigests() []string { func (img *image) configHistory() []v1.History { // Fill only required metadata var history []v1.History + + if len(img.convertedHistory) > 0 { + return img.convertedHistory + } for i := len(img.history) - 1; i >= 0; i-- { h := img.history[i] history = append(history, v1.History{ @@ -153,7 +159,7 @@ func (img *image) configHistory() []v1.History { }, CreatedBy: h.CreatedBy, Comment: h.Comment, - EmptyLayer: h.Size == 0, + EmptyLayer: h.Size == 0 && !strings.HasPrefix(h.CreatedBy, "/bin/sh -c mkdir"), }) } return history diff --git a/pkg/fanal/image/daemon/podman.go b/pkg/fanal/image/daemon/podman.go index fb1cc113fc7..db282e69ea4 100644 --- a/pkg/fanal/image/daemon/podman.go +++ b/pkg/fanal/image/daemon/podman.go @@ -11,11 +11,13 @@ import ( "path/filepath" api "github.com/docker/docker/api/types" + dimage "github.com/docker/docker/api/types/image" "golang.org/x/xerrors" ) var ( inspectURL = "http://podman/images/%s/json" + historyURL = "http://podman/images/%s/history" saveURL = "http://podman/images/%s/get" ) @@ -70,6 +72,29 @@ func (p podmanClient) imageInspect(imageName string) (api.ImageInspect, error) { return inspect, nil } +func (p podmanClient) imageHistoryInspect(imageName string) ([]dimage.HistoryResponseItem, error) { + url := fmt.Sprintf(historyURL, imageName) + resp, err := p.c.Get(url) + if err != nil { + return []dimage.HistoryResponseItem{}, xerrors.Errorf("http error: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + var res errResponse + if err = json.NewDecoder(resp.Body).Decode(&res); err != nil { + return []dimage.HistoryResponseItem{}, xerrors.Errorf("unknown status code from Podman: %d", resp.StatusCode) + } + return []dimage.HistoryResponseItem{}, xerrors.New(res.Message) + } + + var history []dimage.HistoryResponseItem + if err = json.NewDecoder(resp.Body).Decode(&history); err != nil { + return []dimage.HistoryResponseItem{}, xerrors.Errorf("unable to decode JSON: %w", err) + } + return history, nil +} + func (p podmanClient) imageSave(_ context.Context, imageNames []string) (io.ReadCloser, error) { if len(imageNames) < 1 { return nil, xerrors.Errorf("no specified image") @@ -96,6 +121,11 @@ func PodmanImage(ref string) (Image, func(), error) { return nil, cleanup, xerrors.Errorf("unable to inspect the image (%s): %w", ref, err) } + history, err := c.imageHistoryInspect(ref) + if err != nil { + return nil, cleanup, xerrors.Errorf("unable to inspect the image (%s): %w", ref, err) + } + f, err := os.CreateTemp("", "fanal-*") if err != nil { return nil, cleanup, xerrors.Errorf("failed to create a temporary file") @@ -109,5 +139,6 @@ func PodmanImage(ref string) (Image, func(), error) { return &image{ opener: imageOpener(context.Background(), ref, f, c.imageSave), inspect: inspect, + history: history, }, cleanup, nil } diff --git a/pkg/fanal/image/daemon/podman_test.go b/pkg/fanal/image/daemon/podman_test.go index f5b633fbd93..6c66fa62baa 100644 --- a/pkg/fanal/image/daemon/podman_test.go +++ b/pkg/fanal/image/daemon/podman_test.go @@ -53,13 +53,18 @@ func TestPodmanImage(t *testing.T) { imageName string fields fields wantConfigName string + wantCreateBy []string wantErr bool }{ { name: "happy path", imageName: "alpine:3.11", wantConfigName: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72", - wantErr: false, + wantCreateBy: []string{ + "/bin/sh -c #(nop) CMD [\"/bin/sh\"]", + "/bin/sh -c #(nop) ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ", + }, + wantErr: false, }, { name: "unknown image", @@ -88,6 +93,14 @@ func TestPodmanImage(t *testing.T) { confName, err := img.ConfigName() require.NoError(t, err) assert.Equal(t, tt.wantConfigName, confName.String()) + + confFile, err := img.ConfigFile() + require.NoError(t, err) + + assert.Equal(t, len(confFile.History), len(tt.wantCreateBy)) + for _, h := range confFile.History { + assert.Contains(t, tt.wantCreateBy, h.CreatedBy) + } }) } } diff --git a/pkg/fanal/test/integration/containerd_test.go b/pkg/fanal/test/integration/containerd_test.go index 26343e90610..c205c692428 100644 --- a/pkg/fanal/test/integration/containerd_test.go +++ b/pkg/fanal/test/integration/containerd_test.go @@ -112,6 +112,17 @@ func TestContainerd_LocalImage(t *testing.T) { "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", }, }, + History: []v1.History{ + { + Created: v1.Time{Time: time.Date(2019, 8, 20, 20, 19, 55, 62606894, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ADD file:fe64057fbb83dccb960efabbf1cd8777920ef279a7fa8dbca0a8801c651bdf7c in / ", + }, + { + Created: v1.Time{Time: time.Date(2019, 8, 20, 20, 19, 55, 211423266, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) CMD [\"/bin/sh\"]", + EmptyLayer: true, + }, + }, }, }, }, @@ -201,6 +212,173 @@ func TestContainerd_LocalImage(t *testing.T) { "/docker-entrypoint.sh", }, }, + History: []v1.History{ + { + Created: v1.Time{Time: time.Date(2018, 9, 11, 22, 19, 38, 885299940, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ADD file:49f9e47e678d868d5b023482aa8dded71276a241a665c4f8b55ca77269321b34 in / ", + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 11, 22, 19, 39, 58628442, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) CMD [\"/bin/sh\"]", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 26, 59, 951316015, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV PHPIZE_DEPS=autoconf \t\tdpkg-dev dpkg \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkgconf \t\tre2c", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 1, 470388635, time.UTC)}, + CreatedBy: "/bin/sh -c apk add --no-cache --virtual .persistent-deps \t\tca-certificates \t\tcurl \t\ttar \t\txz \t\tlibressl", + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 2, 432381785, time.UTC)}, + CreatedBy: "/bin/sh -c set -x \t&& addgroup -g 82 -S www-data \t&& adduser -u 82 -D -S -G www-data www-data", + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 2, 715120309, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV PHP_INI_DIR=/usr/local/etc/php", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 3, 655421341, time.UTC)}, + CreatedBy: "/bin/sh -c mkdir -p $PHP_INI_DIR/conf.d", + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 3, 931799562, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 4, 210945499, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 4, 523116501, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 4, 795176159, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV GPG_KEYS=1729F83938DA44E27BA0F4D3DBDB397470D12172 B1B44D8F021E4E2D6021E995DC9FF8D3EE5AF27F", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 18, 415761689, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV PHP_VERSION=7.2.11", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 18, 599097853, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV PHP_URL=https://secure.php.net/get/php-7.2.11.tar.xz/from/this/mirror PHP_ASC_URL=https://secure.php.net/get/php-7.2.11.tar.xz.asc/from/this/mirror", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 18, 782890412, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV PHP_SHA256=da1a705c0bc46410e330fc6baa967666c8cd2985378fb9707c01a8e33b01d985 PHP_MD5=", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 22, 795846753, time.UTC)}, + CreatedBy: "/bin/sh -c set -xe; \t\tapk add --no-cache --virtual .fetch-deps \t\tgnupg \t\twget \t; \t\tmkdir -p /usr/src; \tcd /usr/src; \t\twget -O php.tar.xz \"$PHP_URL\"; \t\tif [ -n \"$PHP_SHA256\" ]; then \t\techo \"$PHP_SHA256 *php.tar.xz\" | sha256sum -c -; \tfi; \tif [ -n \"$PHP_MD5\" ]; then \t\techo \"$PHP_MD5 *php.tar.xz\" | md5sum -c -; \tfi; \t\tif [ -n \"$PHP_ASC_URL\" ]; then \t\twget -O php.tar.xz.asc \"$PHP_ASC_URL\"; \t\texport GNUPGHOME=\"$(mktemp -d)\"; \t\tfor key in $GPG_KEYS; do \t\t\tgpg --keyserver ha.pool.sks-keyservers.net --recv-keys \"$key\"; \t\tdone; \t\tgpg --batch --verify php.tar.xz.asc php.tar.xz; \t\tcommand -v gpgconf > /dev/null && gpgconf --kill all; \t\trm -rf \"$GNUPGHOME\"; \tfi; \t\tapk del .fetch-deps", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 23, 71406376, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) COPY file:207c686e3fed4f71f8a7b245d8dcae9c9048d276a326d82b553c12a90af0c0ca in /usr/local/bin/ ", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 13, 93396680, time.UTC)}, + CreatedBy: "/bin/sh -c set -xe \t&& apk add --no-cache --virtual .build-deps \t\t$PHPIZE_DEPS \t\tcoreutils \t\tcurl-dev \t\tlibedit-dev \t\tlibressl-dev \t\tlibsodium-dev \t\tlibxml2-dev \t\tsqlite-dev \t\t&& export CFLAGS=\"$PHP_CFLAGS\" \t\tCPPFLAGS=\"$PHP_CPPFLAGS\" \t\tLDFLAGS=\"$PHP_LDFLAGS\" \t&& docker-php-source extract \t&& cd /usr/src/php \t&& gnuArch=\"$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)\" \t&& ./configure \t\t--build=\"$gnuArch\" \t\t--with-config-file-path=\"$PHP_INI_DIR\" \t\t--with-config-file-scan-dir=\"$PHP_INI_DIR/conf.d\" \t\t\t\t--enable-option-checking=fatal \t\t\t\t--with-mhash \t\t\t\t--enable-ftp \t\t--enable-mbstring \t\t--enable-mysqlnd \t\t--with-sodium=shared \t\t\t\t--with-curl \t\t--with-libedit \t\t--with-openssl \t\t--with-zlib \t\t\t\t$(test \"$gnuArch\" = 's390x-linux-gnu' && echo '--without-pcre-jit') \t\t\t\t$PHP_EXTRA_CONFIGURE_ARGS \t&& make -j \"$(nproc)\" \t&& make install \t&& { find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; } \t&& make clean \t\t&& cp -v php.ini-* \"$PHP_INI_DIR/\" \t\t&& cd / \t&& docker-php-source delete \t\t&& runDeps=\"$( \t\tscanelf --needed --nobanner --format '%n#p' --recursive /usr/local \t\t\t| tr ',' '\\n' \t\t\t| sort -u \t\t\t| awk 'system(\"[ -e /usr/local/lib/\" $1 \" ]\") == 0 { next } { print \"so:\" $1 }' \t)\" \t&& apk add --no-cache --virtual .php-rundeps $runDeps \t\t&& apk del .build-deps \t\t&& pecl update-channels \t&& rm -rf /tmp/pear ~/.pearrc", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 13, 722586262, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) COPY multi:2cdcedabcf5a3b9ae610fab7848e94bc2f64b4d85710d55fd6f79e44dacf73d8 in /usr/local/bin/ ", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 14, 618087104, time.UTC)}, + CreatedBy: "/bin/sh -c docker-php-ext-enable sodium", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 14, 826981756, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENTRYPOINT [\"docker-php-entrypoint\"]", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 15, 10831572, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) CMD [\"php\" \"-a\"]", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 21, 919735971, time.UTC)}, + CreatedBy: "/bin/sh -c apk --no-cache add git subversion openssh mercurial tini bash patch", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 22, 611763893, time.UTC)}, + CreatedBy: "/bin/sh -c echo \"memory_limit=-1\" > \"$PHP_INI_DIR/conf.d/memory-limit.ini\" && echo \"date.timezone=${PHP_TIMEZONE:-UTC}\" > \"$PHP_INI_DIR/conf.d/date_timezone.ini\"", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 50, 224278478, time.UTC)}, + CreatedBy: "/bin/sh -c apk add --no-cache --virtual .build-deps zlib-dev && docker-php-ext-install zip && runDeps=\"$( scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions | tr ',' '\\n' | sort -u | awk 'system(\"[ -e /usr/local/lib/\" $1 \" ]\") == 0 { next } { print \"so:\" $1 }' )\" && apk add --virtual .composer-phpext-rundeps $runDeps && apk del .build-deps", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 50, 503010161, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV COMPOSER_ALLOW_SUPERUSER=1", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 50, 775378559, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV COMPOSER_HOME=/tmp", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 51, 35012363, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENV COMPOSER_VERSION=1.7.2", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 52, 491402624, time.UTC)}, + CreatedBy: "/bin/sh -c curl --silent --fail --location --retry 3 --output /tmp/installer.php --url https://raw.githubusercontent.com/composer/getcomposer.org/b107d959a5924af895807021fcef4ffec5a76aa9/web/installer && php -r \" \\$signature = '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061'; \\$hash = hash('SHA384', file_get_contents('/tmp/installer.php')); if (!hash_equals(\\$signature, \\$hash)) { unlink('/tmp/installer.php'); echo 'Integrity check failed, installer is either corrupt or worse.' . PHP_EOL; exit(1); }\" && php /tmp/installer.php --no-ansi --install-dir=/usr/bin --filename=composer --version=${COMPOSER_VERSION} && composer --ansi --version --no-interaction && rm -rf /tmp/* /tmp/.htaccess", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 52, 948859545, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) COPY file:295943a303e8f27de4302b6aa3687bce4b1d1392335efaaab9ecd37bec5ab4c5 in /docker-entrypoint.sh ", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 53, 295399872, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) WORKDIR /app", + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 53, 582920705, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ENTRYPOINT [\"/bin/sh\" \"/docker-entrypoint.sh\"]", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 53, 798628678, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) CMD [\"composer\"]", + EmptyLayer: true, + }, + { + Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 57, 211142800, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ADD file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ", + }, + { + Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 57, 583779000, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ADD file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ", + }, + { + Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 57, 921730100, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ADD file:54a1c52556a5ebe98fd124f51c25d071f9e29e2714c72c80d6d3d254b9e83386 in /node-app/package-lock.json ", + }, + { + Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 58, 311593100, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ADD file:097d32f46acde76c4da9e55f17110d69d02cc6d16c86da907980da335fc0fc5f in /python-app/Pipfile.lock ", + }, + { + Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 58, 651649800, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ADD file:7f147d85de19bfb905c260a0c175f227a433259022c163017b96d0efacdcd105 in /rust-app/Cargo.lock ", + }, + }, }, }, }, @@ -320,6 +498,17 @@ func TestContainerd_PullImage(t *testing.T) { }, ArgsEscaped: false, }, + History: []v1.History{ + { + Created: v1.Time{time.Date(2019, 8, 20, 20, 19, 55, 62606894, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) ADD file:fe64057fbb83dccb960efabbf1cd8777920ef279a7fa8dbca0a8801c651bdf7c in / ", + }, + { + Created: v1.Time{time.Date(2019, 8, 20, 20, 19, 55, 211423266, time.UTC)}, + CreatedBy: "/bin/sh -c #(nop) CMD [\"/bin/sh\"]", + EmptyLayer: true, + }, + }, }, }, }, diff --git a/pkg/fanal/test/integration/library_test.go b/pkg/fanal/test/integration/library_test.go index df496704de1..7d853a6fc4e 100644 --- a/pkg/fanal/test/integration/library_test.go +++ b/pkg/fanal/test/integration/library_test.go @@ -43,7 +43,7 @@ type testCase struct { } var tests = []testCase{ - { + /*{ name: "happy path, alpine:3.10", remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", imageFile: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", @@ -91,7 +91,7 @@ var tests = []testCase{ remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:fedora-35", imageFile: "../../../../integration/testdata/fixtures/images/fedora-35.tar.gz", wantOS: types.OS{Name: "35", Family: "fedora"}, - }, + },*/ { name: "happy path, vulnimage with lock files", remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:vulnimage", From 894c8c4783825022268a28b24de59082a58771b8 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Tue, 30 Aug 2022 15:09:49 +0600 Subject: [PATCH 07/13] use diffId when wrong histories --- pkg/fanal/artifact/image/image.go | 5 ++++- pkg/report/table/secret.go | 2 ++ pkg/report/table/secret_test.go | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index a7a6f244a87..6a383c28d3d 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -156,6 +156,9 @@ func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1 createdBy = append(createdBy, c) } + // If history detected incorrect - use only diffID + useCreatedBy := len(diffIDs) == len(createdBy) + layerKeyMap := map[string]LayerInfo{} hookVersions := a.handlerManager.Versions() var layerKeys []string @@ -167,7 +170,7 @@ func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1 layerKeys = append(layerKeys, blobKey) c := "" - if len(createdBy) > 0 { + if useCreatedBy { c = createdBy[i] } layerKeyMap[blobKey] = LayerInfo{ diff --git a/pkg/report/table/secret.go b/pkg/report/table/secret.go index 94bfa85a9e0..9c70334447f 100644 --- a/pkg/report/table/secret.go +++ b/pkg/report/table/secret.go @@ -127,6 +127,8 @@ func (r *secretRenderer) renderCode(secret types.SecretFinding) { } else { note = fmt.Sprintf(" (added by '%s')", c[:40]) } + } else { + note = fmt.Sprintf(" (added by '%s' layer)", strings.TrimPrefix(secret.Layer.DiffID, "sha256:")[:8]) } r.printf(" %s%s%s\r\n", r.target, lineInfo, note) r.printSingleDivider() diff --git a/pkg/report/table/secret_test.go b/pkg/report/table/secret_test.go index dc4a77e503a..6bf73893076 100644 --- a/pkg/report/table/secret_test.go +++ b/pkg/report/table/secret_test.go @@ -27,6 +27,7 @@ func TestSecretRenderer(t *testing.T) { Category: ftypes.SecretRuleCategory("category"), Title: "this is a title", Severity: "HIGH", + Layer: ftypes.Layer{DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203"}, StartLine: 1, EndLine: 1, Code: ftypes.Code{ @@ -52,7 +53,7 @@ HIGH: category (rule-id) ════════════════════════════════════════ this is a title ──────────────────────────────────────── - my-file:1 + my-file:1 (added by 'beee9f30' layer) ──────────────────────────────────────── 1 [ password=secret ──────────────────────────────────────── @@ -69,6 +70,7 @@ this is a title Title: "this is a title", Severity: "HIGH", Layer: ftypes.Layer{ + DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203", CreatedBy: "COPY my-file my-file", }, StartLine: 3, From 1e073b2fc8381d903cdff1d7904f4a80010f1aa2 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Tue, 13 Sep 2022 20:25:47 +0300 Subject: [PATCH 08/13] refactor: separate a function --- pkg/fanal/artifact/image/image.go | 57 +++++++++++++++++++------------ pkg/fanal/types/artifact.go | 16 +++++---- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index ca522a9ec65..d4bad42ec6a 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -39,7 +39,7 @@ type Artifact struct { type LayerInfo struct { DiffID string - CreatedBy string + CreatedBy string // can be empty } func NewArtifact(img types.Image, c cache.ArtifactCache, opt artifact.Option) (artifact.Artifact, error) { @@ -95,11 +95,14 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) log.Logger.Debugf("Base Layers: %v", baseDiffIDs) // Convert image ID and layer IDs to cache keys - imageKey, layerKeys, layerKeyMap, err := a.calcCacheKeys(imageID, diffIDs, configFile) + imageKey, layerKeys, err := a.calcCacheKeys(imageID, diffIDs) if err != nil { return types.ArtifactReference{}, err } + // Parse histories and extract a list of "created_by" + layerKeyMap := a.consolidateCreatedBy(diffIDs, layerKeys, configFile) + missingImage, missingLayers, err := a.cache.MissingBlobs(imageKey, layerKeys) if err != nil { return types.ArtifactReference{}, xerrors.Errorf("unable to get missing layers: %w", err) @@ -135,47 +138,57 @@ func (Artifact) Clean(_ types.ArtifactReference) error { return nil } -func (a Artifact) calcCacheKeys(imageID string, diffIDs []string, configFile *v1.ConfigFile) (string, []string, map[string]LayerInfo, error) { +func (a Artifact) calcCacheKeys(imageID string, diffIDs []string) (string, []string, error) { // Pass an empty config scanner option so that the cache key can be the same, even when policies are updated. imageKey, err := cache.CalcKey(imageID, a.analyzer.ImageConfigAnalyzerVersions(), nil, artifact.Option{}) if err != nil { - return "", nil, nil, err + return "", nil, err } - var createdBy []string + hookVersions := a.handlerManager.Versions() + var layerKeys []string + for _, diffID := range diffIDs { + blobKey, err := cache.CalcKey(diffID, a.analyzer.AnalyzerVersions(), hookVersions, a.artifactOption) + if err != nil { + return "", nil, err + } + layerKeys = append(layerKeys, blobKey) + } + return imageKey, layerKeys, nil +} + +func (a Artifact) consolidateCreatedBy(diffIDs, layerKeys []string, configFile *v1.ConfigFile) map[string]LayerInfo { // save createdBy fields in order of layers + var createdBy []string for _, h := range configFile.History { // skip histories for empty layers if h.EmptyLayer { continue } - c := strings.TrimPrefix(strings.TrimPrefix(h.CreatedBy, "/bin/sh -c "), "#(nop) ") + c := strings.TrimPrefix(h.CreatedBy, "/bin/sh -c ") + c = strings.TrimPrefix(c, "#(nop) ") createdBy = append(createdBy, c) } // If history detected incorrect - use only diffID - useCreatedBy := len(diffIDs) == len(createdBy) + // TODO: our current logic may not detect empty layers correctly in rare cases. + validCreatedBy := len(diffIDs) == len(createdBy) layerKeyMap := map[string]LayerInfo{} - hookVersions := a.handlerManager.Versions() - var layerKeys []string for i, diffID := range diffIDs { - blobKey, err := cache.CalcKey(diffID, a.analyzer.AnalyzerVersions(), hookVersions, a.artifactOption) - if err != nil { - return "", nil, nil, err - } - layerKeys = append(layerKeys, blobKey) c := "" - if useCreatedBy { + if validCreatedBy { c = createdBy[i] } - layerKeyMap[blobKey] = LayerInfo{ + + layerKey := layerKeys[i] + layerKeyMap[layerKey] = LayerInfo{ DiffID: diffID, CreatedBy: c, } } - return imageKey, layerKeys, layerKeyMap, nil + return layerKeyMap } func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, baseDiffIDs []string, layerKeyMap map[string]LayerInfo) error { @@ -185,15 +198,15 @@ func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, b var osFound types.OS for _, k := range layerKeys { go func(ctx context.Context, layerKey string) { - lInfo := layerKeyMap[layerKey] + layer := layerKeyMap[layerKey] // If it is a base layer, secret scanning should not be performed. var disabledAnalyers []analyzer.Type - if slices.Contains(baseDiffIDs, lInfo.DiffID) { + if slices.Contains(baseDiffIDs, layer.DiffID) { disabledAnalyers = append(disabledAnalyers, analyzer.TypeSecret) } - layerInfo, err := a.inspectLayer(ctx, lInfo, disabledAnalyers) + layerInfo, err := a.inspectLayer(ctx, layer, disabledAnalyers) if err != nil { errCh <- xerrors.Errorf("failed to analyze layer: %s : %w", layerInfo.DiffID, err) return @@ -265,14 +278,14 @@ func (a Artifact) inspectLayer(ctx context.Context, layerInfo LayerInfo, disable Digest: layerDigest, DiffID: layerInfo.DiffID, CreatedBy: layerInfo.CreatedBy, + OpaqueDirs: opqDirs, + WhiteoutFiles: whFiles, OS: result.OS, Repository: result.Repository, PackageInfos: result.PackageInfos, Applications: result.Applications, Secrets: result.Secrets, Licenses: result.Licenses, - OpaqueDirs: opqDirs, - WhiteoutFiles: whFiles, CustomResources: result.CustomResources, // For Red Hat diff --git a/pkg/fanal/types/artifact.go b/pkg/fanal/types/artifact.go index 291d26e81a5..a2be7e67687 100644 --- a/pkg/fanal/types/artifact.go +++ b/pkg/fanal/types/artifact.go @@ -133,10 +133,16 @@ type ArtifactInfo struct { // BlobInfo is stored in cache type BlobInfo struct { - SchemaVersion int - Digest string `json:",omitempty"` - DiffID string `json:",omitempty"` - CreatedBy string `json:",omitempty"` + SchemaVersion int + + // Layer information + Digest string `json:",omitempty"` + DiffID string `json:",omitempty"` + CreatedBy string `json:",omitempty"` + OpaqueDirs []string `json:",omitempty"` + WhiteoutFiles []string `json:",omitempty"` + + // Analysis result OS *OS `json:",omitempty"` Repository *Repository `json:",omitempty"` PackageInfos []PackageInfo `json:",omitempty"` @@ -144,8 +150,6 @@ type BlobInfo struct { Misconfigurations []Misconfiguration `json:",omitempty"` Secrets []Secret `json:",omitempty"` Licenses []LicenseFile `json:",omitempty"` - OpaqueDirs []string `json:",omitempty"` - WhiteoutFiles []string `json:",omitempty"` // Red Hat distributions have build info per layer. // This information will be embedded into packages when applying layers. From bc6837c9e89b6dbe85193aaadf205cdde6a2c3a3 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Tue, 13 Sep 2022 20:38:43 +0300 Subject: [PATCH 09/13] use v1.History --- pkg/fanal/image/daemon/containerd.go | 6 +- pkg/fanal/image/daemon/docker.go | 2 +- pkg/fanal/image/daemon/image.go | 102 +++++++++++++-------------- pkg/fanal/image/daemon/podman.go | 2 +- 4 files changed, 54 insertions(+), 58 deletions(-) diff --git a/pkg/fanal/image/daemon/containerd.go b/pkg/fanal/image/daemon/containerd.go index 6b2ec56d4ca..8280d57ad1e 100644 --- a/pkg/fanal/image/daemon/containerd.go +++ b/pkg/fanal/image/daemon/containerd.go @@ -97,9 +97,9 @@ func ContainerdImage(ctx context.Context, imageName string) (Image, func(), erro } return &image{ - opener: imageOpener(ctx, ref.String(), f, imageWriter(client, img)), - inspect: insp, - convertedHistory: history, + opener: imageOpener(ctx, ref.String(), f, imageWriter(client, img)), + inspect: insp, + history: history, }, cleanup, nil } diff --git a/pkg/fanal/image/daemon/docker.go b/pkg/fanal/image/daemon/docker.go index 4c3b96c0992..26a707390ca 100644 --- a/pkg/fanal/image/daemon/docker.go +++ b/pkg/fanal/image/daemon/docker.go @@ -56,6 +56,6 @@ func DockerImage(ref name.Reference) (Image, func(), error) { return &image{ opener: imageOpener(context.Background(), imageID, f, c.ImageSave), inspect: inspect, - history: history, + history: configHistory(history), }, cleanup, nil } diff --git a/pkg/fanal/image/daemon/image.go b/pkg/fanal/image/daemon/image.go index 976ea4a97c6..2cce0da1703 100644 --- a/pkg/fanal/image/daemon/image.go +++ b/pkg/fanal/image/daemon/image.go @@ -57,10 +57,9 @@ func imageOpener(ctx context.Context, ref string, f *os.File, imageSave imageSav // To avoid entire loading, this wrapper uses ImageInspectWithRaw and checks image ID and layer IDs. type image struct { v1.Image - opener opener - inspect types.ImageInspect - history []dimage.HistoryResponseItem - convertedHistory []v1.History + opener opener + inspect types.ImageInspect + history []v1.History } // populateImage initializes an "image" struct. @@ -113,7 +112,7 @@ func (img *image) ConfigFile() (*v1.ConfigFile, error) { Created: v1.Time{Time: created}, DockerVersion: img.inspect.DockerVersion, Config: img.imageConfig(img.inspect.Config), - History: img.configHistory(), + History: img.history, OS: img.inspect.Os, RootFS: v1.RootFS{ Type: img.inspect.RootFS.Type, @@ -144,54 +143,6 @@ func (img *image) RepoDigests() []string { return img.inspect.RepoDigests } -func (img *image) configHistory() []v1.History { - // Fill only required metadata - var history []v1.History - - if len(img.convertedHistory) > 0 { - return img.convertedHistory - } - for i := len(img.history) - 1; i >= 0; i-- { - h := img.history[i] - history = append(history, v1.History{ - Created: v1.Time{ - Time: time.Unix(h.Created, 0).UTC(), - }, - CreatedBy: h.CreatedBy, - Comment: h.Comment, - EmptyLayer: emptyLayer(h), - }) - } - return history -} - -func emptyLayer(history dimage.HistoryResponseItem) bool { - if history.Size != 0 { - return false - } - createdBy := strings.TrimSpace(strings.TrimLeft(history.CreatedBy, "/bin/sh -c #(nop)")) - // This logic is taken from https://github.com/moby/buildkit/blob/2942d13ff489a2a49082c99e6104517e357e53ad/frontend/dockerfile/dockerfile2llb/convert.go - if strings.HasPrefix(createdBy, "ENV") || - strings.HasPrefix(createdBy, "MAINTAINER") || - strings.HasPrefix(createdBy, "LABEL") || - strings.HasPrefix(createdBy, "CMD") || - strings.HasPrefix(createdBy, "ENTRYPOINT") || - strings.HasPrefix(createdBy, "HEALTHCHECK") || - strings.HasPrefix(createdBy, "EXPOSE") || - strings.HasPrefix(createdBy, "USER") || - strings.HasPrefix(createdBy, "VOLUME") || - strings.HasPrefix(createdBy, "STOPSIGNAL") || - strings.HasPrefix(createdBy, "SHELL") || - strings.HasPrefix(createdBy, "ARG") || - createdBy == "WORKDIR /" { // only when workdir == "/" then layer is empty - return true - } - // commands here: 'ADD', COPY, RUN and WORKDIR != "/" - // Also RUN command may not include 'RUN' prefix - // e.g. '/bin/sh -c mkdir test ' - return false -} - func (img *image) diffIDs() ([]v1.Hash, error) { var diffIDs []v1.Hash for _, l := range img.inspect.RootFS.Layers { @@ -253,3 +204,48 @@ func (img *image) imageConfig(config *container.Config) v1.Config { return c } + +func configHistory(dhistory []dimage.HistoryResponseItem) []v1.History { + // Fill only required metadata + var history []v1.History + + for i := len(dhistory) - 1; i >= 0; i-- { + h := dhistory[i] + history = append(history, v1.History{ + Created: v1.Time{ + Time: time.Unix(h.Created, 0).UTC(), + }, + CreatedBy: h.CreatedBy, + Comment: h.Comment, + EmptyLayer: emptyLayer(h), + }) + } + return history +} + +func emptyLayer(history dimage.HistoryResponseItem) bool { + if history.Size != 0 { + return false + } + createdBy := strings.TrimSpace(strings.TrimLeft(history.CreatedBy, "/bin/sh -c #(nop)")) + // This logic is taken from https://github.com/moby/buildkit/blob/2942d13ff489a2a49082c99e6104517e357e53ad/frontend/dockerfile/dockerfile2llb/convert.go + if strings.HasPrefix(createdBy, "ENV") || + strings.HasPrefix(createdBy, "MAINTAINER") || + strings.HasPrefix(createdBy, "LABEL") || + strings.HasPrefix(createdBy, "CMD") || + strings.HasPrefix(createdBy, "ENTRYPOINT") || + strings.HasPrefix(createdBy, "HEALTHCHECK") || + strings.HasPrefix(createdBy, "EXPOSE") || + strings.HasPrefix(createdBy, "USER") || + strings.HasPrefix(createdBy, "VOLUME") || + strings.HasPrefix(createdBy, "STOPSIGNAL") || + strings.HasPrefix(createdBy, "SHELL") || + strings.HasPrefix(createdBy, "ARG") || + createdBy == "WORKDIR /" { // only when workdir == "/" then layer is empty + return true + } + // commands here: 'ADD', COPY, RUN and WORKDIR != "/" + // Also RUN command may not include 'RUN' prefix + // e.g. '/bin/sh -c mkdir test ' + return false +} diff --git a/pkg/fanal/image/daemon/podman.go b/pkg/fanal/image/daemon/podman.go index db282e69ea4..399fff96602 100644 --- a/pkg/fanal/image/daemon/podman.go +++ b/pkg/fanal/image/daemon/podman.go @@ -139,6 +139,6 @@ func PodmanImage(ref string) (Image, func(), error) { return &image{ opener: imageOpener(context.Background(), ref, f, c.imageSave), inspect: inspect, - history: history, + history: configHistory(history), }, cleanup, nil } From 68d584bb78580038b7ca157ef017708b83a6158c Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Tue, 13 Sep 2022 20:51:31 +0300 Subject: [PATCH 10/13] remove cruft --- pkg/fanal/test/integration/library_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/fanal/test/integration/library_test.go b/pkg/fanal/test/integration/library_test.go index 7d853a6fc4e..df496704de1 100644 --- a/pkg/fanal/test/integration/library_test.go +++ b/pkg/fanal/test/integration/library_test.go @@ -43,7 +43,7 @@ type testCase struct { } var tests = []testCase{ - /*{ + { name: "happy path, alpine:3.10", remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", imageFile: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", @@ -91,7 +91,7 @@ var tests = []testCase{ remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:fedora-35", imageFile: "../../../../integration/testdata/fixtures/images/fedora-35.tar.gz", wantOS: types.OS{Name: "35", Family: "fedora"}, - },*/ + }, { name: "happy path, vulnimage with lock files", remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:vulnimage", From be1bddc2ffea0310a0e28d9cf53452adfe91e4b9 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Tue, 13 Sep 2022 20:51:47 +0300 Subject: [PATCH 11/13] do not show note when diff_id is empty --- pkg/report/table/secret.go | 10 +++++----- pkg/report/table/secret_test.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/report/table/secret.go b/pkg/report/table/secret.go index 9c70334447f..b8ad688dce3 100644 --- a/pkg/report/table/secret.go +++ b/pkg/report/table/secret.go @@ -123,12 +123,12 @@ func (r *secretRenderer) renderCode(secret types.SecretFinding) { var note string if c := secret.Layer.CreatedBy; c != "" { if len(c) < 40 { - note = fmt.Sprintf(" (added by '%s')", c) - } else { - note = fmt.Sprintf(" (added by '%s')", c[:40]) + // Too long + c = c[:40] } - } else { - note = fmt.Sprintf(" (added by '%s' layer)", strings.TrimPrefix(secret.Layer.DiffID, "sha256:")[:8]) + note = fmt.Sprintf(" (added by '%s')", c) + } else if secret.Layer.DiffID != "" { + note = fmt.Sprintf(" (added in layer '%s')", strings.TrimPrefix(secret.Layer.DiffID, "sha256:")[:12]) } r.printf(" %s%s%s\r\n", r.target, lineInfo, note) r.printSingleDivider() diff --git a/pkg/report/table/secret_test.go b/pkg/report/table/secret_test.go index 6bf73893076..5f19db9a076 100644 --- a/pkg/report/table/secret_test.go +++ b/pkg/report/table/secret_test.go @@ -53,7 +53,7 @@ HIGH: category (rule-id) ════════════════════════════════════════ this is a title ──────────────────────────────────────── - my-file:1 (added by 'beee9f30' layer) + my-file:1 (added in layer 'beee9f30bc1f') ──────────────────────────────────────── 1 [ password=secret ──────────────────────────────────────── From 5817684c8fd1e4dbe86bd93a692e05f853a300c7 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Tue, 13 Sep 2022 20:58:36 +0300 Subject: [PATCH 12/13] rpc: use reserved for deprecated fields --- rpc/common/service.pb.go | 36 ++++++++++++++++++------------------ rpc/common/service.proto | 4 +++- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/rpc/common/service.pb.go b/rpc/common/service.pb.go index cfd71f49bea..bd3b842a3bb 100644 --- a/rpc/common/service.pb.go +++ b/rpc/common/service.pb.go @@ -1423,7 +1423,7 @@ type SecretFinding struct { EndLine int32 `protobuf:"varint,6,opt,name=end_line,json=endLine,proto3" json:"end_line,omitempty"` Code *Code `protobuf:"bytes,7,opt,name=code,proto3" json:"code,omitempty"` Match string `protobuf:"bytes,8,opt,name=match,proto3" json:"match,omitempty"` - Layer *Layer `protobuf:"bytes,9,opt,name=layer,proto3" json:"layer,omitempty"` + Layer *Layer `protobuf:"bytes,10,opt,name=layer,proto3" json:"layer,omitempty"` } func (x *SecretFinding) Reset() { @@ -1805,7 +1805,7 @@ var file_rpc_common_service_proto_rawDesc = []byte{ 0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x99, 0x02, 0x0a, + 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x9f, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, @@ -1821,23 +1821,23 @@ var file_rpc_common_service_proto_rawDesc = []byte{ 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x29, 0x0a, - 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, + 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, - 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x12, 0x37, - 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, - 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2a, 0x44, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, - 0x69, 0x74, 0x79, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x44, - 0x49, 0x55, 0x4d, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x49, 0x47, 0x48, 0x10, 0x03, 0x12, - 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x04, 0x42, 0x31, 0x5a, - 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, - 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0x5d, + 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, + 0x70, 0x61, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2a, 0x44, 0x0a, + 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, + 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, + 0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x44, 0x49, 0x55, 0x4d, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x48, + 0x49, 0x47, 0x48, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43, 0x41, + 0x4c, 0x10, 0x04, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, + 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3b, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/rpc/common/service.proto b/rpc/common/service.proto index d513ee5268c..d6d61a5c6e0 100644 --- a/rpc/common/service.proto +++ b/rpc/common/service.proto @@ -166,7 +166,9 @@ message SecretFinding { int32 end_line = 6; Code code = 7; string match = 8; - Layer layer = 9; + Layer layer = 10; + + reserved 9; // deprecated 'deleted' } message Secret { From 605c02e67df00b31b639b32e333027c1e5ecb16b Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Tue, 13 Sep 2022 21:20:32 +0300 Subject: [PATCH 13/13] fix a bug --- pkg/report/table/secret.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/report/table/secret.go b/pkg/report/table/secret.go index b8ad688dce3..0d1b228ecc1 100644 --- a/pkg/report/table/secret.go +++ b/pkg/report/table/secret.go @@ -122,7 +122,7 @@ func (r *secretRenderer) renderCode(secret types.SecretFinding) { var note string if c := secret.Layer.CreatedBy; c != "" { - if len(c) < 40 { + if len(c) > 40 { // Too long c = c[:40] }