plugins/compliance/skills/call-graph-analysis/SKILL.md
Perform definitive call graph analysis to prove whether vulnerable functions are reachable from program entry points
npx skillsauth add openshift-eng/ai-helpers call-graph-analysisInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Provides highest-confidence vulnerability assessment by proving whether vulnerable functions can actually be reached during program execution.
Use this skill when:
govulncheck is unavailable or didn't find the CVEcallgraph: go install golang.org/x/tools/cmd/callgraph@latestdigraph: go install golang.org/x/tools/cmd/digraph@latestgo.mod filegraphviz (for visualization): brew install graphviz (macOS) or sudo apt-get install graphviz (Linux)sfdp or dot command (part of graphviz)<package-path>.<function-name>)vta) — passed via --algo from parent commandCVE_ID — used to construct the output directoryOUT_DIR (optional, default: .work/compliance/analyze-cve/${CVE_ID}) — where artifacts are written--algo (default: vta).callgraph invocations use timeout 300 (5 minutes) to prevent hanging on large codebases.vta → rta → cha), then narrow scope to specific packages (e.g., ./cmd/..., ./pkg/...).# Check for callgraph
which callgraph || echo "callgraph not found - install with: go install golang.org/x/tools/cmd/callgraph@latest"
# Check for digraph
which digraph || echo "digraph not found - install with: go install golang.org/x/tools/cmd/digraph@latest"
# Optional: Check for graphviz
which sfdp || echo "graphviz not found - visual graphs won't be generated (optional)"
Decision Point:
# ALGO defaults to "vta" unless user specified --algo
ALGO="${USER_ALGO:-vta}"
# Output directory — aligns with parent command report location
OUT_DIR="${OUT_DIR:-.work/compliance/analyze-cve/${CVE_ID}}"
mkdir -p "${OUT_DIR}"
# Build call graph from workspace root
# Timeout after 300s (5 minutes) to avoid hanging on large codebases
timeout 300 callgraph -algo "${ALGO}" -format=digraph . > "${OUT_DIR}/callgraph.txt"
Error Handling:
vta → rta → cha) and retrytimeout 300 callgraph -algo rta -format=digraph ./cmd/... ./pkg/... > "${OUT_DIR}/callgraph.txt"Output: ${OUT_DIR}/callgraph.txt containing the full program call graph
Extract the vulnerable function signature from CVE details.
# Search for exact function in the cached call graph
VULN_FUNC="<package-path>.<vulnerable-function>"
cat "${OUT_DIR}/callgraph.txt" | digraph nodes | grep "${VULN_FUNC}$"
Decision Point:
Search for paths from main entry points to the vulnerable function.
# Find path from main() to vulnerable function using cached call graph
ENTRY_POINT="command-line-arguments.main"
VULN_FUNC="<package-path>.<vulnerable-function>"
cat "${OUT_DIR}/callgraph.txt" | \
digraph somepath "${ENTRY_POINT}" "${VULN_FUNC}"
Alternative Entry Points to Check:
command-line-arguments.main (main program)*_test.go test functions*.initInterpretation:
Output: Text representation of call chain or empty result
If path exists, generate visual representation:
# Generate DOT format from cached call graph
cat "${OUT_DIR}/callgraph.txt" | \
digraph somepath "${ENTRY_POINT}" "${VULN_FUNC}" | \
digraph to dot > "${OUT_DIR}/callgraph.dot"
# Convert to SVG (if graphviz available)
if which sfdp > /dev/null; then
sfdp -Tsvg -o"${OUT_DIR}/callgraph.svg" -Goverlap=scale "${OUT_DIR}/callgraph.dot"
echo "Visual graph saved to: ${OUT_DIR}/callgraph.svg"
else
echo "Graphviz not available - DOT file saved to: ${OUT_DIR}/callgraph.dot"
fi
Output Files:
${OUT_DIR}/callgraph.dot - DOT notation of call path${OUT_DIR}/callgraph.svg - Visual graph (if graphviz available)Extract human-readable call chain from digraph output:
# Get call chain as text from cached call graph
cat "${OUT_DIR}/callgraph.txt" | \
digraph somepath "${ENTRY_POINT}" "${VULN_FUNC}" | \
digraph to dot | \
grep " -> " | \
sed 's/"//g' | \
sed 's/;//g'
Example Output:
command-line-arguments.main -> <package-path>.Handler
<package-path>.Handler -> <package-path>.ProcessFunction
<package-path>.ProcessFunction -> <vulnerable-package>.<vulnerable-function>
Format for Report:
Execution Path Found:
main → Handler → ProcessFunction → <vulnerable-function> (VULNERABLE)
HIGH RISK:
MEDIUM RISK:
LOW RISK:
Return structured result to parent analysis:
{
"method": "call-graph-reachability",
"algorithm": "vta",
"vulnerable_function": "<package-path>.<vulnerable-function>",
"found_in_graph": true,
"reachable_from_main": true,
"call_chain": "main → Handler → ProcessFunction → <vulnerable-function>",
"risk_level": "HIGH",
"evidence": {
"callgraph_file": "${OUT_DIR}/callgraph.txt",
"dot_file": "${OUT_DIR}/callgraph.dot",
"svg_file": "${OUT_DIR}/callgraph.svg"
}
}
vta → rta → cha)timeout 300 callgraph -algo rta -format=digraph ./cmd/... ./pkg/... > "${OUT_DIR}/callgraph.txt"command-line-arguments.main not found → Look for other entry points# Setup: set CVE_ID and output directory
$ CVE_ID="CVE-YYYY-NNNNN"
$ OUT_DIR=".work/compliance/analyze-cve/${CVE_ID}"
$ mkdir -p "${OUT_DIR}"
# Step 1: Build call graph (default: vta; user can override with --algo)
$ timeout 300 callgraph -algo vta -format=digraph . > "${OUT_DIR}/callgraph.txt"
# Step 2: Check if function is called
$ cat "${OUT_DIR}/callgraph.txt" | digraph nodes | grep "<package-path>.<vulnerable-function>$"
<package-path>.<vulnerable-function>
# Step 3: Find path from main
$ cat "${OUT_DIR}/callgraph.txt" | digraph somepath command-line-arguments.main <package-path>.<vulnerable-function>
digraph {
"command-line-arguments.main" -> "<app-package>.Handler";
"<app-package>.Handler" -> "<app-package>.ProcessFunction";
"<app-package>.ProcessFunction" -> "<intermediate-package>.HelperFunction";
"<intermediate-package>.HelperFunction" -> "<vulnerable-package>.<vulnerable-function>";
}
# Step 4: Generate visual graph
$ cat "${OUT_DIR}/callgraph.txt" | digraph somepath command-line-arguments.main <package-path>.<vulnerable-function> | digraph to dot | sfdp -Tsvg -o"${OUT_DIR}/callgraph.svg"
# Result: HIGH RISK — reachable path found
# Call chain: main → Handler → ProcessFunction → HelperFunction → <vulnerable-function>
This skill is called from Method 4 of the codebase-impact-analysis skill.
When to Invoke:
Return to Parent:
research
Shared engine for analyzing Jira issue activity and generating status summaries
testing
Snapshot OpenShift payload data (release controller, PR diffs, comments, CI jobs, JUnit results, regression tracking) to a local directory for offline analysis
development
Analyze a payload snapshot to identify root causes of blocking job failures, score candidate PRs, and produce an HTML report with revert recommendations
tools
Create TRT JIRA bugs, open revert PRs, and trigger payload jobs for high-confidence revert candidates