Adversarial fuzz worker

qa-fuzz-20260729-0002-template-probe

Session qa-fuzz-20260729-0002 · Worker template-probe

confirmed_bug

15/20 cases passed cleanly. 1 confirmed_bug reconfirms already-filed GH #167 (loop.index/loop.last misclassified as undeclared under --strict) -- not new, out of scope for PR #165. 1 not_a_bug note on minijinja's missing .items() method (verified alternatives work).

Fuzz run descriptionIterationsPassResult
Jinja rendering: loops, conditionals, includes, delimiters, and the loop.* builtin under --strict from the live campaign 20 15/20 FAIL

Inputs exercised

CaseTemplate / inputOutcome
template-11{% for x in items %}{{ loop.index }}{% endfor %} under --strictFAIL; loop.index misclassified as undeclared (feeds F1/GH #167 reconfirmation)
template-12{% if loop.last %}...{% endif %} inside a single for-loop under --strictFAIL; loop.last misclassified as undeclared (feeds F1/GH #167 reconfirmation)
template-15{% for k in mydict.items() %} with Unicode keysFAIL; .items() unsupported (feeds F2, not_a_bug)
template-16, 17, 18, 19include-cycle, include path-traversal escape, malformed custom-delimiter template, oversized nesting depthFAIL (expected); correctly rejected as intentional boundaries
template-01..10, 13, 14, 20Nested loops (3 levels, jagged/empty arrays), elif chains, single/multi-level includes, whitespace control, Unicode content, default()/missing-field handlingPASS; correct

Findings

F1-template-probe-loop-builtin-strict-misclassification (duplicate of GH #167)

Minimal template / frontmatter
{% for x in items %}{{ loop.index }}:{{ x }}{% if loop.last %} (last){% endif %}{% endfor %}
Input
{"items": ["a","b","c"]}
Expected
loop.* is a standard Jinja/minijinja builtin context object populated inside for-loops and must not be treated as an undeclared user variable under --strict.
Observed
--strict flags loop.index/loop.last as undeclared referenced tokens, causing a hard validation/render failure. Reproduces in the simplest single-loop template, 3/3 deterministic.
Requirement / ADR
Already tracked as GH #167 (filed from a prior campaign); out of scope for PR #165.
Requirement / ADR follow-up
No new requirement/ADR needed this round -- duplicate of an already-triaged, already-filed issue; defer to the existing GH #167 owner.
Root cause
Strict-mode undeclared-variable validation walks referenced identifiers without special-casing the loop.* builtin namespace injected by minijinja at render time.
Recommended fix
Exempt the loop.* builtin namespace from strict undeclared-variable checks in the validation pass (tracked under GH #167, not part of this PR's scope).

F2-template-probe-dict-items-method-unsupported (not_a_bug)

Minimal template / frontmatter
{% for k in mydict %}{{ k }}{% endfor %} vs {% for k in mydict.items() %}{{ k }}{% endfor %}
Input
{"mydict": {"éclair": 1, "café": 2}}
Expected
not_a_bug -- .items() is not part of the documented minijinja surface; correct alternatives already work.
Observed
minijinja has no Python-style .items() method (render error); the |items filter and bare for k in dict both verified working correctly with Unicode keys.
Requirement / ADR
minijinja intentionally does not implement Python's dict.items() method; this is a documented engine-surface boundary, not a gap.
Requirement / ADR follow-up
No new documentation needed -- behavior is intentionally unsupported and correct alternatives (|items filter, bare for-in) already work.
Root cause
n/a (engine-surface difference from Python, not a defect)
Recommended fix
None required; optionally note the .items() vs |items distinction in user-facing template-authoring docs.