Skip to content

fix(jinja2): detect lipsum and get_flashed_messages __globals__ SSTI gadgets#1728

Open
back2matching wants to merge 1 commit into
promptfoo:mainfrom
back2matching:fix/jinja2-ssti-lipsum-gadgets
Open

fix(jinja2): detect lipsum and get_flashed_messages __globals__ SSTI gadgets#1728
back2matching wants to merge 1 commit into
promptfoo:mainfrom
back2matching:fix/jinja2-ssti-lipsum-gadgets

Conversation

@back2matching

Copy link
Copy Markdown

What

Adds the lipsum.__globals__ and get_flashed_messages.__globals__ global-access gadgets to JINJA2_SSTI_PATTERNS["global_access"], plus a generic \.__globals__ attribute pattern, and a regression test.

This is a detection-quality improvement (a gadget-enumeration completeness gap), not a security-vulnerability report. The classic weaponized forms are already caught today, so nothing here is a practical bypass. Per SECURITY.md this is the "detection quality / obfuscation outside implemented coverage" category, so I'm filing it as a normal PR rather than a private advisory.

Why

The global_access list already enumerates the sibling gadgets cycler, joiner, namespace, request.application, and config, but not lipsum or get_flashed_messages, both staples of public Jinja2 SSTI references. lipsum is a default Jinja2 global, so it's reachable in a plain chat-template render (the same pattern set the GGUF tokenizer.chat_template path uses).

Two gaps, one fix:

  1. Gadget list consistency. lipsum / get_flashed_messages were the only common global-access gadgets missing while their siblings are present.
  2. Dotted __globals__ reach. The existing __globals__[ pattern only catches the subscript form. Jinja2 resolves a.b by attribute then item, so x.__globals__.os is a working construct whose source text contains no __globals__[ and matched nothing before this change. The added \.__globals__ pattern closes that generically and covers future gadget objects.

Scope note: a fully weaponized payload usually still self-flags through its sink (e.g. os.popen( / eval(), which is a separate critical_injection pattern, so this is a completeness/consistency hardening rather than a bypass fix. The sandboxed render probe is unaffected.

Testing

tests/scanners/test_jinja2_template_scanner.py::TestJinja2TemplateScannerPatternCategories::test_detects_lipsum_and_get_flashed_messages_gadgets scans {{ lipsum.__globals__.os }} and {{ get_flashed_messages.__globals__.os }} (benign markers, no exploit chain) and asserts both are flagged as global_access. It fails on main (both produce zero findings) and passes with this change. Existing benign-template false-positive tests still pass (benign chat templates don't reference __globals__).

uv run ruff check, uv run ruff format --check, and uv run mypy on the changed files are clean; the jinja2 scanner + detector suites pass.

No operational exploit payloads are included; the gadget families referenced are long-public SSTI knowledge.

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.

1 participant