From security-research
Detect all input-to-sink vulnerabilities — SQLi, NoSQLi, CMDi, path traversal, SSTI, SSRF, XSS, deserialization/XXE, and file handling. Consolidated detection skill covering all cases where user-controlled data reaches a dangerous operation.
npx claudepluginhub pucagit/claude-plugin --plugin security-researchThis skill uses the workspace's default tool permissions.
Find all places where user-controlled data reaches a dangerous sink without adequate sanitization, parameterization, or validation.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Find all places where user-controlled data reaches a dangerous sink without adequate sanitization, parameterization, or validation.
Before hunting, read references/cool_techniques.md for applicable injection detection techniques learned from previous audits. Apply any relevant techniques during your analysis.
| Category | Sub-Types |
|---|---|
| SQL/NoSQL Injection | SQLi (string concat, f-string, raw queries), NoSQLi ($ne/$gt/$where), GraphQL injection |
| Command Injection | OS CMDi (system/exec/popen), argument injection, SSTI (template injection), LDAP/XPath injection |
| Path/File | Path traversal, arbitrary file read/write, zip slip, unrestricted file upload, MIME bypass, ImageMagick/Ghostscript RCE, temp file race, symlink attack |
| SSRF | Direct URL fetch, webhook/callback abuse, cloud metadata (169.254.169.254), DNS rebinding, protocol smuggling (gopher/file/dict), rendering engine SSRF (wkhtmltopdf, puppeteer) |
| XSS | Stored, reflected, DOM-based, template auto-escape bypass ( |
| Deserialization/XXE | Python pickle/yaml.load, Java ObjectInputStream, .NET BinaryFormatter, PHP unserialize, Ruby Marshal, Node serialize, XXE via DTD, XStream, JSON TypeNameHandling |
| Header/Protocol | CRLF injection, log injection, SMTP injection, HTTP request smuggling, cache poisoning, prototype pollution |
Note: For memory safety vulnerabilities (buffer overflow, UAF, format string, integer overflow, unsafe bindings), see
detect-memory.
grep -rn "cursor\.execute\|\.raw(\|RawSQL(\|db\.query(\|sequelize\.query(\|createNativeQuery\|Statement\.execute\|mysqli_query\|PDO::query\|db\.Exec\|db\.Query\|\.execute(f\"\|\.execute(\".*%\|\.execute(\".*+\|\.execute(\".*format\|\.execute(\".*{" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" \
--include="*.php" --include="*.rb" --include="*.go" --include="*.cs" \
${TARGET_SOURCE}
grep -rn "\$ne\|\$gt\|\$where\|\$regex\|find({.*req\.\|findOne({.*req\.\|aggregate(\[.*req\." \
--include="*.js" --include="*.ts" --include="*.py" ${TARGET_SOURCE}
grep -rn "os\.system(\|subprocess\.call(\|subprocess\.run(\|subprocess\.Popen(\|popen(\|exec(\|system(\|shell_exec(\|Runtime\.exec(\|ProcessBuilder(\|child_process\|exec\.Command(\|os\.StartProcess(" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" \
--include="*.php" --include="*.rb" --include="*.go" ${TARGET_SOURCE}
grep -rn "open(\|os\.path\.join(\|send_file(\|fs\.readFile(\|fs\.createReadStream(\|new File(\|FileInputStream(\|file_get_contents(\|os\.Open(" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" \
--include="*.php" --include="*.rb" --include="*.go" \
${TARGET_SOURCE} | grep -v "test\|spec\|vendor\|node_modules"
grep -rn "render_template_string(\|Template(\|\.render(\|Jinja2.*input\|ejs\.render(\|nunjucks\.renderString(\|Velocity\.evaluate(\|freemarker\.template\|ThymeleafTemplateEngine" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" ${TARGET_SOURCE}
grep -rn "requests\.get(\|requests\.post(\|urllib\.request\.\|urllib\.urlopen(\|httpx\.get(\|fetch(\|axios\.get(\|http\.Get(\|curl_exec(\|HttpClient\.\|WebClient\.\|RestTemplate\.\|OkHttpClient\|Faraday\.get(\|Net::HTTP" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" \
--include="*.php" --include="*.rb" --include="*.go" --include="*.cs" ${TARGET_SOURCE}
grep -rn "webhook\|callback_url\|hook_url\|notify_url\|redirect_uri\|return_url\|target_url\|destination_url" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" \
--include="*.php" --include="*.rb" --include="*.go" \
${TARGET_SOURCE} | grep -i "request\.\|req\.\|params\.\|body\.\|form\."
grep -rn "wkhtmltopdf\|pdfkit\|weasyprint\|puppeteer\|playwright\|phantomjs\|html2pdf\|pdf.*url\|screenshot.*url" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" --include="*.php" ${TARGET_SOURCE}
grep -rn "| safe\|{% autoescape off\|{!! \|raw(\|unescape(\|mark_safe(\|Markup(\|SafeString" \
--include="*.html" --include="*.j2" --include="*.jinja" --include="*.twig" \
--include="*.blade.php" --include="*.py" ${TARGET_SOURCE}
grep -rn "innerHTML\|outerHTML\|document\.write(\|insertAdjacentHTML\|\.html(\|eval(\|location\.href\s*=" \
--include="*.js" --include="*.ts" --include="*.html" \
${TARGET_SOURCE} | grep -v "test\|spec\|node_modules"
grep -rn "dangerouslySetInnerHTML\|v-html=\|ng-bind-html\|bypassSecurityTrustHtml\|trustAsHtml" \
--include="*.js" --include="*.ts" --include="*.jsx" --include="*.tsx" --include="*.vue" ${TARGET_SOURCE}
grep -rn "pickle\.loads(\|pickle\.load(\|yaml\.load(\|marshal\.loads(\|shelve\.open(\|Marshal\.load(\|YAML\.load(" \
--include="*.py" --include="*.rb" ${TARGET_SOURCE}
grep -rn "ObjectInputStream\|readObject()\|XMLDecoder\|XStream\|BinaryFormatter\|SoapFormatter\|NetDataContractSerializer\|TypeNameHandling" \
--include="*.java" --include="*.cs" ${TARGET_SOURCE}
grep -rn "DocumentBuilderFactory\|SAXParserFactory\|XMLReader\|lxml\.etree\|xml\.etree\|simplexml_load\|Nokogiri::XML\|DOMParser\|XMLInputFactory" \
--include="*.java" --include="*.py" --include="*.php" --include="*.rb" --include="*.cs" ${TARGET_SOURCE}
grep -rn "request\.FILES\|request\.files\|file\.save(\|upload\.\|uploaded_file\|multipart\|IFormFile\|MultipartFile" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" \
--include="*.php" --include="*.rb" --include="*.go" --include="*.cs" ${TARGET_SOURCE}
grep -rn "zipfile\.extractall\|zipfile\.extract\|tarfile\.extractall\|ZipFile(\|TarFile(\|shutil\.unpack_archive\|ZipArchive\|ZipEntry" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" --include="*.go" ${TARGET_SOURCE}
grep -rn "header(\|redirect(\|Location:\|response\.setHeader\|w\.Header()" \
--include="*.py" --include="*.js" --include="*.ts" --include="*.java" \
--include="*.php" --include="*.go" ${TARGET_SOURCE}
grep -rn "Object\.assign(\|merge(\|extend(\|defaultsDeep(\|_\.merge(\|deepmerge(" \
--include="*.js" --include="*.ts" ${TARGET_SOURCE} | grep -v "test\|spec"
For each grep hit:
file:linerequest.args, req.body, $_GET, etc.)?recon/architecture.md Section 3 (Framework Protections): Does the ORM/framework already mitigate this?| Pattern | Verdict |
|---|---|
cursor.execute(f"SELECT ... {user_input}") | HIGH — f-string SQLi |
cursor.execute("SELECT ... %s", (user_input,)) | FALSE POSITIVE — parameterized |
os.system(f"cmd {user_input}") | HIGH — CMDi |
subprocess.run(["cmd", user_input], shell=False) | MEDIUM — check arg behavior |
Template(user_input).render() | HIGH — SSTI |
render_template("fixed.html", var=user_input) | FALSE POSITIVE |
requests.get(user_url) no validation | CRITICAL — SSRF |
requests.get(user_url) weak blocklist | HIGH — SSRF bypass |
{{ user_input | safe }} in Jinja2 | HIGH — XSS |
dangerouslySetInnerHTML={{ __html: userInput }} | HIGH — XSS |
element.innerHTML = location.hash | CRITICAL — DOM XSS |
element.textContent = user_input | FALSE POSITIVE |
pickle.loads(user_input) | CRITICAL — RCE |
yaml.safe_load(data) | FALSE POSITIVE |
ObjectInputStream with commons-collections | CRITICAL — RCE |
zipfile.extractall(dest) no path check | CRITICAL — zip slip |
tarfile.extractall(filter='data') | FALSE POSITIVE |
| SVG upload served same-origin | HIGH — stored XSS |
wkhtmltopdf rendering user HTML | HIGH — SSRF |
Object.assign({}, JSON.parse(body)) | MEDIUM — prototype pollution |
Use LSP diagnostics to reduce false positives and confirm exploitability:
mcp__ide__getDiagnostics on files with grep hits — check for type errors, dead code, unreachable pathsint or enum, string injection is impossible — mark as FALSE POSITIVELSP is especially valuable for statically-typed languages (Java, Go, TypeScript, Rust, C/C++) where type constraints can eliminate entire vulnerability classes.
The grep patterns above catch known vulnerability shapes. After completing the pattern scan, perform semantic analysis on the code you've read:
For each handler/endpoint: Read the full function. Ask: "What security assumption does this code make? Can that assumption be violated?"
For custom abstractions: If the codebase has custom sanitization functions, query builders, ORM extensions, or input processing utilities — read their implementations. Are they correct? Do they handle edge cases (null, empty, unicode, concurrent calls)?
Cross-module flows: If a variable passes through 3+ functions before reaching a sink, follow it through every hop. One missed encoding step in the middle = vulnerability.
Injection-specific deep analysis:
.raw(), .extra(), RawSQL() call.request.body or request.params before the handler runs? A sanitizer on the handler is useless if middleware decoded the payload first.