| name | xgrep-triage |
| description | Investigates and classifies xgrep scan findings using code graph analysis for call chain navigation and dataflow tracing. Use when triaging SAST findings, investigating vulnerabilities, or classifying true/false positives. |
| allowed-tools | Bash Read Glob Grep |
xgrep Triage
Investigate and classify xgrep scan findings using the code graph for call chain analysis and dataflow tracing.
When to Use
- Triaging scan findings from xgrep
- Investigating whether a finding is a true or false positive
- Understanding dataflow paths from sources to sinks
- Mapping attack surface via call chain analysis
When NOT to Use
- Creating or modifying rules (use
xgrep-rule-creator)
- Running a scan without investigation (just use
xgrep scan -f rules.yaml --json target/)
Overview
This skill guides systematic investigation of xgrep findings. For each finding, you build context using the code graph, trace dataflow, check for validation/sanitization, and classify the result with evidence.
Workflow
Step 1: Scan the Target
xgrep scan --json <target> > findings.json
xgrep scan -f <rules-path> --json <target> > findings.json
The JSON output includes code context and remediation guidance for every finding. Parse it and group findings by:
- Severity (ERROR first)
- Rule ID (related findings together)
- File/function (use
context.function for grouping)
Present a summary: N findings across M rules, severity breakdown.
Key fields per finding:
extra.severity, extra.message, extra.lines — what was found
context.before/context.after — surrounding code for understanding
context.function, context.callers, context.callees — call graph location
remediation.description — how to fix it
remediation.has_autofix — whether autofix is available via extra.fix
Step 2: Investigate Each Finding
Note: The code graph is built automatically during the scan — every finding already includes context.function, context.callers, and context.callees. No separate xgrep graph build needed.
For each finding, starting with the highest severity:
Start with the built-in context — every finding already includes context.before/context.after (surrounding code), context.function (enclosing function), and context.callers/context.callees (immediate call graph). This is often enough for initial triage.
For deeper investigation, use graph commands:
xgrep graph context <function-name> --depth 2
xgrep graph paths <entry-point> <dangerous-sink>
xgrep graph callers <handler-function>
xgrep graph reachable <data-source-function>
Step 3: Classify
Based on the evidence from Step 3:
True Positive:
- Untrusted data reaches a dangerous sink without adequate validation
- No sanitization on any code path between source and sink
- The sink is security-sensitive in context
False Positive:
- Input is validated/sanitized before reaching the sink
- The code path is unreachable from untrusted input
- The sink is not security-sensitive in this context
- Framework-level protection handles this case
Needs Review:
- Partial validation exists but may be incomplete or bypassable
- Complex control flow makes it hard to determine safety
- Framework-level protection may or may not apply
Always cite specific functions and line numbers as evidence.
Step 4: Record the verdict in findings.json
Write the verdict back onto each finding as an extra.triage object (located by
extra.fingerprint), then print a short human summary. The durable record is the
JSON — one artifact carrying detection, fix capability, and verdict — not the prose.
"extra": {
"...": "...",
"fix_info": { "kind": "assisted", "...": "..." },
"triage": {
"reviewed": true,
"status": "true-positive",
"rationale": "uid flows unsanitized into execute()",
"reviewed_by": "xgrep-triage",
"reviewed_at": "<RFC3339>"
}
}
Edit the JSON in place (a small python/jq step keyed on fingerprint), leaving
every other field intact. Then xgrep fix apply --confirmed < findings.json (or the
xgrep-fix skill) fixes only the true-positive findings and skips false-positive
ones automatically. See triage-workflow.md
§6 for the write-back recipe and the summary-table format. Triage decides whether;
xgrep already decided how (extra.fix_info).
Investigation Patterns by Vulnerability Type
Injection (SQL, Command, XSS) -- CWE-89, CWE-78, CWE-79
- Identify the sink (SQL query, command execution, HTML output)
- Trace backwards:
xgrep graph callers <sink-function>
- Find the entry point where user input enters
- Check every function in the path for sanitization
- Verify sanitization is correct for the specific context (SQL vs HTML vs shell)
Authentication/Authorization -- CWE-287, CWE-862
- Identify the protected resource or action
xgrep graph callers <handler> to find all entry points
- Check if authentication middleware is applied to all paths
- Look for alternative paths that bypass checks
Sensitive Data Exposure -- CWE-200, CWE-532
- Identify where sensitive data is created or loaded
xgrep graph reachable <data-source> to see where it flows
- Check for logging, error messages, or API responses that include it
- Verify encryption/masking before external output
References
Tips
- Use
--depth 1 for focused context, --depth 2 for broader investigation
xgrep graph context is the most useful single command -- topology and code in one shot
- Confidence levels on edges:
certain (direct call), inferred (method on known type), uncertain (dynamic dispatch)
- Function names can be partial matches (e.g.,
EvalRule matches EvalRule and EvalRuleWithContext)
- For exact matches, use the full node ID:
pkg/core/eval.go::EvalRule