New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(secret): add line from dockerfile where secret was added to secret result #2780
Changes from 4 commits
0b570bc
91d7cef
ab8ea1a
67c70da
70384d9
c0b43d2
894c8c4
f8c6387
7a889eb
1e073b2
bc6837c
68d584b
be1bddc
5817684
605c02e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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,65 @@ 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] | ||||||
// skip histories for empty layers | ||||||
if h.EmptyLayer { | ||||||
continue | ||||||
} | ||||||
c := strings.TrimPrefix(strings.TrimPrefix(h.CreatedBy, "/bin/sh -c "), "#(nop) ") | ||||||
createdBy = append(createdBy, c) | ||||||
} | ||||||
|
||||||
layerKeyMap := map[string]LayerInfo{} | ||||||
hookVersions := a.handlerManager.Versions() | ||||||
var layerKeys []string | ||||||
for _, diffID := range diffIDs { | ||||||
for i, diffID := range diffIDs { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should compare |
||||||
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 | ||||||
|
||||||
c := "" | ||||||
if len(createdBy) > 0 { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
c = createdBy[i] | ||||||
} | ||||||
layerKeyMap[blobKey] = LayerInfo{ | ||||||
DiffID: diffID, | ||||||
CreatedBy: c, | ||||||
} | ||||||
} | ||||||
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 +230,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 +264,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, | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,6 @@ type SecretFinding struct { | |
EndLine int | ||
Code Code | ||
Match string | ||
Deleted bool | ||
Layer Layer `json:",omitempty"` | ||
CreatedBy string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if we put There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DOne |
||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -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' | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After some consideration, I came up with another idea. One line looks better. If it has a file hash, what if we take the first 7 characters like
Suggested change
Then, if it is still too long, we can cut it like the first 40 chars, etc. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||
──────────────────────────────────────── | ||||||||||
1 #!/bin/bash | ||||||||||
2 | ||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done