mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-05 20:40:16 -08:00
fix(misconf): move disabled checks filtering after analyzer scan (#9002)
Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io>
This commit is contained in:
@@ -14,21 +14,17 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/detection"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/mapfs"
|
||||
"github.com/aquasecurity/trivy/pkg/misconf"
|
||||
"github.com/aquasecurity/trivy/pkg/set"
|
||||
"github.com/aquasecurity/trivy/pkg/version/doc"
|
||||
)
|
||||
|
||||
var disabledChecks = []misconf.DisabledCheck{
|
||||
{
|
||||
ID: "DS007", Scanner: string(analyzer.TypeHistoryDockerfile),
|
||||
Reason: "See " + doc.URL("docs/target/container_image", "disabled-checks"),
|
||||
},
|
||||
{
|
||||
ID: "DS016", Scanner: string(analyzer.TypeHistoryDockerfile),
|
||||
Reason: "See " + doc.URL("docs/target/container_image", "disabled-checks"),
|
||||
},
|
||||
}
|
||||
var (
|
||||
disabledChecks = set.New("AVD-DS-0007", "AVD-DS-0016")
|
||||
reason = "See " + doc.URL("docs/target/container_image", "disabled-checks")
|
||||
)
|
||||
|
||||
const analyzerVersion = 1
|
||||
|
||||
@@ -41,7 +37,6 @@ type historyAnalyzer struct {
|
||||
}
|
||||
|
||||
func newHistoryAnalyzer(opts analyzer.ConfigAnalyzerOptions) (analyzer.ConfigAnalyzer, error) {
|
||||
opts.MisconfScannerOption.DisabledChecks = append(opts.MisconfScannerOption.DisabledChecks, disabledChecks...)
|
||||
s, err := misconf.NewScanner(detection.FileTypeDockerfile, opts.MisconfScannerOption)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("misconfiguration scanner error: %w", err)
|
||||
@@ -72,8 +67,10 @@ func (a *historyAnalyzer) Analyze(ctx context.Context, input analyzer.ConfigAnal
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
misconfig := misconfs[0]
|
||||
misconfig.Failures = filterDisabledChecks(misconfig.Failures)
|
||||
return &analyzer.ConfigAnalysisResult{
|
||||
Misconfiguration: &misconfs[0],
|
||||
Misconfiguration: &misconfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -174,3 +171,16 @@ func (a *historyAnalyzer) Type() analyzer.Type {
|
||||
func (a *historyAnalyzer) Version() int {
|
||||
return analyzerVersion
|
||||
}
|
||||
|
||||
func filterDisabledChecks(results types.MisconfResults) types.MisconfResults {
|
||||
var filtered types.MisconfResults
|
||||
for _, r := range results {
|
||||
if disabledChecks.Contains(r.AVDID) {
|
||||
log.WithPrefix("image history analyzer").Info("Skip disabled check",
|
||||
log.String("ID", r.AVDID), log.String("reason", reason))
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, r)
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
@@ -378,11 +378,6 @@ func (s *Scanner) isModuleApplicable(module *ast.Module, metadata *StaticMetadat
|
||||
return false
|
||||
}
|
||||
|
||||
// ignore disabled built-in checks
|
||||
if IsBuiltinNamespace(getModuleNamespace(module)) && s.disabledCheckIDs.Contains(metadata.ID) {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(metadata.InputOptions.Selectors) == 0 && !metadata.Library {
|
||||
s.logger.Warn(
|
||||
"Module has no input selectors - it will be loaded for all inputs",
|
||||
|
||||
@@ -106,15 +106,6 @@ func WithCustomSchemas(schemas map[string][]byte) options.ScannerOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDisabledCheckIDs disables checks by their ID (ID field in metadata)
|
||||
func WithDisabledCheckIDs(ids ...string) options.ScannerOption {
|
||||
return func(s options.ConfigurableScanner) {
|
||||
if ss, ok := s.(*Scanner); ok {
|
||||
ss.disabledCheckIDs.Append(ids...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithIncludeDeprecatedChecks(include bool) options.ScannerOption {
|
||||
return func(s options.ConfigurableScanner) {
|
||||
if ss, ok := s.(*Scanner); ok {
|
||||
|
||||
@@ -67,8 +67,6 @@ type Scanner struct {
|
||||
embeddedLibs map[string]*ast.Module
|
||||
embeddedChecks map[string]*ast.Module
|
||||
customSchemas map[string][]byte
|
||||
|
||||
disabledCheckIDs set.Set[string]
|
||||
}
|
||||
|
||||
func (s *Scanner) trace(heading string, input any) {
|
||||
@@ -94,14 +92,13 @@ func NewScanner(opts ...options.ScannerOption) *Scanner {
|
||||
LoadAndRegister()
|
||||
|
||||
s := &Scanner{
|
||||
regoErrorLimit: ast.CompileErrorLimitDefault,
|
||||
ruleNamespaces: builtinNamespaces.Clone(),
|
||||
runtimeValues: addRuntimeValues(),
|
||||
logger: log.WithPrefix("rego"),
|
||||
customSchemas: make(map[string][]byte),
|
||||
disabledCheckIDs: set.New[string](),
|
||||
moduleMetadata: make(map[string]*StaticMetadata),
|
||||
trivyVersion: app.Version(),
|
||||
regoErrorLimit: ast.CompileErrorLimitDefault,
|
||||
ruleNamespaces: builtinNamespaces.Clone(),
|
||||
runtimeValues: addRuntimeValues(),
|
||||
logger: log.WithPrefix("rego"),
|
||||
customSchemas: make(map[string][]byte),
|
||||
moduleMetadata: make(map[string]*StaticMetadata),
|
||||
trivyVersion: app.Version(),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
|
||||
@@ -1107,86 +1107,3 @@ deny {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_RegoScanner_WithDisabledCheckIDs(t *testing.T) {
|
||||
|
||||
check := `# METADATA
|
||||
# custom:
|
||||
# id: TEST-001
|
||||
# avd_id: AVD-TEST-001
|
||||
# severity: LOW
|
||||
# provider: aws
|
||||
# service: s3
|
||||
# short_code: test
|
||||
package builtin.test
|
||||
|
||||
deny {
|
||||
true
|
||||
}
|
||||
`
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
disabledChecks []string
|
||||
inputCheck string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "no disabled checks",
|
||||
expected: true,
|
||||
inputCheck: check,
|
||||
},
|
||||
{
|
||||
name: "disable check by ID",
|
||||
disabledChecks: []string{"TEST-001"},
|
||||
inputCheck: check,
|
||||
},
|
||||
{
|
||||
name: "disabling a non-existent check",
|
||||
disabledChecks: []string{"FOO"},
|
||||
expected: true,
|
||||
inputCheck: check,
|
||||
},
|
||||
{
|
||||
name: "one of the identifiers does not exist",
|
||||
disabledChecks: []string{"FOO", "TEST-001"},
|
||||
inputCheck: check,
|
||||
},
|
||||
{
|
||||
name: "do not disable user checks with builtin IDs",
|
||||
inputCheck: `# METADATA
|
||||
# custom:
|
||||
# id: TEST-001
|
||||
# avd_id: AVD-TEST-001
|
||||
# severity: LOW
|
||||
# provider: aws
|
||||
# service: s3
|
||||
# short_code: test
|
||||
package user.test
|
||||
|
||||
deny {
|
||||
true
|
||||
}
|
||||
`,
|
||||
disabledChecks: []string{"TEST-001"},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
scanner := rego.NewScanner(
|
||||
rego.WithPolicyReader(strings.NewReader(tt.inputCheck)),
|
||||
rego.WithDisabledCheckIDs(tt.disabledChecks...),
|
||||
rego.WithPolicyNamespaces("user"),
|
||||
)
|
||||
|
||||
require.NoError(t, scanner.LoadPolicies(nil))
|
||||
results, err := scanner.ScanInput(t.Context(), types.SourceYAML, rego.Input{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tt.expected, len(results.GetFailed()) > 0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,12 +52,6 @@ var enablediacTypes = map[detection.FileType]types.ConfigType{
|
||||
detection.FileTypeYAML: types.YAML,
|
||||
}
|
||||
|
||||
type DisabledCheck struct {
|
||||
ID string
|
||||
Scanner string // For logging
|
||||
Reason string // For logging
|
||||
}
|
||||
|
||||
type ScannerOption struct {
|
||||
Trace bool
|
||||
Namespaces []string
|
||||
@@ -82,9 +76,8 @@ type ScannerOption struct {
|
||||
FilePatterns []string
|
||||
ConfigFileSchemas []*ConfigFileSchema
|
||||
|
||||
DisabledChecks []DisabledCheck
|
||||
SkipFiles []string
|
||||
SkipDirs []string
|
||||
SkipFiles []string
|
||||
SkipDirs []string
|
||||
|
||||
RegoScanner *rego.Scanner
|
||||
}
|
||||
@@ -236,17 +229,10 @@ func InitRegoScanner(opt ScannerOption) (*rego.Scanner, error) {
|
||||
}
|
||||
|
||||
func initRegoOptions(opt ScannerOption) ([]options.ScannerOption, error) {
|
||||
disabledCheckIDs := lo.Map(opt.DisabledChecks, func(check DisabledCheck, _ int) string {
|
||||
log.Info("Check disabled", log.Prefix(log.PrefixMisconfiguration), log.String("ID", check.ID),
|
||||
log.String("scanner", check.Scanner), log.String("reason", check.Reason))
|
||||
return check.ID
|
||||
})
|
||||
|
||||
opts := []options.ScannerOption{
|
||||
rego.WithEmbeddedPolicies(!opt.DisableEmbeddedPolicies),
|
||||
rego.WithEmbeddedLibraries(!opt.DisableEmbeddedLibraries),
|
||||
rego.WithIncludeDeprecatedChecks(opt.IncludeDeprecatedChecks),
|
||||
rego.WithDisabledCheckIDs(disabledCheckIDs...),
|
||||
rego.WithTrivyVersion(app.Version()),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user