Skip to content

Commit 4337068

Browse files
authored
fix(misconf): avoid panic if the scheme is not valid (aquasecurity#6496)
1 parent d82d6cb commit 4337068

File tree

5 files changed

+94
-50
lines changed

5 files changed

+94
-50
lines changed

pkg/iac/rego/build.go

+24-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package rego
22

33
import (
4+
"fmt"
45
"io/fs"
56
"path/filepath"
67
"strings"
@@ -16,28 +17,37 @@ func BuildSchemaSetFromPolicies(policies map[string]*ast.Module, paths []string,
1617
schemaSet := ast.NewSchemaSet()
1718
schemaSet.Put(ast.MustParseRef("schema.input"), make(map[string]interface{})) // for backwards compat only
1819
var customFound bool
20+
1921
for _, policy := range policies {
2022
for _, annotation := range policy.Annotations {
2123
for _, ss := range annotation.Schemas {
2224
schemaName, err := ss.Schema.Ptr()
23-
if err != nil {
25+
if err != nil || schemaName == "input" {
2426
continue
2527
}
26-
if schemaName != "input" {
27-
if schema, ok := schemas.SchemaMap[types.Source(schemaName)]; ok {
28-
customFound = true
29-
schemaSet.Put(ast.MustParseRef(ss.Schema.String()), util.MustUnmarshalJSON([]byte(schema)))
30-
} else {
31-
b, err := findSchemaInFS(paths, fsys, schemaName)
32-
if err != nil {
33-
return schemaSet, true, err
34-
}
35-
if b != nil {
36-
customFound = true
37-
schemaSet.Put(ast.MustParseRef(ss.Schema.String()), util.MustUnmarshalJSON(b))
38-
}
28+
29+
var schema []byte
30+
if s, ok := schemas.SchemaMap[types.Source(schemaName)]; ok {
31+
schema = []byte(s)
32+
} else {
33+
b, err := findSchemaInFS(paths, fsys, schemaName)
34+
if err != nil {
35+
return schemaSet, true, err
36+
}
37+
38+
if b == nil {
39+
return nil, false, fmt.Errorf("could not find schema %q", schemaName)
3940
}
41+
42+
schema = b
43+
}
44+
45+
var rawSchema any
46+
if err := util.UnmarshalJSON(schema, &rawSchema); err != nil {
47+
return schemaSet, false, fmt.Errorf("could not parse schema %q: %w", schemaName, err)
4048
}
49+
customFound = true
50+
schemaSet.Put(ast.MustParseRef(ss.Schema.String()), rawSchema)
4151
}
4252
}
4353
}

pkg/iac/rego/embed_test.go

-18
Original file line numberDiff line numberDiff line change
@@ -80,24 +80,6 @@ deny[res]{
8080
res := true
8181
}`,
8282
},
83-
{
84-
name: "sad path schema does not exist",
85-
inputPolicy: `# METADATA
86-
# title: "dummy title"
87-
# description: "some description"
88-
# scope: package
89-
# schemas:
90-
# - input: schema["invalid schema"]
91-
# custom:
92-
# input:
93-
# selector:
94-
# - type: dockerfile
95-
package builtin.dockerfile.DS1234
96-
deny[res]{
97-
res := true
98-
}`,
99-
expectedError: true,
100-
},
10183
}
10284

10385
for _, tc := range testCases {

pkg/iac/rego/load_test.go

+68-17
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
package rego
1+
package rego_test
22

33
import (
44
"bytes"
55
"embed"
6+
"io"
7+
"strings"
68
"testing"
9+
"testing/fstest"
710

8-
"github.com/aquasecurity/trivy/pkg/iac/types"
911
"github.com/stretchr/testify/assert"
1012
"github.com/stretchr/testify/require"
13+
14+
"github.com/aquasecurity/trivy/pkg/iac/rego"
15+
"github.com/aquasecurity/trivy/pkg/iac/scanners/options"
16+
"github.com/aquasecurity/trivy/pkg/iac/types"
1117
)
1218

1319
//go:embed all:testdata/policies
@@ -16,31 +22,76 @@ var testEmbedFS embed.FS
1622
func Test_RegoScanning_WithSomeInvalidPolicies(t *testing.T) {
1723
t.Run("allow no errors", func(t *testing.T) {
1824
var debugBuf bytes.Buffer
19-
scanner := NewScanner(types.SourceDockerfile)
20-
scanner.SetRegoErrorLimit(0)
21-
scanner.SetDebugWriter(&debugBuf)
22-
p, _ := LoadPoliciesFromDirs(testEmbedFS, ".")
23-
require.NotNil(t, p)
24-
25-
scanner.policies = p
26-
err := scanner.compilePolicies(testEmbedFS, []string{"policies"})
25+
scanner := rego.NewScanner(
26+
types.SourceDockerfile,
27+
options.ScannerWithRegoErrorLimits(0),
28+
options.ScannerWithDebug(&debugBuf),
29+
)
30+
31+
err := scanner.LoadPolicies(false, false, testEmbedFS, []string{"."}, nil)
2732
require.ErrorContains(t, err, `want (one of): ["Cmd" "EndLine" "Flags" "JSON" "Original" "Path" "Stage" "StartLine" "SubCmd" "Value"]`)
2833
assert.Contains(t, debugBuf.String(), "Error(s) occurred while loading policies")
2934
})
3035

3136
t.Run("allow up to max 1 error", func(t *testing.T) {
3237
var debugBuf bytes.Buffer
33-
scanner := NewScanner(types.SourceDockerfile)
34-
scanner.SetRegoErrorLimit(1)
35-
scanner.SetDebugWriter(&debugBuf)
36-
37-
p, _ := LoadPoliciesFromDirs(testEmbedFS, ".")
38-
scanner.policies = p
38+
scanner := rego.NewScanner(
39+
types.SourceDockerfile,
40+
options.ScannerWithRegoErrorLimits(1),
41+
options.ScannerWithDebug(&debugBuf),
42+
)
3943

40-
err := scanner.compilePolicies(testEmbedFS, []string{"policies"})
44+
err := scanner.LoadPolicies(false, false, testEmbedFS, []string{"."}, nil)
4145
require.NoError(t, err)
4246

4347
assert.Contains(t, debugBuf.String(), "Error occurred while parsing: testdata/policies/invalid.rego, testdata/policies/invalid.rego:7")
4448
})
4549

50+
t.Run("schema does not exist", func(t *testing.T) {
51+
check := `# METADATA
52+
# schemas:
53+
# - input: schema["fooschema"]
54+
package mypackage
55+
56+
deny {
57+
input.evil == "foo bar"
58+
}`
59+
scanner := rego.NewScanner(types.SourceJSON)
60+
61+
err := scanner.LoadPolicies(false, false, fstest.MapFS{}, []string{"."}, []io.Reader{strings.NewReader(check)})
62+
assert.ErrorContains(t, err, "could not find schema \"fooschema\"")
63+
})
64+
65+
t.Run("schema is invalid", func(t *testing.T) {
66+
check := `# METADATA
67+
# schemas:
68+
# - input: schema["fooschema"]
69+
package mypackage
70+
71+
deny {
72+
input.evil == "foo bar"
73+
}`
74+
scanner := rego.NewScanner(types.SourceJSON)
75+
76+
fsys := fstest.MapFS{
77+
"schemas/fooschema.json": &fstest.MapFile{
78+
Data: []byte("bad json"),
79+
},
80+
}
81+
82+
err := scanner.LoadPolicies(false, false, fsys, []string{"."}, []io.Reader{strings.NewReader(check)})
83+
assert.ErrorContains(t, err, "could not parse schema \"fooschema\"")
84+
})
85+
86+
t.Run("schema is not specified", func(t *testing.T) {
87+
check := `package mypackage
88+
89+
deny {
90+
input.evil == "foo bar"
91+
}`
92+
scanner := rego.NewScanner(types.SourceJSON)
93+
err := scanner.LoadPolicies(false, false, fstest.MapFS{}, []string{"."}, []io.Reader{strings.NewReader(check)})
94+
assert.NoError(t, err)
95+
})
96+
4697
}

pkg/iac/scanners/dockerfile/scanner_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ package builtin.dockerfile.DS006
546546
deny[res]{
547547
res := true
548548
}`,
549-
expectedError: `1 error occurred: rules/rule.rego:12: rego_type_error: undefined schema: schema["spooky-schema"]`,
549+
expectedError: "could not find schema \"spooky-schema\"",
550550
},
551551
}
552552

pkg/iac/scanners/terraform/scanner_integration_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ deny[cause] {
161161

162162
t.Run("without skip", func(t *testing.T) {
163163
scanner := New(
164+
ScannerWithSkipCachedModules(true),
164165
options.ScannerWithPolicyDirs("rules"),
165166
options.ScannerWithRegoOnly(true),
166167
options.ScannerWithEmbeddedPolicies(false),

0 commit comments

Comments
 (0)