--matching-explanations
- Accepted by
opengrep scan,opengrep ci
Adds an explanations array to the JSON output, which records how the parts of each rule matched: each operator of the rule, what it matched, and what its children contributed. It shows why a rule matches where it does, or why it does not match.
The flag affects only the JSON output. It slows the scan down and makes the document much larger.
Examples
The explanations of a match
rule.yaml
rules: - id: eval-in-function patterns: - pattern-inside: | def $F(...): ... - pattern: eval($X) message: eval inside a function languages: [python] severity: WARNINGapp.py
def handler(user): eval(user)Command and result
$ opengrep scan --config rule.yaml --json --matching-explanations app.py 2>/dev/null | jq .
{
"version": "X.Y.Z",
"results": [
{
"check_id": "eval-in-function",
"path": "app.py",
"start": {
"line": 2,
"col": 5,
"offset": 23
},
"end": {
"line": 2,
"col": 15,
"offset": 33
},
"extra": {
"metavars": {
"$F": {
"start": {
"line": 1,
"col": 5,
"offset": 4
},
"end": {
"line": 1,
"col": 12,
"offset": 11
},
"abstract_content": "handler"
},
"$X": {
"start": {
"line": 2,
"col": 10,
"offset": 28
},
"end": {
"line": 2,
"col": 14,
"offset": 32
},
"abstract_content": "user"
}
},
"message": "eval inside a function",
"metadata": {},
"severity": "WARNING",
"fingerprint": "e4f28acf86ffd5b4749bce46013ccfc565ce0f6621b7dfb300e2017c0410e5f408166fa621cc42ce50ccddc298a099f69185267f66820c593738ae8b89296bda_0",
"lines": " eval(user)",
"is_ignored": false,
"validation_state": "NO_VALIDATOR",
"engine_kind": "Opengrep"
}
}
],
"errors": [],
"paths": {
"scanned": [
"app.py"
]
},
"explanations": [
{
"op": "And",
"children": [
{
"op": [
"XPat",
"eval($X)"
],
"children": [],
"matches": [
{
"check_id": "eval-in-function",
"path": "app.py",
"start": {
"line": 2,
"col": 5,
"offset": 23
},
"end": {
"line": 2,
"col": 15,
"offset": 33
},
"extra": {
"metavars": {
"$X": {
"start": {
"line": 2,
"col": 10,
"offset": 28
},
"end": {
"line": 2,
"col": 14,
"offset": 32
},
"abstract_content": "user"
}
},
"engine_kind": "Opengrep",
"is_ignored": false,
"message": "eval inside a function",
"validation_state": "NO_VALIDATOR"
}
}
],
"loc": {
"path": "rule.yaml",
"start": {
"line": 7,
"col": 18,
"offset": 130
},
"end": {
"line": 7,
"col": 26,
"offset": 138
}
}
},
{
"op": "Inside",
"children": [
{
"op": [
"XPat",
"def $F(...):\n ...\n"
],
"children": [],
"matches": [
{
"check_id": "eval-in-function",
"path": "app.py",
"start": {
"line": 1,
"col": 1,
"offset": 0
},
"end": {
"line": 2,
"col": 15,
"offset": 33
},
"extra": {
"metavars": {
"$F": {
"start": {
"line": 1,
"col": 5,
"offset": 4
},
"end": {
"line": 1,
"col": 12,
"offset": 11
},
"abstract_content": "handler"
}
},
"engine_kind": "Opengrep",
"is_ignored": false,
"message": "eval inside a function",
"validation_state": "NO_VALIDATOR"
}
}
],
"loc": {
"path": "rule.yaml",
"start": {
"line": 4,
"col": 26,
"offset": 71
},
"end": {
"line": 6,
"col": 19,
"offset": 113
}
}
}
],
"matches": [
{
"check_id": "eval-in-function",
"path": "app.py",
"start": {
"line": 1,
"col": 1,
"offset": 0
},
"end": {
"line": 2,
"col": 15,
"offset": 33
},
"extra": {
"metavars": {
"$F": {
"start": {
"line": 1,
"col": 5,
"offset": 4
},
"end": {
"line": 1,
"col": 12,
"offset": 11
},
"abstract_content": "handler"
}
},
"engine_kind": "Opengrep",
"is_ignored": false,
"message": "eval inside a function",
"validation_state": "NO_VALIDATOR"
}
}
],
"loc": {
"path": "rule.yaml",
"start": {
"line": 4,
"col": 9,
"offset": 54
},
"end": {
"line": 4,
"col": 23,
"offset": 68
}
}
}
],
"matches": [
{
"check_id": "eval-in-function",
"path": "app.py",
"start": {
"line": 2,
"col": 5,
"offset": 23
},
"end": {
"line": 2,
"col": 15,
"offset": 33
},
"extra": {
"metavars": {
"$F": {
"start": {
"line": 1,
"col": 5,
"offset": 4
},
"end": {
"line": 1,
"col": 12,
"offset": 11
},
"abstract_content": "handler"
},
"$X": {
"start": {
"line": 2,
"col": 10,
"offset": 28
},
"end": {
"line": 2,
"col": 14,
"offset": 32
},
"abstract_content": "user"
}
},
"engine_kind": "Opengrep",
"is_ignored": false,
"message": "eval inside a function",
"validation_state": "NO_VALIDATOR"
}
}
],
"loc": {
"path": "rule.yaml",
"start": {
"line": 3,
"col": 5,
"offset": 36
},
"end": {
"line": 3,
"col": 13,
"offset": 44
}
},
"extra": {
"before_negation_matches": [
"Some",
[
{
"check_id": "eval-in-function",
"path": "app.py",
"start": {
"line": 2,
"col": 5,
"offset": 23
},
"end": {
"line": 2,
"col": 15,
"offset": 33
},
"extra": {
"metavars": {
"$F": {
"start": {
"line": 1,
"col": 5,
"offset": 4
},
"end": {
"line": 1,
"col": 12,
"offset": 11
},
"abstract_content": "handler"
},
"$X": {
"start": {
"line": 2,
"col": 10,
"offset": 28
},
"end": {
"line": 2,
"col": 14,
"offset": 32
},
"abstract_content": "user"
}
},
"engine_kind": "Opengrep",
"is_ignored": false,
"message": "eval inside a function",
"validation_state": "NO_VALIDATOR"
}
}
]
],
"before_filter_matches": "None"
}
}
],
"interfile_languages_used": [],
"skipped_rules": []
}