Skip to content

Commit

Permalink
feat(misconf): support for ignoring by inline comments for Dockerfile (
Browse files Browse the repository at this point in the history
…#8115)

Signed-off-by: nikpivkin <[email protected]>
  • Loading branch information
nikpivkin authored Jan 20, 2025
1 parent 6d84e0c commit c002327
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 2 deletions.
11 changes: 9 additions & 2 deletions docs/docs/scanner/misconfiguration/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,9 @@ From the Terraform [docs](https://developer.hashicorp.com/terraform/cli/config/c
If multiple variables evaluate to the same hostname, Trivy will choose the environment variable name where the dashes have not been encoded as double underscores.
### Skipping resources by inline comments
### Skipping detected misconfigurations by inline comments
Trivy supports ignoring misconfigured resources by inline comments for Terraform, CloudFormation and Helm configuration files only.
Trivy supports ignoring detected misconfigurations by inline comments for Terraform, CloudFormation (YAML), Helm and Dockerfile configuration files only.
In cases where Trivy can detect comments of a specific format immediately adjacent to resource definitions, it is possible to ignore findings from a single source of resource definition (in contrast to `.trivyignore`, which has a directory-wide scope on all of the files scanned). The format for these comments is `trivy:ignore:<rule>` immediately following the format-specific line-comment [token](https://developer.hashicorp.com/terraform/language/syntax/configuration#comments).
Expand Down Expand Up @@ -519,6 +519,13 @@ Example for Helm:
imagePullPolicy: "Always"
```
Example for Dockerfile:
```Dockerfile
FROM scratch
# trivy:ignore:AVD-DS-0022
MAINTAINER [email protected]
```
#### Expiration Date
You can specify the expiration date of the ignore rule in `yyyy-mm-dd` format. This is a useful feature when you want to make sure that an ignored issue is not forgotten and worth revisiting in the future. For example:
Expand Down
72 changes: 72 additions & 0 deletions pkg/iac/scanners/dockerfile/scanner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package dockerfile_test
import (
"bytes"
"context"
"strings"
"testing"
"testing/fstest"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -630,3 +632,73 @@ COPY --from=dep /binary /`
}

}

func Test_IgnoreByInlineComments(t *testing.T) {
tests := []struct {
name string
src string
expected bool
}{
{
name: "without ignore rule",
src: `FROM scratch
MAINTAINER [email protected]`,
expected: true,
},
{
name: "with ignore rule",
src: `FROM scratch
# trivy:ignore:USER-TEST-0001
MAINTAINER [email protected]`,
expected: false,
},
}

check := `# METADATA
# title: test
# schemas:
# - input: schema["dockerfile"]
# custom:
# avd_id: USER-TEST-0001
# short_code: maintainer-deprecated
# input:
# selector:
# - type: dockerfile
package user.test0001
import rego.v1
get_maintainer contains cmd if {
cmd := input.Stages[_].Commands[_]
cmd.Cmd == "maintainer"
}
deny contains res if {
cmd := get_maintainer[_]
msg := sprintf("MAINTAINER should not be used: 'MAINTAINER %s'", [cmd.Value[0]])
res := result.new(msg, cmd)
}
`

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fsys := fstest.MapFS{
"Dockerfile": &fstest.MapFile{Data: []byte(tt.src)},
}

scanner := dockerfile.NewScanner(
rego.WithPolicyReader(strings.NewReader(check)),
rego.WithPolicyNamespaces("user"),
rego.WithEmbeddedLibraries(true),
rego.WithRegoErrorLimits(0),
)
results, err := scanner.ScanFS(context.TODO(), fsys, ".")
require.NoError(t, err)
if tt.expected {
testutil.AssertRuleFound(t, "dockerfile-general-maintainer-deprecated", results, "")
} else {
testutil.AssertRuleNotFailed(t, "dockerfile-general-maintainer-deprecated", results, "")
}
})
}
}
32 changes: 32 additions & 0 deletions pkg/iac/scanners/generic/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import (
"sync"

"github.com/BurntSushi/toml"
"github.com/samber/lo"
"gopkg.in/yaml.v3"

"github.com/aquasecurity/trivy/pkg/iac/ignore"
"github.com/aquasecurity/trivy/pkg/iac/rego"
"github.com/aquasecurity/trivy/pkg/iac/scan"
"github.com/aquasecurity/trivy/pkg/iac/scanners/options"
Expand Down Expand Up @@ -122,9 +124,18 @@ func (s *GenericScanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (sc
return nil, err
}
results.SetSourceAndFilesystem("", fsys, false)

if err := s.applyIgnoreRules(fsys, results); err != nil {
return nil, err
}

return results, nil
}

func (s *GenericScanner) supportsIgnoreRules() bool {
return s.source == types.SourceDockerfile
}

func (s *GenericScanner) parseFS(ctx context.Context, fsys fs.FS, path string) (map[string]any, error) {
files := make(map[string]any)
if err := fs.WalkDir(fsys, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error {
Expand Down Expand Up @@ -173,6 +184,27 @@ func (s *GenericScanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) {
return regoScanner, nil
}

func (s *GenericScanner) applyIgnoreRules(fsys fs.FS, results scan.Results) error {
if !s.supportsIgnoreRules() {
return nil
}

uniqueFiles := lo.Uniq(lo.Map(results.GetFailed(), func(res scan.Result, _ int) string {
return res.Metadata().Range().GetFilename()
}))

for _, filename := range uniqueFiles {
content, err := fs.ReadFile(fsys, filename)
if err != nil {
return err
}

ignoreRules := ignore.Parse(string(content), filename, "")
results.Ignore(ignoreRules, nil)
}
return nil
}

func parseJson(ctx context.Context, r io.Reader, _ string) (any, error) {
var target any
if err := json.NewDecoder(r).Decode(&target); err != nil {
Expand Down

0 comments on commit c002327

Please sign in to comment.