用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/ersinkoc/security-check --skill sc-ssti命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | sc-ssti |
| description | Server-Side Template Injection detection across all major template engines |
| license | MIT |
| metadata | {"author":"ersinkoc","category":"security","version":"1.0.0"} |
Detects server-side template injection vulnerabilities where user input is embedded into template strings before compilation/rendering, allowing attackers to execute arbitrary code on the server. Covers Jinja2, Twig, Freemarker, Velocity, Pug, Handlebars, ERB, Mako, Thymeleaf, and Go templates.
Called by sc-orchestrator during Phase 2 when template engines are detected.
**/*.py, **/*.php, **/*.java, **/*.rb, **/*.js, **/*.ts, **/*.go,
**/templates/*, **/views/*, **/*template*, **/*render*, **/*view*
# Python/Jinja2
"render_template_string(", "Template(", "Environment(",
"from_string(", "jinja2.Template("
# PHP/Twig
"$twig->createTemplate(", "Twig\\Template", "renderString("
# Java/Freemarker/Velocity/Thymeleaf
"new Template(", "freemarker", "VelocityEngine",
"templateEngine.process(", "StandardDialect"
# Ruby/ERB
"ERB.new(", "render inline:", "Erubis"
# JavaScript/Pug/Handlebars/EJS
"pug.render(", "pug.compile(", "Handlebars.compile(",
"ejs.render(", "nunjucks.renderString("
# Go
"template.New(", "text/template", "html/template",
".Parse(", "template.Must("
render_template_string() instead of render_template() in FlaskThe vulnerability occurs when user input becomes part of the TEMPLATE CODE, not the template DATA:
# SAFE: User input as template data (parameterized)
render_template('hello.html', name=user_input)
# VULNERABLE: User input as template code
render_template_string(f"Hello {user_input}")
# If user_input = "{{7*7}}", the template engine evaluates it as 49
# If user_input = "{{config.items()}}", it leaks Flask config
| Engine | Detection Probe | Code Execution |
|---|---|---|
| Jinja2 | {{7*7}} → 49 | {{config.__class__.__init__.__globals__['os'].popen('id').read()}} |
| Twig | {{7*7}} → 49 | {{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id")}} |
| Freemarker | ${7*7} → 49 | <#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")} |
| Velocity | $class.inspect("java.lang.Runtime") | Via reflection chain |
| Pug | #{7*7} → 49 | Via code blocks |
| ERB | <%= 7*7 %> → 49 | <%= system("id") %> |
| Mako | ${7*7} → 49 | ${__import__("os").popen("id").read()} |
| Thymeleaf | [[${7*7}]] → 49 | Via SpEL: ${T(java.lang.Runtime).getRuntime().exec("id")} |
# VULNERABLE: User input in template string
@app.route('/greeting')
def greeting():
template = f"Hello, {request.args.get('name', 'World')}!"
return render_template_string(template)
# SAFE: User input as template variable
@app.route('/greeting')
def greeting():
return render_template_string(
"Hello, {{ name }}!",
name=request.args.get('name', 'World')
)
// VULNERABLE: text/template with user input in template string
tmpl := fmt.Sprintf("Hello, %s!", userInput)
t, _ := template.New("").Parse(tmpl) // text/template does not escape!
// SAFE: html/template with user input as data
t, _ := htmltemplate.New("").Parse("Hello, {{.Name}}!")
t.Execute(w, map[string]string{"Name": userInput})
{{7*7}} as input would render 49, confirming template evaluation.render_template() instead of render_template_string().render_template('page.html', data=user_input) is safe{% extends %} and {% include %} with static paths