I Ran a Graph-Aware Security Scanner on a Popular Open Source Repo. Here’s What It Found.

Most security scanners are pattern matchers. They scan files, find strings that look like vulnerabilities, and hand you a list. The list is often long. The list is rarely prioritized by what actually matters in your specific codebase. And the list has no idea which vulnerabilities are reachable from the outside world and which are buried five layers deep in an internal utility that nothing ever calls.
Depwire’s security scanner works differently. It uses the dependency graph to determine which vulnerabilities are reachable and elevates their severity accordingly. A shell injection in a file that handles raw user input from an HTTP route is Critical. The same pattern in a file that only internal scripts ever touch is Low. The code is identical. The risk is not.
Here’s how it works, and what it found on a real-world codebase.
The Problem With Generic SAST
Static application security testing tools scan for patterns. They’re useful. They’re also noisy by design, because they have no way to know your architecture. They flag every eval() call the same way, whether it's in your main request handler or in a test fixture that hasn't been touched in two years.
The result is alert fatigue. Developers learn to ignore security reports because 80% of the findings are not exploitable in practice. The 20% that matter get buried in the noise.
Graph-aware security scanning flips this. Instead of asking “does this pattern exist somewhere in the codebase?”, it asks “is this pattern reachable from an entry point that handles untrusted input?” That’s the question that actually determines exploitability.
How Depwire’s Security Scanner Works
Depwire builds a deterministic dependency graph of your codebase using Tree-Sitter. Every file’s imports, exports, and symbols are mapped. Every HTTP route, every MCP tool handler, every API endpoint is identified as an external entry point.
The scanner then runs in four steps:
Step 1 — Attack surface ranking. Files are scored 1–5 based on what they handle. Files that import execSync, handle auth tokens, process file paths from user input, or sit in route/middleware directories automatically score 4-5. The graph identifies which files have high external fan-in — meaning many things depend on them, meaning a bug there has a wide blast radius.
Step 2 — Vulnerability class detection. Ten categories are checked: dependency CVEs, shell injection, hardcoded secrets, path traversal, auth bypass, IDOR, credential exposure in logs, missing input validation, dangerous function usage, and weak cryptography.
Step 3 — Graph-aware severity elevation. This is the differentiator. A vulnerability in a file with zero external connections is scored Low regardless of the pattern-match severity. The same vulnerability, reachable via an unauthenticated HTTP route, is rated Critical. Depwire runs the What If simulation in reverse — given a vulnerable function, which external entry points can reach it?
Step 4 — Ranked report. Critical → High → Medium → Low, with per-finding detail: file, line, vulnerability class, attack scenario, suggested fix, and SARIF output for CI integration.
Real Numbers: honojs/hono
We ran depwire security . on the Hono framework codebase — 352 TypeScript files, 6,245 symbols.
6 Critical
19 High
14 Medium
1 Low
The Critical findings include shell injection patterns reachable from the MCP tool handlers, which means any AI assistant with Depwire connected could potentially trigger them. That’s exactly the kind of context-aware severity elevation that generic scanners miss.
Run it yourself:
npm install -g depwire-cli
cd your-repo
depwire security .
The 10 Vulnerability Categories
Dependency CVEs — wraps npm audit, pip audit, cargo audit, and go mod tidy. Flags known CVEs in your dependency tree.
Shell injection — detects string interpolation into execSync, child_process, subprocess, system(), and equivalent calls in each supported language. A crafted branch name or filename becomes an RCE vector faster than most developers realize.
Hardcoded secrets — API keys, salts, tokens, passwords, and connection strings in source. Includes PHP-specific patterns like hardcoded PBKDF2 salts and weak cryptographic seeds.
Path traversal — user-supplied strings joined to file paths without resolve() containment checks. Common in MCP tools that accept directory parameters.
Auth bypass — missing token validation, fail-open catch blocks (where an error in the auth middleware calls next() instead of returning 403), unauthenticated endpoints with high fan-in.
IDOR — database queries that accept user-supplied IDs without ownership scoping. Particularly common in REST APIs built quickly.
Credential exposure in logs — auth tokens, GitHub tokens, and session credentials appearing in error messages or clone URLs that get logged.
Missing input validation — no type or length checks on user-supplied data before it reaches storage or processing layers.
Dangerous function usage — eval(), Function() constructor, Math.random() for security-sensitive values, unserialize on user input, extract() on PHP superglobals.
Weak cryptography — md5()/sha1() for password hashing, deprecated cipher usage, hardcoded initialization vectors, rand()/mt_rand() for token generation.
CI Integration
The scanner supports a --fail-on flag for CI gates:
depwire security . --fail-on critical
Returns exit code 1 if any Critical findings exist. Add it to your GitHub Actions workflow:
- name: Depwire security scan
run: depwire security . --fail-on high
SARIF output for GitHub Code Scanning:
depwire security . --format sarif --output results.sarif
The MCP Tool: AI Agents That Self-Audit
The security_scan MCP tool lets AI assistants run the scanner as part of their reasoning loop:
{
"tool": "security_scan",
"params": {
"path": "."
}
}When Claude or Cursor has Depwire connected as an MCP server, you can ask it to audit the code it just generated. The AI writes a function, calls security_scan, receives structured findings, and fixes them before you even see the output. This is the security review loop compressed from hours to seconds.
Configure Depwire as an MCP server in Claude Desktop:
{
"mcpServers": {
"depwire": {
"command": "npx",
"args": ["-y", "depwire-cli", "mcp"]
}
}
}Why Graph-Aware Severity Matters for AI-Generated Code
AI coding assistants generate code fast. They also generate vulnerabilities fast — not because they’re careless, but because they don’t know your threat model. They don’t know which files are called from unauthenticated routes. They don’t know which functions handle untrusted input. They write code that looks correct without understanding where on the attack surface it lives.
Depwire knows. The graph encodes exactly which code is reachable from which entry points. The security scanner uses that knowledge to tell you not just what’s vulnerable, but what’s exploitable given your specific architecture.
That’s the difference between a list and an answer.
Install
npm install -g depwire-cli
GitHub: github.com/depwire/depwire
NPM Package: https://www.npmjs.com/package/depwire-cli
Official Website: https://depwire.dev
Supports TypeScript, JavaScript, Python, Go, Rust, C, C#, Java, C++, Kotlin, and PHP. Works with Claude, Cursor, VS Code Copilot, and any MCP-compatible AI tool. SARIF output is supported for GitHub Code Scanning integration.
Full Tutorial on my channel: