You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add structured metadata fields to findings for programmatic access (#385)
* Add structured metadata fields to findings for programmatic access
Adds new fields to FindingMeta for library users who need machine-readable
access to security-relevant data without parsing human-readable strings:
- injection_sources: Array of specific expressions being injected
- lotp_tool: Living Off The Pipeline build tool (npm, pip, make, etc.)
- lotp_action: LOTP GitHub Action identifier
- referenced_secrets: Secrets referenced in the job (excludes GITHUB_TOKEN)
The referenced_secrets field is automatically extracted when rules pass
the _job field, supporting dot notation (secrets.FOO) and bracket notation
(secrets['FOO'] and secrets["FOO"]).
Benchmark (Apple M4 Pro):
| Version | ns/op | B/op | allocs/op |
|---------|-----------|-----------|-----------|
| Before | 10971339 | 7149084 | 132787 |
| After | 12059356 | 7858242 | 148422 |
| Delta | +9.9% | +9.9% | +11.8% |
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Use hex.EncodeToString for faster fingerprint encoding
Fixes perfsprint linter warning by replacing fmt.Sprintf("%x", ...) with
hex.EncodeToString which is more performant.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Use require.NoError for error assertions in test
Fixes testifylint warning by using require.NoError instead of
assert.NoError for error checking in TestStructuredFindingFields.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Poutine findings now include structured metadata fields that provide programmatic access to security-relevant information. These fields enable library users to build automated triage workflows, correlate findings with secrets exposure, and integrate with downstream security tooling without parsing human-readable text.
9
+
10
+
## New Finding Fields
11
+
12
+
### `injection_sources`
13
+
14
+
**Type:**`[]string`
15
+
16
+
A sorted array of the specific expression sources that are being injected into a sink (shell script, JavaScript, etc.).
**Use case:** Programmatically identify which untrusted inputs are exploitable without parsing the `details` string.
30
+
31
+
---
32
+
33
+
### `lotp_tool`
34
+
35
+
**Type:**`string`
36
+
37
+
The "Living Off The Pipeline" build tool detected after an untrusted checkout. Common values include `npm`, `pip`, `make`, `bash`, `cargo`, `gradle`, etc.
38
+
39
+
**Example:**
40
+
```json
41
+
{
42
+
"rule_id": "untrusted_checkout_exec",
43
+
"meta": {
44
+
"details": "Detected usage of `npm`",
45
+
"lotp_tool": "npm"
46
+
}
47
+
}
48
+
```
49
+
50
+
**Use case:** Filter findings by tool type, prioritize based on tool risk, or build tool-specific remediation guidance.
51
+
52
+
---
53
+
54
+
### `lotp_action`
55
+
56
+
**Type:**`string`
57
+
58
+
The GitHub Action identified as a "Living Off The Pipeline" vector (e.g., actions that execute code from the checked-out repository).
59
+
60
+
**Example:**
61
+
```json
62
+
{
63
+
"rule_id": "untrusted_checkout_exec",
64
+
"meta": {
65
+
"details": "Detected usage the GitHub Action `bridgecrewio/checkov-action`",
**Use case:** Assess blast radius of a vulnerability - if a job with an injection vulnerability also references `PROD_DEPLOY_KEY`, the finding is more critical than one with no secrets.
returnany(p in s for s in sources for p in pr_body_patterns)
121
+
```
122
+
123
+
### Group by LOTP Tool
124
+
125
+
```python
126
+
from collections import defaultdict
127
+
128
+
defgroup_by_tool(findings):
129
+
by_tool = defaultdict(list)
130
+
for f in findings:
131
+
if f["rule_id"] =="untrusted_checkout_exec":
132
+
tool = f["meta"].get("lotp_tool") or f["meta"].get("lotp_action", "unknown")
133
+
by_tool[tool].append(f)
134
+
returndict(by_tool)
135
+
```
136
+
137
+
---
138
+
139
+
## Backward Compatibility
140
+
141
+
These fields are additive - the existing `details` field continues to provide human-readable descriptions. Tools parsing `details` will continue to work, but new integrations should prefer the structured fields for reliability.
142
+
143
+
**JSON behavior:**
144
+
-`injection_sources`, `lotp_tool`, `lotp_action`: Omitted when not applicable
145
+
-`referenced_secrets`: Present as `[]` (empty array) for GitHub Actions findings even when no secrets are found; omitted for other CI systems
0 commit comments