Repository navigation
fix: respect project template filter overrides before reporting built-ins - #189
Merged
Merged
Conversation
…ocessor A TEMPLATES bound in a function, called or not, or in a class configures nothing; a function reading, mutating or rebinding the module's TEMPLATES leaves the activation uncertain; a local TEMPLATES beside module settings changes nothing.
request_processor walked every node of every module and counted any assignment to TEMPLATES, so a function-local or class-level assignment activated the request context processor. It now walks the modules with their scope tables: an assignment counts only at module scope, and a mention counts only when the name resolves to the module's binding, or to nothing, as a star import gives. ScopeTable.scope_for accepts a lambda, whose scope the builder already records.
…e flow
A block rendering {{ block.super }} extends the parent's block: its filters stay fed by the render context, with the parent template as the place of the call, however block.super is rendered; a block without it replaces the parent's whole block; other overridden blocks stay excluded; a chain of templates keeps exactly the parents each level renders, once.
A template extending another replaced every block it defined in the parent, so the parent's filter applications dropped out of the render context flow even when the child rendered {{ block.super }}, which Django executes. A template now records the blocks that render block.super, and only the blocks defined without it are passed up as replaced, level by level.
A deployment declaration names its handler as the module binds it, and a module may bind that name as an alias of the function doing the work: main = actual. A model naming the alias's project symbol now applies to the function, or to the class's methods for a class alias. Aliases are module-level assignments of one name to another, followed transitively in source order; a name bound inside a function or class, or to a call, an import or any other value, is no alias.
…-ins A project tag library registering a filter of a built-in's name replaces it in every template loading the library before applying the filter, as Django's parser does; loads are ordered, selective loads honoured, Django's own libraries change nothing. A library the engine cannot find, read or understand, or several apps disagreeing, leaves the filter uncertain: no call is claimed and the load is listed among the unread templates, keeping the advisory under investigation (#183).
# Conflicts: # CHANGELOG.md
# Conflicts: # CHANGELOG.md
…rides # Conflicts: # CHANGELOG.md # src/coretrace_python/taint/templates.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #183.
A project tag library registering a filter of a built-in's name replaces the built-in in every template loading it before applying the filter, as Django's parser does.
{% load custom %}{{ bio|striptags }}was reported as a reachable, and with attacker input an exploitable, call todjango.template.defaultfilters.striptagseven whenapp/templatetags/custom.pyregisters its ownstriptags: the project's function is ordinary code, analysed as any other, and the template's call is no evidence about the built-in._read_scopesresolves each filter where it is applied: the built-in, unless the latest applicable{% load %}so far names a project library that certainly registers the name (nothing recorded) or may (the load is kept as unresolved). Loads are ordered as Django parses them,{% load a from lib %}selects, Django's own libraries change nothing.templatetags/*.pymodulesdiscover_filesalready lists, read with the HIR and the semantic layers:registermust resolve todjango.template.Librarywhatever the import spelling; the decorator and call forms ofregister.filterare read, at module level or underif,tryor a function; tag registrars are ignored. Anything the engine cannot follow, a name not written as a constant, unpacked arguments,registerpassed elsewhere (to a call or a decorator),filters=orregister.filters, anotherLibraryattribute, a file it cannot read or parse, makes the whole library uncertain, fail-closed.unreadchannel,app/templates/app/profile.html:1 loads 'custom', not found | not read | found in several files, soCoverage.unread_templatesand the VEXunder_investigationstatus need no change.OPTIONS["libraries"]andOPTIONS["builtins"]are not read, and a library found under notemplatetagsdirectory, such as one an installed package ships, is uncertain too (documented).escaped_templatesis untouched: a template loading an overriding library is still not established to escape.Tests:
tests/test_template_filter_overrides.py(60 cases, 52 failing before the change: reproduction, 17 registration forms, 7 import spellings, load order, selective loads, 11 unreadable forms, two apps agreeing or not, an override callingstrip_tagsreported at the library's line only,calls/filtersconsequences);pytest -m "not regression"1483 passed, 2 skipped; regression corpus 19 passed, snapshots unchanged;ruff check .andmypyclean.