Skip to content

python/flask: catch inline render_template_string() calls in dangerous-template-string - #4040

Open
shmulc8 wants to merge 1 commit into
semgrep:developfrom
shmulc8:fix/dangerous-template-string-inline-calls
Open

python/flask: catch inline render_template_string() calls in dangerous-template-string#4040
shmulc8 wants to merge 1 commit into
semgrep:developfrom
shmulc8:fix/dangerous-template-string-inline-calls

Conversation

@shmulc8

@shmulc8 shmulc8 commented Aug 18, 2026

Copy link
Copy Markdown

What

dangerous-template-string requires the template to be assigned to a variable before the call, so a template formatted inline at the call site is missed entirely:

# not flagged today
return flask.render_template_string(f"<h1>{request.url}</h1>")

All eight existing patterns are of the form $V = <formatted> ... render_template_string($V). This adds four that match the call expression itself — f-string, .format, %, concatenation. Matching the expression also covers return render_template_string(...), 404 for free, which is why the existing set needs two entries per formatting style.

The commented-out test

dangerous-template-string.py carries an error3 case commented out as ## Doesn't work yet. The assignment-plus-f-string form it describes is matched today; the block could never have passed because f'''{ extends "layout.html" }''' is not valid Python — the braces are parsed as f-string expressions. Rewritten with escaped braces so it parses, and enabled.

Tests

Five vulnerable cases and two # ok: cases added. The # ok: half is deliberate: it pins the rule against being widened into flagging every render_template_string call, which flask/security/audit/render-template-string already does at WARNING.

semgrep --test passes 1/1 on the rule.

@CLAassistant

CLAassistant commented Aug 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread python/flask/security/dangerous-template-string.py
Comment thread python/flask/security/dangerous-template-string.py
Comment thread python/flask/security/dangerous-template-string.py
@semgrep-code-dev-returntocorp

Copy link
Copy Markdown

Semgrep found 6 render-template-string findings:

Found a template created with string formatting. This is susceptible to server-side template injection and cross-site scripting attacks.

Comment thread python/flask/security/dangerous-template-string.py
@shmulc8
shmulc8 force-pushed the fix/dangerous-template-string-inline-calls branch 2 times, most recently from 8949589 to b6b7d40 Compare August 18, 2026 21:45
@shmulc8

shmulc8 commented Aug 18, 2026

Copy link
Copy Markdown
Author

For what it is worth, the whole rule also collapses into an allowlist:

  patterns:
  - pattern: flask.render_template_string($X, ...)
  - pattern-not: flask.render_template_string("...", ...)

It covers the same cases plus render_template_string(tpl) where tpl came from a function call, which none of the current patterns reach. The cost is that it anchors findings on the call line rather than the assignment line, which relocates four existing findings and needs four test annotations moved. Kept this PR as the targeted fix instead; happy to switch if you prefer that trade.

@shmulc8
shmulc8 force-pushed the fix/dangerous-template-string-inline-calls branch 2 times, most recently from 5f932cc to 8be86a1 Compare August 18, 2026 21:51
Every pattern in dangerous-template-string requires the template to be
assigned to a variable before the call, so a template formatted inline at
the call site is missed:

    return flask.render_template_string(f"<h1>{request.url}</h1>")

Adds four patterns matching the call expression itself (f-string, .format,
%, concatenation). Matching the expression also covers
`return render_template_string(...), 404` without needing a separate
pattern per formatting style, which is why the existing set has two
entries each.

Also enables the error3 test case that was commented out as "Doesn't work
yet". The assignment-plus-f-string form it describes has been matched for
a while; the block could never have passed because
f'''{  extends "layout.html"  }''' is not valid Python. Rewritten with
escaped braces so it parses, and it matches.

Test file gains five vulnerable cases and two `# ok:` cases, the latter
pinning the rule against being widened into flagging every
render_template_string call.
@shmulc8
shmulc8 force-pushed the fix/dangerous-template-string-inline-calls branch from 8be86a1 to 2904f2c Compare August 18, 2026 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants