Repository navigation
feat: match curated entry points by suffix for untypeable receivers - #200
Merged
Merged
Conversation
Add Condition.present: the argument being given at all, whatever its value, is the condition, exclusive with values and default. A call giving it, positionally, by keyword or through a folded ** literal, meets it even when the value is unknown; a call surely without it is ruled out (reason absent); *args or an unreadable **mapping leaves it pending review. Closes #195.
Cover issue #197 before the implementation: the reproduction (Item.objects.annotate through a manager the engine cannot type), a declared queryset chain, an undeclared chain and a non-project receiver that must not match, ruled-out and pending conditions through the suffix, the advisories.json round trip with validation, and the ModelTable and SuffixIndex unit behaviour.
An advisory entry point may declare suffixes: a derived symbol of the project's own modules ending with a dot plus the suffix reaches the entry point, as a SuffixSink matches a sink. Suffixes load, dump and validate in advisories.json (at least two dot-separated names); SuffixIndex and affected_entries resolve exact and suffix matches for correlate(), the reachable-vulnerability detector and the vulnerable-dependency exclusions; advisory_suffix_sinks feeds the taint engine, and findings keep the advisory's symbol as entry_point and the derived one as symbol. ModelTable.sink now merges an exact sink with every matching suffix sink instead of returning the first, so an advisory sink on a derived symbol composes with objects.extra's SQL kind. No cache-key change: the advisory repr already carries the suffixes, and the project-prefix test can only flip for a module when the prefix module enters or leaves its transitive import closure, which module_keys already keys on. Closes #197.
…try-suffixes # Conflicts: # CHANGELOG.md # docs/plugins.md
Merged
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 #197. Stacked on #199 (
feat/argument-present-conditions); merge that one first.A curated entry point names its symbol canonically (
python.django.db.models.QuerySet.annotate), but a project reaches it through a manager on its own model,Item.objects.annotate(...), which the engine derives as the project symbolpython.app.models.Item.objects.annotate— the entry point never matched, and the five Django ORM advisories thekeyword_namecondition of #193 was built for could not be curated against real projects. The bundled Django models meet the same shape for sinks and solve it withSuffixSink("objects.raw").AdvisoryEntryPoint.suffixes: each suffix (at least two dot-separated names, so a bareannotateis rejected) matches a derived symbol on a dot boundary — verbatim theSuffixSinkrule — and only symbols of the project's own modules, enforced in one place (SuffixIndex.matches); a queryset chain is declared explicitly (objects.filter.annotate). Another package'sobjects.annotatenever matches.affected_entriesresolves exact then suffix matches for the three finding paths: the reachable-vulnerability detector (calls, reads, template filters), the vulnerable-dependency exclusions (so a contradicted condition through a suffix feedsruled_outand VEXnot_affected), andcorrelate(). The finding keeps the advisory's symbol asentry_pointand the derived one assymbol.advisory_suffix_sinksgives the taint engine aSuffixSink(suffix, ADVISORY)per curated suffix; in the workers,_Batch.projectcarries the project's modules so the index is identical serial and parallel (checked by hand underjobs=2).ModelTable.sinknow merges an exact sink with every matching suffix sink instead of returning the first: the shadowing found during Taint the keys of a **mapping expansion as the keyword names of the call #193's design (an advisory-only sink on a symbol endingobjects.extrasilently dropped Django's SQL kind) is fixed, with the SQL positions kept.module_keysalready keys on.Documented residual risk: a project symbol genuinely ending with a declared suffix (a project module named
objects) matches; the vulnerable range and the conditions still gate it.Tests:
tests/test_entry_point_suffixes.py(18 cases, failing before the change: the issue's reproduction withkeyword_namecomposing, the declared chain, the undeclared chain and a non-project receiver as negatives, the ruled-out and pending paths, the JSON round trip with six invalid suffixes, theModelTable/SuffixIndexunit behaviour); on the stacked branch: full suite 1613 passed, 2 skipped; regression corpus 19 passed, snapshots unchanged;ruff check .andmypyclean.