Rule Reference
All 61 review rules organized by layer.
Base Rules
13 rules that apply to every TypeScript and Python file. These catch universal code-quality problems regardless of framework or target.
floating-promise— Promise created but never awaited or returnedstate-mutation— Direct mutation of state that should be immutableempty-catch— Catch block with no error handling logicmachine-gap— State machine transition references a state that does not existcognitive-complexity— Function exceeds the configured complexity thresholddead-code— Code that can never execute (after return, throw, or break)unused-imports— Imported binding is never referenced in the modulemissing-return— Code path exits a function without a return value when one is expectedtype-any— Explicit or inferred any type that weakens type safetyimplicit-return— Function returns undefined on some paths but a value on othershardcoded-secret— API key, token, or password literal embedded in sourceno-eval— Use of eval() or Function() constructor with dynamic inputconsole-in-prod— console.log or console.debug left in production code
Security Rules — v1
8 rules covering the OWASP Top 10 surface: injection, XSS, deserialization, and cryptographic misuse.
injection— Unsanitized user input flows into a shell command or system callsql-injection— Raw string concatenation in a SQL query instead of parameterized statementsxss— User-controlled value rendered into HTML without escapingunsanitized-html— Raw HTML inserted via dangerouslySetInnerHTML or v-html without sanitizerunsafe-deserialization— Untrusted data passed to JSON.parse, pickle.loads, or yaml.load without validationinsecure-random— Math.random() or random.random() used in a security-sensitive contexthardcoded-secret— Credential literal found in source (also a base rule, upgraded to error in security context)weak-hash— Use of MD5 or SHA-1 for hashing where a collision-resistant algorithm is required
Security Rules — v2
6 rules for authentication, authorization, and concurrency vulnerabilities.
csrf-token-missing— State-changing endpoint accepts requests without CSRF token validationrate-limit-missing— Public or auth endpoint has no rate-limiting middlewareauth-bypass— Route handler reachable without authentication checkprivilege-escalation— User-controlled input determines access level without authorization guardpath-traversal— File path constructed from user input without normalization or allowlistrace-condition— Shared resource accessed concurrently without lock or atomic operation
Security Rules — v3
5 rules targeting modern attack vectors including prototype pollution, regex denial-of-service, and LLM prompt injection.
regex-dos— Regular expression with catastrophic backtracking potentialmissing-input-validation— External input consumed without schema or type validationprototype-pollution— Dynamic property assignment on Object.prototype or via unchecked mergeinformation-exposure— Stack trace, internal path, or debug data leaked in an error responseprompt-injection— User-controlled text concatenated into an LLM prompt without boundary enforcement
Dead Logic
8 rules that detect code which compiles but can never affect runtime behavior. These are often symptoms of refactoring mistakes.
unreachable-code— Statement after an unconditional return, throw, or breakalways-true— Condition that evaluates to true on every possible code pathalways-false— Condition that evaluates to false on every possible code pathunused-variable— Variable declared and assigned but never readdead-branch— If/else or switch branch that can never executeredundant-condition— Condition already guaranteed by a parent guard or earlier checkimpossible-type— Type narrowing produces never, meaning the branch is unreachableempty-block— Block statement with no body (empty if, empty loop)
React Rules
6 rules active when the target is React, Next.js, Tailwind, or React Native. They catch hook misuse and rendering pitfalls.
async-effect— useEffect callback is async (should return void, not a Promise)render-side-effect— Side effect executed during the render phase instead of inside useEffectmissing-dependency— Reactive value used inside useEffect/useMemo/useCallback but missing from the dependency arraystale-closure— Callback captures a stale variable because the dependency array is incompletehook-rules— Hook called conditionally or inside a loop, violating the Rules of Hooksmissing-key— List item rendered without a stable key prop
Next.js Rules
3 rules specific to the Next.js App Router model.
server-hook— React hook called inside a Server Component (must be a Client Component)hydration-mismatch— Server-rendered HTML will differ from client hydration outputclient-directive-missing— Component uses hooks or browser APIs but is missing the 'use client' directive
Vue Rules
4 rules for Vue 2/3 and Nuxt projects.
vue-data-not-function— data property is a plain object instead of a factory function (Vue 2)vue-missing-key— v-for list item missing a :key bindingvue-prop-mutation— Child component directly mutates a prop instead of emitting an eventvue-lifecycle-deprecated— Deprecated lifecycle hook used (beforeDestroy, destroyed in Vue 3)
Express Rules
3 rules for Express.js server applications.
express-missing-error-handler— Express app has no 4-argument error-handling middleware registeredexpress-helmet-missing— Express app does not use Helmet or equivalent security headers middlewareexpress-sync-io— Synchronous fs or child_process call inside a route handler blocks the event loop
Prompt injection detection
Beyond the prompt-injection rule in Security v3, kern review detects 7 verified attack vectors from the OWASP LLM Top 10 (LLM01). Each vector is identified by taint-tracking user input through prompt construction paths.
indirect-prompt-injection— Untrusted data (fetched content, DB rows) injected into a prompt without boundary markersllm-output-execution— LLM response passed directly to eval, exec, or shell without validationprompt-injection— User-controlled string concatenated into a system or user promptencoding-bypass— Base64, hex, or unicode encoding used to smuggle instructions past input filtersdelimiter-injection— User input contains prompt delimiters (detected via the prompt-injection vector)json-output-manipulation— LLM JSON output parsed and used in control flow without schema validationmissing-output-validation— LLM response consumed by application logic with no sanitization or type check
Example — detecting llm-output-execution:
// Flagged: LLM output flows into eval without validation
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: userInput }],
});
const code = response.choices[0].message.content;
eval(code); // llm-output-execution (error, confidence: 0.97)
// Fix: validate and sandbox the output
const parsed = safeParseCode(code);
if (parsed.ok) {
sandbox.run(parsed.value);
}Severity levels
Every finding is assigned one of three severity levels. CI enforcement via --enforce fails on any error-level finding by default.
| Level | Meaning | Examples |
|---|---|---|
| error | Must fix. Security vulnerability, data loss risk, or guaranteed runtime failure. | sql-injection, prompt-injection, auth-bypass, floating-promise |
| warning | Should fix. Code smell, potential bug, or degraded maintainability. | cognitive-complexity, missing-dependency, dead-branch |
| info | Informational. Style preference or low-risk observation. | unused-imports, console-in-prod, empty-block |
Confidence scores
Each finding includes a confidence score from 0 to 1 indicating how certain the analyzer is that the finding is a true positive.
- 0.9 – 1.0 — High confidence. Pattern matched exactly with full taint-tracking or type evidence.
- 0.7 – 0.89 — Medium confidence. Pattern matched but some context is ambiguous (e.g., dynamic import, indirect call).
- 0.5 – 0.69 — Low confidence. Heuristic match that may be a false positive. Review manually.
- Below 0.5 — Suppressed by default. Enable with
--min-confidence=0to see all findings.
Filter findings by confidence using the --min-confidence flag or the minConfidence config key:
# Only show findings with >= 80% confidence
kern review src/ --recursive --min-confidence=0.8