Jinja2 Template Rules
Detects server-side template injection and unsafe template constructs in prompt, chat, and report templates.
The Jinja2 rule family turns findings on this surface into actionable records with rule ID, severity, CWE, OWASP LLM mapping, owner, release decision, and retest command.
Jinja2 templates appear in chat templates, RAG prompts, dashboards, and report generation. Unsafe templates can expose secrets or execute code.
Supported inputs
.j2.jinjaYAML prompt templatesGGUF tokenizer metadataHTML report templates
Typical attack scenarios
- A user-controlled prompt reaches a Jinja2 render call.
- A model chat template contains object traversal primitives.
- A report template exposes environment variables.
Detection logic
Sentinel ties Jinja2 evidence to reproducible signals such as file path, metadata, opcode, AST node, manifest field, dependency, or archive entry. The same signal should disappear when the finding is closed.
Triage
Do not read Jinja2 findings as scanner noise. Verify the evidence first, map the finding to a severity-based release decision, and then produce closure evidence with the same Sentinel command.
- Source: where did the file, manifest, prompt, archive, or dependency come from?
- Impact: code execution, data leakage, supply chain, or resource consumption?
- Control: allowlist, hash, sandbox, egress policy, or secret rotation?
- Evidence: does the same rule category return clean after the fix?
Remediation
Remediation should change the risk boundary, not merely silence the finding: remove executable formats, pin source or hash, narrow tool permissions, rotate secrets, or add runtime sandboxing.
CI policy
category: JINJA2
fail_on:
- CRITICAL
- HIGH
ticket_on:
- MEDIUM
retest: "sentinel sast ./src/ --rule JINJA2"Rule index
| Rule ID | Severity | Title | CWE | Fix Hint |
|---|---|---|---|---|
| JINJA2-SSTI-001 | CRITICAL | Server-Side Template Injection | CWE-94 | Treat prompt templates as code and review them before load. |
| JINJA2-UNSANDBOXED-TEMPLATE | HIGH | Unsandboxed Jinja2 Rendering | CWE-94 | Sandbox template rendering and avoid dynamic template strings. |
| JINJA2-SECRET-EXPOSURE | HIGH | Template Secret Exposure | CWE-200 | Keep credentials out of render context. |
JINJA2-SSTI-001 — Server-Side Template Injection
CRITICAL| Rule ID | JINJA2-SSTI-001 |
|---|---|
| Category | JINJA2 |
| Severity | CRITICAL |
| CWE | CWE-94 |
| OWASP LLM | LLM01 — Prompt Injection, LLM06 — Excessive Agency |
| FP Risk | LOW |
| Owner | Application security and backend/agent owner |
| Release decision | Block release; do not promote the artifact or code path until it is isolated. |
Description
Detects Jinja2 expressions that can traverse Python objects, access globals, or execute functions.
Why it matters
Jinja2 templates appear in chat templates, RAG prompts, dashboards, and report generation. Unsafe templates can expose secrets or execute code.
When it fires
Sentinel fires this rule in the Jinja2 category when it sees template tokens containing __class__, __mro__, __subclasses__, __globals__, cycler, joiner, or namespace abuse.. The finding should be reported with reproducible evidence such as file name, metadata, opcode, AST node, or manifest field.
Evidence format
Template tokens containing __class__, __mro__, __subclasses__, __globals__, cycler, joiner, or namespace abuse.
Expected evidence
The report should include the affected file or manifest path, observed signal, rule ID, severity, owner, and retest command required for closure.
False-positive notes
False-positive probability is low. If evidence points directly to a file, opcode, secret pattern, path, or manifest field, treat it as real and require closure evidence.
Triage
- Owner: Application security and backend/agent owner.
- Decision: Block release; do not promote the artifact or code path until it is isolated.
- Evidence: Template tokens containing __class__, __mro__, __subclasses__, __globals__, cycler, joiner, or namespace abuse.
- Closure: sentinel sast ./src/ --rule JINJA2 must return clean output.
How to fix
Never render user-controlled templates. Use SandboxedEnvironment and pass a minimal validated context.
CLI
sentinel sast ./src/ --rule JINJA2Policy example
rules:
JINJA2-SSTI-001:
owner: "Application security and backend/agent owner"
fail_on: ["CRITICAL", "HIGH"]
retest: "sentinel sast ./src/ --rule JINJA2"Expected output
JINJA2-SSTI-001 CRITICAL
Server-Side Template Injection
Treat prompt templates as code and review them before load.Example
template = "{{ request.args.q }} {{ config.__class__.__init__.__globals__ }}"
render_template_string(template)env = SandboxedEnvironment(autoescape=True)
template = env.get_template("safe_prompt.j2")
template.render(validated_context)Related rules
- JINJA2-UNSANDBOXED-TEMPLATE: Unsandboxed Jinja2 Rendering
- JINJA2-SECRET-EXPOSURE: Template Secret Exposure
JINJA2-UNSANDBOXED-TEMPLATE — Unsandboxed Jinja2 Rendering
HIGH| Rule ID | JINJA2-UNSANDBOXED-TEMPLATE |
|---|---|
| Category | JINJA2 |
| Severity | HIGH |
| CWE | CWE-94 |
| OWASP LLM | LLM01 — Prompt Injection |
| FP Risk | MEDIUM |
| Owner | Application security and backend/agent owner |
| Release decision | Treat as a release gate; remediation or explicit risk acceptance is required. |
Description
Flags Jinja2 render paths that use default Environment or render_template_string with untrusted template strings.
Why it matters
Jinja2 templates appear in chat templates, RAG prompts, dashboards, and report generation. Unsafe templates can expose secrets or execute code.
When it fires
Sentinel fires this rule in the Jinja2 category when it sees ast calls to environment(...), template(...), or render_template_string(...) without sandboxing and context validation.. The finding should be reported with reproducible evidence such as file name, metadata, opcode, AST node, or manifest field.
Evidence format
AST calls to Environment(...), Template(...), or render_template_string(...) without sandboxing and context validation.
Expected evidence
The report should include the affected file or manifest path, observed signal, rule ID, severity, owner, and retest command required for closure.
False-positive notes
False-positive probability is medium. Verify source, expected use, and owner first; add an allowlist if needed, but do not remove evidence from the report.
Triage
- Owner: Application security and backend/agent owner.
- Decision: Treat as a release gate; remediation or explicit risk acceptance is required.
- Evidence: AST calls to Environment(...), Template(...), or render_template_string(...) without sandboxing and context validation.
- Closure: sentinel sast ./src/ --rule JINJA2 must return clean output.
How to fix
Use SandboxedEnvironment, fixed template files, strict undefined behavior, and schema-validated context objects.
CLI
sentinel sast ./src/ --rule JINJA2Policy example
rules:
JINJA2-UNSANDBOXED-TEMPLATE:
owner: "Application security and backend/agent owner"
fail_on: ["CRITICAL", "HIGH"]
retest: "sentinel sast ./src/ --rule JINJA2"Expected output
JINJA2-UNSANDBOXED-TEMPLATE HIGH
Unsandboxed Jinja2 Rendering
Sandbox template rendering and avoid dynamic template strings.Example
template = "{{ request.args.q }} {{ config.__class__.__init__.__globals__ }}"
render_template_string(template)env = SandboxedEnvironment(autoescape=True)
template = env.get_template("safe_prompt.j2")
template.render(validated_context)Related rules
- JINJA2-SSTI-001: Server-Side Template Injection
- JINJA2-SECRET-EXPOSURE: Template Secret Exposure
JINJA2-SECRET-EXPOSURE — Template Secret Exposure
HIGH| Rule ID | JINJA2-SECRET-EXPOSURE |
|---|---|
| Category | JINJA2 |
| Severity | HIGH |
| CWE | CWE-200 |
| OWASP LLM | LLM02 — Sensitive Information Disclosure |
| FP Risk | MEDIUM |
| Owner | Application security and backend/agent owner |
| Release decision | Treat as a release gate; remediation or explicit risk acceptance is required. |
Description
Detects templates that render environment variables, credentials, request headers, or internal config objects.
Why it matters
Jinja2 templates appear in chat templates, RAG prompts, dashboards, and report generation. Unsafe templates can expose secrets or execute code.
When it fires
Sentinel fires this rule in the Jinja2 category when it sees template references env, environ, secrets, config, headers, cookies, or token-like variables.. The finding should be reported with reproducible evidence such as file name, metadata, opcode, AST node, or manifest field.
Evidence format
Template references env, environ, secrets, config, headers, cookies, or token-like variables.
Expected evidence
The report should include the affected file or manifest path, observed signal, rule ID, severity, owner, and retest command required for closure.
False-positive notes
False-positive probability is medium. Verify source, expected use, and owner first; add an allowlist if needed, but do not remove evidence from the report.
Triage
- Owner: Application security and backend/agent owner.
- Decision: Treat as a release gate; remediation or explicit risk acceptance is required.
- Evidence: Template references env, environ, secrets, config, headers, cookies, or token-like variables.
- Closure: sentinel sast ./src/ --rule JINJA2 must return clean output.
How to fix
Remove secrets from template context and pass only explicitly required display fields.
CLI
sentinel sast ./src/ --rule JINJA2Policy example
rules:
JINJA2-SECRET-EXPOSURE:
owner: "Application security and backend/agent owner"
fail_on: ["CRITICAL", "HIGH"]
retest: "sentinel sast ./src/ --rule JINJA2"Expected output
JINJA2-SECRET-EXPOSURE HIGH
Template Secret Exposure
Keep credentials out of render context.Example
template = "{{ request.args.q }} {{ config.__class__.__init__.__globals__ }}"
render_template_string(template)env = SandboxedEnvironment(autoescape=True)
template = env.get_template("safe_prompt.j2")
template.render(validated_context)Related rules
- JINJA2-SSTI-001: Server-Side Template Injection
- JINJA2-UNSANDBOXED-TEMPLATE: Unsandboxed Jinja2 Rendering