Skip to content

Commit 86d8353

Browse files
committed
chore: improve test-coverage of yaml runtime
1 parent a08622f commit 86d8353

File tree

8 files changed

+327
-18
lines changed

8 files changed

+327
-18
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
language: java
2+
name: malformed_path
3+
message: "Testing"
4+
category: security
5+
severity: critical
6+
7+
pattern: >
8+
(method_invocation
9+
object: (identifier) @cipherClass
10+
name: (identifier) @instanceMethod
11+
arguments: (argument_list
12+
(string_literal
13+
(string_fragment) @str))
14+
(#match? @str ".*CBC.*PKCS5Padding")
15+
(#eq? @cipherClass "Cipher")
16+
(#eq? @instanceMethod "getInstance")) @cbc-padding-oracle
17+
18+
19+
exclude:
20+
- "file[.js"
21+
22+
description: >
23+
test
24+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
language: java
2+
name: cbc-padding-oracle
3+
message: "Using CBC mode with PKCS5Padding can cause padding oracle attacks"
4+
category: security
5+
severity: critical
6+
7+
pattern: >
8+
(method_invocation
9+
object: (identifier) @cipherClass
10+
name: (identifier) @instanceMethod
11+
arguments: (argument_list
12+
(string_literal
13+
(string_fragment) @str))
14+
(#match? @str ".*CBC.*PKCS5Padding")
15+
(#eq? @cipherClass "Cipher")
16+
(#eq? @instanceMethod "getInstance")) @cbc-padding-oracle
17+
18+
19+
exclude:
20+
- "tests/**"
21+
- "vendor/**"
22+
- "**/Test_*.java"
23+
- "**/*Test.java"
24+
25+
include:
26+
- "*.java"
27+
28+
description: >
29+
Java applications using CBC mode with PKCS5Padding for encryption are vulnerable to padding oracle attacks, where attackers can distinguish between valid and invalid padding to potentially decrypt sensitive data without knowing the encryption key. This vulnerability is compounded by CBC mode's lack of built-in integrity checks. The recommended approach is using AES/GCM/NoPadding instead, which provides both confidentiality and integrity protection through authenticated encryption.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
language: javascript
2+
name: multi-pattern
3+
message: "Checking precense of multiple patterns"
4+
category: style
5+
severity: info
6+
patterns:
7+
- >
8+
(call_expression)
9+
- >
10+
(function_declaration)
11+
description: "Test checker no-pattern"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
language: javascript
2+
name: no-pattern
3+
message: "Checking absence of Patterns"
4+
category: style
5+
severity: info
6+
pattern:
7+
description: "Test checker no-pattern"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
language: javascript
2+
name: single-multiple
3+
message: "Checking precense of multiple patterns and single pattern"
4+
category: style
5+
severity: info
6+
pattern: (call_expression)
7+
patterns:
8+
- >
9+
(call_expression)
10+
- >
11+
(function_declaration)
12+
description: "Test checker no-pattern"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
language: javascript
2+
name: wrong-pattern
3+
message: "Checking wrong pattern presence"
4+
category: style
5+
severity: info
6+
pattern: "hello world"
7+
description: "Test checker no-pattern"

analysis/yaml.go

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,9 @@ func ReadFromBytes(fileContent []byte) (Analyzer, YamlAnalyzer, error) {
8787
return Analyzer{}, YamlAnalyzer{}, err
8888
}
8989

90-
lang := DecodeLanguage(checker.Language)
91-
if lang == LangUnknown {
92-
return Analyzer{}, YamlAnalyzer{}, fmt.Errorf("unknown language code: '%s'", checker.Language)
93-
}
94-
95-
if checker.Code == "" {
96-
return Analyzer{}, YamlAnalyzer{}, fmt.Errorf("no name provided in checker definition")
97-
}
98-
99-
if checker.Message == "" {
100-
return Analyzer{}, YamlAnalyzer{}, fmt.Errorf("no message provided in checker '%s'", checker.Code)
90+
lang, code, message, err := verifyChecker(checker)
91+
if err != nil {
92+
return Analyzer{}, YamlAnalyzer{}, err
10193
}
10294

10395
var patterns []*sitter.Query
@@ -116,7 +108,7 @@ func ReadFromBytes(fileContent []byte) (Analyzer, YamlAnalyzer, error) {
116108
patterns = append(patterns, pattern)
117109
}
118110
} else {
119-
return Analyzer{}, YamlAnalyzer{}, fmt.Errorf("no pattern provided in checker '%s'", checker.Code)
111+
return Analyzer{}, YamlAnalyzer{}, fmt.Errorf("no pattern provided in checker '%s'", code)
120112
}
121113

122114
if checker.Pattern != "" && len(checker.Patterns) > 0 {
@@ -134,7 +126,7 @@ func ReadFromBytes(fileContent []byte) (Analyzer, YamlAnalyzer, error) {
134126
for _, exclude := range checker.Exclude {
135127
g, err := glob.Compile(exclude)
136128
if err != nil {
137-
return Analyzer{}, YamlAnalyzer{}, err
129+
return Analyzer{}, YamlAnalyzer{}, fmt.Errorf("invalid exclude pattern in yaml checker")
138130
}
139131
pathFilter.ExcludeGlobs = append(pathFilter.ExcludeGlobs, g)
140132
}
@@ -156,7 +148,7 @@ func ReadFromBytes(fileContent []byte) (Analyzer, YamlAnalyzer, error) {
156148
queryStr := filter.PatternInside + " @" + filterPatternKey
157149
query, err := sitter.NewQuery([]byte(queryStr), lang.Grammar())
158150
if err != nil {
159-
return Analyzer{}, YamlAnalyzer{}, err
151+
return Analyzer{}, YamlAnalyzer{}, fmt.Errorf("invalid tree-sitter pattern inside 'pattern-inside' field")
160152
}
161153

162154
filters = append(filters, NodeFilter{
@@ -169,7 +161,7 @@ func ReadFromBytes(fileContent []byte) (Analyzer, YamlAnalyzer, error) {
169161
queryStr := filter.PatternNotInside + " @" + filterPatternKey
170162
query, err := sitter.NewQuery([]byte(queryStr), lang.Grammar())
171163
if err != nil {
172-
return Analyzer{}, YamlAnalyzer{}, err
164+
return Analyzer{}, YamlAnalyzer{}, fmt.Errorf("invalid tree-sitter pattern inside 'pattern-not-inside' field")
173165
}
174166

175167
filters = append(filters, NodeFilter{
@@ -181,7 +173,7 @@ func ReadFromBytes(fileContent []byte) (Analyzer, YamlAnalyzer, error) {
181173
}
182174

183175
patternChecker := Analyzer{
184-
Name: checker.Code,
176+
Name: code,
185177
Language: lang,
186178
Description: checker.Description,
187179
Category: checker.Category,
@@ -193,7 +185,7 @@ func ReadFromBytes(fileContent []byte) (Analyzer, YamlAnalyzer, error) {
193185
Patterns: patterns,
194186
NodeFilter: filters,
195187
PathFilter: pathFilter,
196-
Message: checker.Message,
188+
Message: message,
197189
}
198190

199191
patternChecker.Run = RunYamlAnalyzer(yamlAnalyzer)
@@ -285,3 +277,19 @@ func filterMatchesParent(filter *NodeFilter, parent *sitter.Node, source []byte)
285277

286278
return false
287279
}
280+
281+
func verifyChecker(checker Yaml) (Language, string, string, error) {
282+
lang := DecodeLanguage(checker.Language)
283+
code := checker.Code
284+
msg := checker.Message
285+
286+
if lang == LangUnknown {
287+
return lang, code, msg, fmt.Errorf("unknown language code: %v", lang)
288+
}
289+
290+
if (code == "") || (msg == "") {
291+
return lang, code, msg, fmt.Errorf("missing necessary field in checker definition")
292+
}
293+
294+
return lang, code, msg, nil
295+
}

0 commit comments

Comments
 (0)