Static analysis
Static analysis for code written by people, agents, and LLMs.
kern review is a semantic companion to your linter. It combines AST rules, TypeScript and Python concept extraction, taint analysis, native .kern review rules, confidence scoring, and MCP security checks.
See it catch a prompt injection — live
async function chat(db, llm, userId) {
// DB results go straight into prompt
const history = await db.query(
`SELECT msg FROM chat
WHERE user_id = '${userId}'`
);
const prompt =
`Assistant: ${history.rows
.map(r => r.msg).join('\n')}`
// User input unsanitized
return llm.complete(prompt);
}! indirect-prompt-injection
DB result 'history' from db.query
used in LLM prompt without
sanitization — indirect injection
risk
chat.ts:9
~ unguarded-effect
Network/DB effect without
auth/validation guard
chat.ts:3
~ unrecovered-effect
db effect without error recovery
chat.ts:3Syntax linters can miss this class of generated-code bug. kern review follows the data and effect boundaries.
@kernlang/review — analyzing src/
! indirect-prompt-injection
DB result used in LLM prompt without sanitization
src/chat/handler.ts:9
! llm-output-execution
LLM output passed to eval() — arbitrary code execution
src/agent/runner.ts:17
! prompt-injection
User input embedded in prompt without sanitization
src/api/chat.ts:23
~ encoding-bypass
Decoded content from Buffer.from() used in prompt
src/utils/decode.ts:50
~ json-output-manipulation
JSON.parse on LLM output without schema validation
src/api/structured.ts:69
~ missing-output-validation
LLM response used without validation
src/codegen/generate.ts:75
~ unguarded-effect (×3)
Network/DB effect without error recovery
~ rag-poisoning
Retrieval result embedded in prompt unsanitized
src/rag/search.ts:28
~ tool-calling-manipulation
LLM-returned tool calls executed without allowlist
src/agent/tools.ts:41
~ unsanitized-history
Unsanitized messages spread into LLM API call
src/chat/multi-turn.ts:63
✓ 847 lines scanned · 3 errors · 8 warnings
✓ prompt-injection patterns reviewedRepresentative output from the security benchmark patterns. The important part is the file:line evidence and rule ID.
rule registry entries
MCP security rule IDs
languages (TS + Python)
scored findings
kern review doesn't just lint syntax. It understands concepts: entrypoints, effects, guards, state mutations, boundaries.
Prompt injection patterns, RAG poisoning, encoding bypasses, taint analysis, path traversal, prototype pollution, crypto issues, and sensitive logs
Hooks, composition, setState in render, stale closures, conditional hooks, missing deps, render side effects
Floating promises, unused exports, complex conditionals, hardcoded secrets, handler size, memory leaks
Unreachable code after return, dead branches, exhaustiveness gaps in switches, unused collections
Next.js App Router, Express middleware, Vue reactivity, Nuxt SSR, FastAPI async, Terminal, Ink, CLI
Accessibility checks, performance patterns, abort-controller leaks, Promise.all handling, and async safety
Concept rules reason over entrypoints, effects, guards, mutations, boundaries, routes, request bodies, and response shapes
Command injection, path traversal, tool poisoning, secrets exposure, missing auth, typosquatting, data injection, and resource exhaustion
kern review isn't trying to replace your linter. It catches what they miss.
| kern review | ESLint | SonarQube | |
|---|---|---|---|
| Concept-level analysis | Yes | No | Limited |
| Prompt-injection review patterns | Yes | Rulepack-dependent | Rulepack-dependent |
| LLM-ready output | Yes (5x smaller IR) | No | No |
| TypeScript + Python | Both | TS only | Many languages |
| Framework-aware rules | Next.js, Express, Vue | Via plugins | Limited |
| Rule count | 233 registry entries | Hundreds | Thousands |
| SARIF / CI integration | Yes | Yes | Yes |
| Free for developers | Yes | Yes | Community only |
ESLint and SonarQube have more rules and broader language coverage. kern review focuses on concept-level generated-code analysis, prompt-injection review patterns, and LLM-exportable findings. Use them together.
CWE-1427: Improper Neutralization of Input Used for LLM Prompting. The Kern repo includes a security benchmark with 10 code patterns for LLM prompt-injection style failures.
The benchmark file is public: examples/security-benchmark.ts. Use this table as a reproducible project benchmark, not a universal claim about every codebase.
The practical reason to run Kern here is evidence: it points to the exact source span where untrusted data enters prompts, tools, eval, JSON parsing, or output handling.
| Attack vector | kern | Evidence | Scope | Status |
|---|---|---|---|---|
| Indirect injection (DB→prompt) | Yes | source span | data to prompt | active |
| LLM output execution | Yes | source span | eval boundary | active |
| System prompt leakage | Yes | source span | prompt boundary | active |
| RAG poisoning | Yes | source span | retrieval flow | active |
| Tool calling manipulation | Yes | source span | tool boundary | active |
| Encoding bypasses | Yes | source span | encoded input | active |
| Delimiter injection | Yes | source span | prompt format | active |
| Unsanitized history | Yes | source span | chat history | active |
| JSON output manipulation | Yes | source span | output parsing | active |
| Missing output validation | Yes | source span | validation | active |
| Project benchmark | covered | file:line | generated-code flows | documented |
Methodology
The project benchmark file contains vulnerable TypeScript patterns used to exercise generated-code review rules. Keep benchmark examples in context: rulepacks change, and results vary by configuration.
Run the project benchmark locally:
kern review examples/security-benchmark.tsThese checks are mapped to prompt-injection and generated-code failure modes such as RAG poisoning, encoding bypass, delimiter injection, tool calling validation, and unsanitized history. Mapped to CWE-1427 and OWASP LLM01:2025.
12 rules purpose-built for MCP servers. Static analysis that scans the code that makes the server dangerous — no running server required.
Mapped to OWASP MCP Top 10 categories with source-code rule IDs for dangerous MCP server patterns.
// Vulnerable MCP server
server.tool('run', 'Run command', {}, async (params) => {
execSync(`${params.cmd}`);
});
! mcp-command-injection
Shell command execution in MCP tool handler
server.ts:3 confidence: 0.95
! mcp-ir-unguarded-effect
action "run" has shell-exec effect without any guard
server.ts:3 confidence: 0.90| Capability | kern review | mcp-scan | Proximity |
|---|---|---|---|
| Analysis type | Static (source code) | Dynamic (running server) | Dynamic (running server) |
| Languages | TypeScript + Python | Any (protocol-level) | Any (protocol-level) |
| Prompt injection | Yes (code + data) | Yes (tool descriptions) | Yes (tool descriptions) |
| Command injection | Yes (taint + IR) | No | No |
| Path traversal | Yes (AST + IR) | No | No |
| Secrets detection | Yes (pattern + base64) | No | No |
| Auth checks | Yes (middleware) | No | No |
| Structural analysis | Yes (KERN IR) | No | No |
| Requires running server | No | Yes | Yes |
| Confidence scoring | Yes (0.70–0.95) | No | No |
KERN scans the code that makes the server dangerous. mcp-scan checks running servers. Use both.
Free CLI. Hosted and BYOK tiers for teams.
See pricing →