coretrace-python-analyzer 0.15.0__tar.gz → 0.16.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/CHANGELOG.md +8 -0
  2. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/PKG-INFO +1 -1
  3. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/docs/plugins.md +5 -1
  4. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/docs/usage.md +64 -4
  5. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/pyproject.toml +1 -1
  6. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/__init__.py +1 -1
  7. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/dependency/reachable_vulnerability/reachable_vulnerability.py +9 -2
  8. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/django/django_models.py +4 -1
  9. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dependency/vex.py +10 -1
  10. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/engine.py +27 -3
  11. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/findings/coverage.py +4 -1
  12. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/interprocedural/__init__.py +8 -0
  13. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/interprocedural/summaries.py +173 -7
  14. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/plugins/api.py +7 -4
  15. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/taint/__init__.py +16 -1
  16. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/taint/engine.py +63 -4
  17. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/taint/models.py +20 -2
  18. coretrace_python_analyzer-0.16.0/src/coretrace_python/taint/templates.py +690 -0
  19. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_release.py +1 -1
  20. coretrace_python_analyzer-0.16.0/tests/test_template_context_flows.py +306 -0
  21. coretrace_python_analyzer-0.16.0/tests/test_template_filter_calls.py +283 -0
  22. coretrace_python_analyzer-0.16.0/tests/test_template_request_processor.py +215 -0
  23. coretrace_python_analyzer-0.15.0/src/coretrace_python/taint/templates.py +0 -250
  24. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/.github/workflows/ci.yml +0 -0
  25. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/.github/workflows/release.yml +0 -0
  26. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/.gitignore +0 -0
  27. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/LICENSE +0 -0
  28. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/NOTICE +0 -0
  29. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/README.md +0 -0
  30. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/docs/architecture.md +0 -0
  31. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/examples/add.py +0 -0
  32. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/examples/canonical_symbols.py +0 -0
  33. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/__main__.py +0 -0
  34. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/abstract/__init__.py +0 -0
  35. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/abstract/constants.py +0 -0
  36. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/abstract/heap.py +0 -0
  37. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/abstract/ranges.py +0 -0
  38. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/abstract/strings.py +0 -0
  39. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/abstract/values.py +0 -0
  40. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/analysis/__init__.py +0 -0
  41. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/analysis/manager.py +0 -0
  42. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/analysis/provider.py +0 -0
  43. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/dependency/dependency_policy/dependency_policy.py +0 -0
  44. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/dependency/dependency_policy/plugin.toml +0 -0
  45. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/dependency/reachable_vulnerability/plugin.toml +0 -0
  46. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/dependency/sample_advisories/plugin.toml +0 -0
  47. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/dependency/sample_advisories/sample_advisories.py +0 -0
  48. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/dependency/vulnerable_dependency/plugin.toml +0 -0
  49. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/dependency/vulnerable_dependency/vulnerable_dependency.py +0 -0
  50. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/aiohttp/aiohttp_models.py +0 -0
  51. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/aiohttp/plugin.toml +0 -0
  52. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/bottle/bottle_models.py +0 -0
  53. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/bottle/plugin.toml +0 -0
  54. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/cli/cli_models.py +0 -0
  55. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/cli/plugin.toml +0 -0
  56. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/credentials/credential_models.py +0 -0
  57. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/credentials/plugin.toml +0 -0
  58. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/db_drivers/db_driver_models.py +0 -0
  59. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/db_drivers/plugin.toml +0 -0
  60. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/django/plugin.toml +0 -0
  61. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/fastapi/fastapi_models.py +0 -0
  62. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/fastapi/plugin.toml +0 -0
  63. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/flask/flask_models.py +0 -0
  64. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/flask/plugin.toml +0 -0
  65. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/http_clients/http_client_models.py +0 -0
  66. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/http_clients/plugin.toml +0 -0
  67. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/python_stdlib/plugin.toml +0 -0
  68. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/python_stdlib/python_stdlib.py +0 -0
  69. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/sqlalchemy/plugin.toml +0 -0
  70. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/sqlalchemy/sqlalchemy_models.py +0 -0
  71. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/tornado/plugin.toml +0 -0
  72. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/models/tornado/tornado_models.py +0 -0
  73. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/secrets/config_secrets/config_secrets.py +0 -0
  74. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/secrets/config_secrets/plugin.toml +0 -0
  75. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/secrets/hardcoded_secrets/hardcoded_secrets.py +0 -0
  76. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/secrets/hardcoded_secrets/plugin.toml +0 -0
  77. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/code_injection/code_injection.py +0 -0
  78. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/code_injection/plugin.toml +0 -0
  79. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/command_injection/command_injection.py +0 -0
  80. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/command_injection/plugin.toml +0 -0
  81. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/insecure_deserialization/insecure_deserialization.py +0 -0
  82. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/insecure_deserialization/plugin.toml +0 -0
  83. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/nosql_injection/nosql_injection.py +0 -0
  84. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/nosql_injection/plugin.toml +0 -0
  85. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/open_redirect/open_redirect.py +0 -0
  86. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/open_redirect/plugin.toml +0 -0
  87. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/path_traversal/path_traversal.py +0 -0
  88. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/path_traversal/plugin.toml +0 -0
  89. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/plaintext_credentials/plaintext_credentials.py +0 -0
  90. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/plaintext_credentials/plugin.toml +0 -0
  91. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/sql_injection/plugin.toml +0 -0
  92. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/sql_injection/sql_injection.py +0 -0
  93. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/ssrf/plugin.toml +0 -0
  94. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/ssrf/ssrf.py +0 -0
  95. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/xss/plugin.toml +0 -0
  96. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/security/xss/xss.py +0 -0
  97. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/dangerous_eval/dangerous_eval.py +0 -0
  98. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/dangerous_eval/plugin.toml +0 -0
  99. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/flask_debug/flask_debug.py +0 -0
  100. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/flask_debug/plugin.toml +0 -0
  101. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/insecure_tempfile/insecure_tempfile.py +0 -0
  102. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/insecure_tempfile/plugin.toml +0 -0
  103. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/insecure_tls/insecure_tls.py +0 -0
  104. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/insecure_tls/plugin.toml +0 -0
  105. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/missing_timeout/missing_timeout.py +0 -0
  106. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/missing_timeout/plugin.toml +0 -0
  107. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/unsafe_archive/plugin.toml +0 -0
  108. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/unsafe_archive/unsafe_archive.py +0 -0
  109. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/unsafe_xml/plugin.toml +0 -0
  110. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/unsafe_xml/unsafe_xml.py +0 -0
  111. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/weak_crypto/plugin.toml +0 -0
  112. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/weak_crypto/weak_crypto.py +0 -0
  113. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/weak_random/plugin.toml +0 -0
  114. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/bundled/syntax/weak_random/weak_random.py +0 -0
  115. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/cache.py +0 -0
  116. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/cfg/__init__.py +0 -0
  117. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/cfg/builder.py +0 -0
  118. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/cfg/dominance.py +0 -0
  119. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/cfg/model.py +0 -0
  120. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/cli.py +0 -0
  121. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dataflow/__init__.py +0 -0
  122. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dataflow/lattice.py +0 -0
  123. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dataflow/solver.py +0 -0
  124. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dependency/__init__.py +0 -0
  125. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dependency/advisories.py +0 -0
  126. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dependency/correlation.py +0 -0
  127. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dependency/graph.py +0 -0
  128. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dependency/policy.py +0 -0
  129. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/dependency/sbom.py +0 -0
  130. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/findings/__init__.py +0 -0
  131. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/findings/baseline.py +0 -0
  132. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/findings/model.py +0 -0
  133. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/findings/provenance.py +0 -0
  134. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/findings/refutation.py +0 -0
  135. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/findings/suppressions.py +0 -0
  136. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/frontend/__init__.py +0 -0
  137. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/frontend/ast_adapter.py +0 -0
  138. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/frontend/parser.py +0 -0
  139. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/hir/__init__.py +0 -0
  140. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/hir/nodes.py +0 -0
  141. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/hir/visitors.py +0 -0
  142. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/interprocedural/callgraph.py +0 -0
  143. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/interprocedural/modulegraph.py +0 -0
  144. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/ir/__init__.py +0 -0
  145. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/ir/defuse.py +0 -0
  146. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/ir/lowering.py +0 -0
  147. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/ir/model.py +0 -0
  148. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/ir/printer.py +0 -0
  149. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/ir/ssa.py +0 -0
  150. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/plugins/__init__.py +0 -0
  151. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/plugins/detectors.py +0 -0
  152. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/plugins/loader.py +0 -0
  153. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/plugins/manifest.py +0 -0
  154. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/plugins/registry.py +0 -0
  155. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/plugins/secrets.py +0 -0
  156. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/reporters/__init__.py +0 -0
  157. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/reporters/json_format.py +0 -0
  158. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/reporters/report.py +0 -0
  159. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/reporters/sarif.py +0 -0
  160. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/reporters/text.py +0 -0
  161. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/semantic/__init__.py +0 -0
  162. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/semantic/identity.py +0 -0
  163. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/semantic/imports.py +0 -0
  164. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/semantic/scopes.py +0 -0
  165. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/semantic/symbols.py +0 -0
  166. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/source/__init__.py +0 -0
  167. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/source/manager.py +0 -0
  168. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/source/model.py +0 -0
  169. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/taint/routes.py +0 -0
  170. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/src/coretrace_python/taint/urls.py +0 -0
  171. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/Chatbot.json +0 -0
  172. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/DjangoGoat.json +0 -0
  173. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/Flask-Image-Editing-Website.json +0 -0
  174. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/InsecureGram.json +0 -0
  175. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/MiniBookApiServer.json +0 -0
  176. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/NPL-IA.json +0 -0
  177. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/Spam-Detection-Project.json +0 -0
  178. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/Vulnerable_fastapi.json +0 -0
  179. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/dvpwa.json +0 -0
  180. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/full-stack-fastapi-template.json +0 -0
  181. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/healthchecks.json +0 -0
  182. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/httpie.json +0 -0
  183. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/luigi.json +0 -0
  184. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/my_gdb.json +0 -0
  185. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/network-topologer.json +0 -0
  186. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/pygoat.json +0 -0
  187. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/uploadbox-cloud-storage-solution.json +0 -0
  188. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/vulnerable-flask.json +0 -0
  189. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/expected/yt-fts.json +0 -0
  190. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/fixtures/vulnerable-flask/README.md +0 -0
  191. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/fixtures/vulnerable-flask/app.py +0 -0
  192. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/fixtures/vulnerable-flask/requirements.txt +0 -0
  193. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/fixtures/vulnerable-flask/vulnerable_services.py +0 -0
  194. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/regression/repositories.toml +0 -0
  195. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_advisory_evidence.py +0 -0
  196. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_advisory_feeds.py +0 -0
  197. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_advisory_url_host.py +0 -0
  198. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_aiohttp_models.py +0 -0
  199. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_analysis_manager.py +0 -0
  200. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_architecture.py +0 -0
  201. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_argument_conditions.py +0 -0
  202. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_attacker_arguments.py +0 -0
  203. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_audit_detectors.py +0 -0
  204. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_baseline.py +0 -0
  205. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_cache.py +0 -0
  206. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_cfg.py +0 -0
  207. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_class_keywords_with_targets.py +0 -0
  208. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_cli.py +0 -0
  209. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_closures.py +0 -0
  210. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_code_injection.py +0 -0
  211. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_config_secrets_coverage.py +0 -0
  212. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_constants.py +0 -0
  213. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_correlation.py +0 -0
  214. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_credential_context.py +0 -0
  215. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_dataflow.py +0 -0
  216. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_dependencies.py +0 -0
  217. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_detectors.py +0 -0
  218. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_discovery.py +0 -0
  219. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_django_http_clients.py +0 -0
  220. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_django_routes.py +0 -0
  221. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_django_safe_values.py +0 -0
  222. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_docs.py +0 -0
  223. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_dominance.py +0 -0
  224. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_emit_ir.py +0 -0
  225. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_exceptions.py +0 -0
  226. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_factories_match_loop_else.py +0 -0
  227. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_fail_on.py +0 -0
  228. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_fastapi_cli_precision.py +0 -0
  229. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_frameworks.py +0 -0
  230. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_frontend_gaps.py +0 -0
  231. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_heap.py +0 -0
  232. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_hex_digests.py +0 -0
  233. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_hir_builder.py +0 -0
  234. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_imports.py +0 -0
  235. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_interprocedural.py +0 -0
  236. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_interprocedural_taint.py +0 -0
  237. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_ir.py +0 -0
  238. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_match_patterns.py +0 -0
  239. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_members.py +0 -0
  240. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_module_level.py +0 -0
  241. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_nonlocal_writeback.py +0 -0
  242. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_nosql_injection.py +0 -0
  243. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_open_redirect_destinations.py +0 -0
  244. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_operator_sources.py +0 -0
  245. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_packaging.py +0 -0
  246. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_parallel.py +0 -0
  247. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_parser.py +0 -0
  248. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_plaintext_credentials.py +0 -0
  249. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_plugins.py +0 -0
  250. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_project.py +0 -0
  251. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_project_models.py +0 -0
  252. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_project_validators.py +0 -0
  253. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_provenance.py +0 -0
  254. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_pyir_imports.py +0 -0
  255. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_read_entry_points.py +0 -0
  256. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_real_code_precision.py +0 -0
  257. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_redirect_targets.py +0 -0
  258. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_refutation.py +0 -0
  259. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_refutation_evidence.py +0 -0
  260. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_regression.py +0 -0
  261. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_relative_paths.py +0 -0
  262. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_remaining_limits.py +0 -0
  263. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_reporters.py +0 -0
  264. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_safe_arguments.py +0 -0
  265. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_scale.py +0 -0
  266. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_scopes.py +0 -0
  267. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_secrets_sbom.py +0 -0
  268. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_self_state.py +0 -0
  269. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_source_manager.py +0 -0
  270. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_ssa.py +0 -0
  271. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_ssrf_destinations.py +0 -0
  272. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_ssrf_targets.py +0 -0
  273. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_summary_sanitizers.py +0 -0
  274. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_suppressions.py +0 -0
  275. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_symbol_resolution.py +0 -0
  276. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_symbols.py +0 -0
  277. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_syntactic_rules.py +0 -0
  278. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_syntax_control_flow.py +0 -0
  279. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_syntax_coverage.py +0 -0
  280. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_syntax_expressions.py +0 -0
  281. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_taint.py +0 -0
  282. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_template_escaping.py +0 -0
  283. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_tornado_bottle_models.py +0 -0
  284. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_url_proof.py +0 -0
  285. {coretrace_python_analyzer-0.15.0 → coretrace_python_analyzer-0.16.0}/tests/test_vex.py +0 -0
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.16.0 (2026-09-27)
4
+
5
+ ### Advisories
6
+
7
+ - A filter of Django's own libraries that a project template applies is a call to the function behind it, at the template's line: `{{ bio|striptags }}` calls `django.template.defaultfilters.striptags`, and so do filters in tag arguments and `{% filter %}` blocks. An advisory entry point naming that function is reachable there, whether or not a Python call names the template, since a class-based view renders its `template_name` inside Django. A template the analyzer cannot read may apply any filter: when the project names one by an expression, or by a name found under no `templates` directory, in `render`, `render_to_string`, `TemplateResponse`, `{% include %}` or `{% extends %}`, an advisory whose entry points include a template filter stays `under_investigation` in the VEX document, and the notes say where. `render`, `TemplateResponse` and `SimpleTemplateResponse` are now template renders like `render_to_string` (#146).
8
+ - Attacker input in a render context reaching a template filter makes an advisory entry point naming that filter exploitable at the render call. The analyzer links them only where it is certain of the value: a dict literal with constant keys that the render call alone uses, and a filter the rendered template applies to a context variable, directly or through `{% for %}`, `{% with %}`, constant `{% include %}` and `{% extends %}`, earlier filter arguments and `{% filter %}` blocks, in the blocks that render. A name a tag binds shadows the context, and `{% include ... only %}` passes none of it. The filter's value is its first argument, the filter's own argument its second. A project function rendering what it receives carries it the same way (#146).
9
+ - The request the `request` context processor adds reaches a template's filters too, as `{{ request.GET.q|striptags }}`, only where the analyzer is certain of it: every Django template engine the settings assign to `TEMPLATES`, as literals no other code names, lists the processor; the render call passes the request (`render`, `TemplateResponse`, `render_to_string` given `request`) with a certain context, absent or a dict literal; nothing shadows `request`; and the template reads a text attribute of the request object, such as `GET`, `POST`, `COOKIES` or `headers`. Otherwise the filter stays reachable (#146).
10
+
3
11
  ## 0.15.0 (2026-09-26)
4
12
 
5
13
  ### Precision
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: coretrace-python-analyzer
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: Static security analysis infrastructure for Python code
5
5
  Project-URL: Homepage, https://github.com/CoreTrace/coretrace-python-analyzer
6
6
  Project-URL: Repository, https://github.com/CoreTrace/coretrace-python-analyzer
@@ -157,7 +157,7 @@ class BottleModels(ModelPlugin):
157
157
  | `RouteRegistrar(symbol, argument, label, kinds=ALL, keyword=None)` | A call registering a view at argument `argument` (or `keyword`), such as Django's `path`; the view receives `label` input. |
158
158
  | `SuffixSink(suffix, kinds, positions=())` | A sink matched by the end of the symbol, for methods of any class such as `objects.raw`. |
159
159
  | `SafeArgument(symbol, argument, values, position=None, kinds=ALL)` | A call to the sink `symbol` whose `argument` (by keyword, or at `position`) denotes one of `values` is not a sink for `kinds`, such as `yaml.load` with `Loader=yaml.SafeLoader`. Values are written as the analyzer records arguments: a symbol by its canonical name, a constant as Python writes it (`True`). Only a value given explicitly makes the call safe. |
160
- | `TemplateRender(symbol, position=0, keyword="template_name")` | A call rendering, with autoescaping, the template named by its argument at `position` or `keyword`, such as `render_to_string`. What it returns carries no `HTML` when the name is written in the call and the project's template escapes everything it prints (see the usage guide). |
160
+ | `TemplateRender(symbol, position=0, keyword="template_name", context=1, request=None)` | A call rendering, with autoescaping, the template named by its argument at `position` or `keyword`, such as `render_to_string`, with the variables of its argument at `context` or `context=` and the request at `request` or `request=` (None: the call takes none); it makes the filter calls the template applies, fed from that context and, with the `request` context processor, that request (see the usage guide). What it returns carries no `HTML` when the name is written in the call and the project's template escapes everything it prints (see the usage guide). A name the analyzer cannot read keeps an advisory a template filter reaches under investigation in the VEX document. |
161
161
  | `Validator(symbol, kinds=ALL, argument=0)` | A callable whose truth proves its argument safe for `kinds`, such as `re.fullmatch`. A flow guarded by it is refuted when it carries no other kind into the sink, and is a hotspot otherwise: a redirect validator does not make a shell command safe. `symbol` may be a function of the project, by its project symbol (`python.hc.accounts.views._allow_redirect`), which then counts wherever it is called, in its own module too. |
162
162
  | `RequestObject(symbol, text=())` | The inputs from `symbol`, an entry point, a route registrar, a typed parameter or a source, are request objects. A view receives the request first (after `self`), then URL parameters, which are text. Reading one of the request's `text` attributes gives text, as Django's `GET` or aiohttp's `query`; its body and files keep the request's kinds. An attribute read counts only when every source of the value is such a request. |
163
163
  | `AuthorizationGuard(symbol, label)` | A decorator or a condition restricting who reaches the code, such as `login_required`; a flow behind it is a hotspot. |
@@ -258,6 +258,10 @@ one, and the label of the entry point it is (`http` for a route, `argv` for a co
258
258
  when the models make it one. `ctx.call_graph(module)` gives each function's call sites
259
259
  (`sites(function)`) and the symbols it reads, called or not (`reads(function)`: reading
260
260
  `request.form['name']` reads `python.flask.request.form`), each where it first reads it.
261
+ `ctx.templates` gives the templates found under the project's `templates` directories:
262
+ their `names`, the filters they apply as `calls` (each a `FilterCall(symbol, span)`, the
263
+ function behind the filter and where the template applies it), and where they name a
264
+ template the analyzer cannot read (`unread`).
261
265
  The shipped `vulnerable-dependency`, `reachable-vulnerability` and `dependency-policy`
262
266
  plugins are of this kind.
263
267
 
@@ -241,7 +241,7 @@ the directory of the checked file; a path outside it is printed as it is.
241
241
  ```json
242
242
  {
243
243
  "schema_version": 1,
244
- "tool": {"name": "coretrace-python-analyzer", "version": "0.15.0"},
244
+ "tool": {"name": "coretrace-python-analyzer", "version": "0.16.0"},
245
245
  "root": "/home/me/project",
246
246
  "findings": [
247
247
  {
@@ -273,7 +273,7 @@ bytes. A single-file check lists no components.
273
273
 
274
274
  ```json
275
275
  "tool": {
276
- "name": "coretrace-python-analyzer", "version": "0.15.0",
276
+ "name": "coretrace-python-analyzer", "version": "0.16.0",
277
277
  "components": [
278
278
  {"kind": "plugin", "name": "curated-advisories", "version": "2026.09.25", "digest": "sha256:…"},
279
279
  {"kind": "advisories", "name": "advisories.json", "digest": "sha256:…"}
@@ -362,6 +362,57 @@ it is reachable, called or not — `request.form['name']`, `for key in request.f
362
362
  `request.form.get('name')` all read it. A function reading it several times is reported
363
363
  once, where it first reads it.
364
364
 
365
+ A filter of Django's own libraries that a project template applies is a call to the
366
+ function behind it, placed at the template's line: `{{ bio|striptags }}` calls
367
+ `python.django.template.defaultfilters.striptags`, and so do filters in tag arguments
368
+ (`{% if bio|striptags %}`) and `{% filter %}` blocks. A template counts whether or not a
369
+ Python call names it, since a class-based view renders its `template_name` inside
370
+ Django. Most filters are functions of the same name in `django.template.defaultfilters`;
371
+ `escape`, `escapejs`, `linebreaks`, `phone2numeric`, `slice`, `timesince` and `timeuntil`
372
+ are `<name>_filter` there, and the filters of `i18n`, `l10n`, `tz` and `humanize` are in
373
+ their library's module (`timezone` is `django.templatetags.tz.do_timezone`).
374
+
375
+ Attacker input in the render context makes the filter exploitable at the render call:
376
+ `render(request, "app/profile.html", {"bio": request.POST["bio"]})` with
377
+ `{{ bio|striptags }}`. The analyzer links a context value to a filter only where it is
378
+ certain of it:
379
+
380
+ - The context is a dict literal with constant keys, used by the render call and
381
+ nothing else, written in the call or through a variable. A dict mutated or passed
382
+ elsewhere, one unpacking another (`**extra`), or a context built any other way leaves
383
+ the filter reachable.
384
+ - The filter's value is a context variable, directly or through `{% for %}` and
385
+ `{% with %}`, the templates the template includes or extends by a constant name, the
386
+ arguments of the filters before it, or the output of a `{% filter %}` block. A name a
387
+ tag binds shadows the context, and `{% include ... only %}` passes none of it.
388
+ - The filter renders: a template extending another renders only its blocks, which
389
+ replace the blocks of that name in what it extends.
390
+ - One file has the template's name; of two files of the same name, which one renders
391
+ depends on the loaders.
392
+
393
+ The filter's value is its first argument and its argument (`cut:bio`) its second, so an
394
+ entry point naming only the value in `attacker_arguments` is not exploitable through
395
+ the argument. A project function rendering the values it receives carries them the same
396
+ way.
397
+
398
+ With the `django.template.context_processors.request` context processor, a template
399
+ rendered with the request reads it as `request`: `{{ request.GET.q|striptags }}` is
400
+ exploitable at the render call too. The analyzer counts it only where all of these hold:
401
+
402
+ - The project's settings assign `TEMPLATES` a literal list, every `DjangoTemplates`
403
+ engine of it lists the processor in a literal `context_processors`, and no other code
404
+ of the project names `TEMPLATES`. A mere mention of the processor proves nothing.
405
+ - The render call passes the request: `render` and `TemplateResponse` always do,
406
+ `render_to_string` when given `request`, `SimpleTemplateResponse` never.
407
+ - The render's context is certain, absent or a dict literal as above, so it cannot hide
408
+ a `request` entry. An entry of that name, a name a tag binds or `{% include ... only %}`
409
+ shadows the processor's request.
410
+ - The template reads text the user controls: an attribute the request object lists
411
+ among its text attributes, such as `GET`, `POST`, `COOKIES` or `headers`; not `user` or
412
+ `session`.
413
+
414
+ Through a project function, only the context entries are followed.
415
+
365
416
  Most vulnerabilities need attacker input in one argument: the path `send_from_directory`
366
417
  serves, not its `download_name`; the URL `requests.get` fetches, not its body. An entry
367
418
  point may name them in `attacker_arguments`, by keyword `argument` and, when it may be
@@ -444,16 +495,25 @@ check, including findings the policy accepts or a comment suppresses:
444
495
  | Status | When |
445
496
  |---|---|
446
497
  | `affected` | The project's code reaches the vulnerable code. The notes give each place and its level, `reachable` or `exploitable`. |
447
- | `not_affected` | Justified as `vulnerable_code_not_in_execute_path`, only when all of these hold: the advisory names entry points, no code of the project reaches them, every file and function was analysed, and a lock file (`uv.lock` or `poetry.lock`) shows that no other package requires the vulnerable one. The impact statement names the entry points and any calls ruled out by their arguments. |
498
+ | `not_affected` | Justified as `vulnerable_code_not_in_execute_path`, only when all of these hold: the advisory names entry points, no code of the project reaches them, every file and function was analysed, every template the project names was read if a template filter is among them, and a lock file (`uv.lock` or `poetry.lock`) shows that no other package requires the vulnerable one. The impact statement names the entry points and any calls ruled out by their arguments. |
448
499
  | `under_investigation` | Anything else. The notes say which condition failed. |
449
500
 
501
+ A template the analyzer cannot read may apply any filter. The project names one when
502
+ `render`, `render_to_string`, `TemplateResponse`, an `{% include %}` or an `{% extends %}`
503
+ names a template by an expression, or by a name found under no `templates` directory,
504
+ including one an installed package ships; a template file that cannot be read counts
505
+ too. An advisory whose entry points include a template filter then stays
506
+ `under_investigation`, and the notes list where the project names each such template
507
+ (`app.views:12 names a template by an expression`). A template named elsewhere, such as
508
+ a class-based view's `template_name`, is not checked.
509
+
450
510
  `not_affected` needs the lock-file check because the analyzer reads the project's code,
451
511
  not the code of installed packages. A framework calling the vulnerable function on the
452
512
  project's behalf would go unseen. Without a lock file, a package is never
453
513
  `not_affected`. The document's `@id` derives from its statements, so two runs with the
454
514
  same result share it; its `author` is `Unknown Author`, as OpenVEX tools write when they
455
515
  cannot know it. Its `tooling` names the analyzer and each component with its digest
456
- (`coretrace-python-analyzer 0.15.0; curated-advisories 2026.09.25 (sha256:…)`), so the
516
+ (`coretrace-python-analyzer 0.16.0; curated-advisories 2026.09.25 (sha256:…)`), so the
457
517
  `@id` changes with the advisory data a statement was decided with.
458
518
 
459
519
  ## Large projects
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "coretrace-python-analyzer"
7
- version = "0.15.0"
7
+ version = "0.16.0"
8
8
  description = "Static security analysis infrastructure for Python code"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,4 +1,4 @@
1
1
  """CoreTrace's Python static analysis frontend."""
2
2
 
3
- __version__ = "0.15.0"
3
+ __version__ = "0.16.0"
4
4
 
@@ -1,5 +1,6 @@
1
1
  """Calls, anywhere in the project, to an API affected by a vulnerable requirement, and
2
- reads of an affected attribute whose getter runs the vulnerable code."""
2
+ reads of an affected attribute whose getter runs the vulnerable code. A filter a project
3
+ template applies is a call to the function behind it, at the template's line."""
3
4
 
4
5
  from __future__ import annotations
5
6
 
@@ -56,6 +57,10 @@ class ReachableVulnerabilityPlugin(ProjectPlugin):
56
57
  reported.add((advisory, symbol))
57
58
  check = check_conditions(entry, None)
58
59
  findings.append(_reached(advisory, symbol, read.location, function, check))
60
+ for call in ctx.templates.calls:
61
+ for advisory in affected.get(call.symbol, ()):
62
+ check = check_conditions(advisory.entry_point(call.symbol), None)
63
+ findings.append(_reached(advisory, call.symbol, call.span, None, check))
59
64
  return findings
60
65
 
61
66
 
@@ -67,7 +72,9 @@ def _read_through(symbol: SymbolId) -> Iterator[SymbolId]:
67
72
  yield SymbolId(".".join(components[:end]))
68
73
 
69
74
 
70
- def _reached(advisory: Advisory, symbol: SymbolId, span: SourceSpan, function: str, check: ConditionCheck) -> Finding:
75
+ def _reached(
76
+ advisory: Advisory, symbol: SymbolId, span: SourceSpan, function: str | None, check: ConditionCheck
77
+ ) -> Finding:
71
78
  return Finding(
72
79
  rule_id="reachable-vulnerability",
73
80
  message=(
@@ -139,7 +139,10 @@ class DjangoModels(ModelPlugin):
139
139
  Sink(_sym("django.http.HttpResponseRedirect"), TaintKind.REDIRECT, _TARGET_ONLY),
140
140
  Sink(_sym("django.http.HttpResponsePermanentRedirect"), TaintKind.REDIRECT, _TARGET_ONLY),
141
141
  Sanitizer(_sym("django.utils.html.escape"), TaintKind.HTML),
142
- TemplateRender(_sym("django.template.loader.render_to_string")),
142
+ TemplateRender(_sym("django.template.loader.render_to_string"), request=2),
143
+ TemplateRender(_sym("django.shortcuts.render"), 1, context=2, request=0),
144
+ TemplateRender(_sym("django.template.response.TemplateResponse"), 1, "template", 2, 0),
145
+ TemplateRender(_sym("django.template.response.SimpleTemplateResponse"), 0, "template"),
143
146
  Sanitizer(_sym("django.utils.html.conditional_escape"), TaintKind.HTML),
144
147
  # The masked CSRF secret: ASCII letters and digits only, a malformed cookie is
145
148
  # replaced before it is used.
@@ -7,7 +7,8 @@ subcomponent of the project:
7
7
  exploitable finding, whatever the policy or a suppression did with it;
8
8
  - ``not_affected``, as ``vulnerable_code_not_in_execute_path``, only when the advisory is
9
9
  curated (it names entry points), no code of the project reaches them, every file and
10
- function was analysed, and a lock file shows that no other package requires the
10
+ function was analysed, every template the project names was read when a template
11
+ filter can reach them, and a lock file shows that no other package requires the
11
12
  vulnerable one, since the code of installed packages is not analysed;
12
13
  - ``under_investigation`` otherwise, with the reason in its notes.
13
14
  """
@@ -25,6 +26,7 @@ from coretrace_python.dependency.graph import Advisory, DependencyGraph, Require
25
26
  from coretrace_python.dependency.sbom import purl
26
27
  from coretrace_python.findings import Component, Finding
27
28
  from coretrace_python.findings.coverage import Coverage
29
+ from coretrace_python.taint import FILTER_FUNCTIONS
28
30
 
29
31
  CONTEXT = "https://openvex.dev/ns/v0.2.0"
30
32
  # OpenVEX's shared namespace for documents without an IRI of their own, and the author
@@ -33,6 +35,8 @@ NAMESPACE = "https://openvex.dev/docs/public/vex-"
33
35
  AUTHOR = "Unknown Author"
34
36
  # Evidence levels that put the vulnerable code in the project's execution path, lowest first.
35
37
  REACHED = ("reachable", "exploitable")
38
+ # What a template calls: a template the engine cannot read may reach these.
39
+ _TEMPLATE_CALLS = frozenset(FILTER_FUNCTIONS.values())
36
40
 
37
41
 
38
42
  def render_vex(
@@ -140,6 +144,11 @@ def _status(
140
144
  f"No analysed code reaches {entries}, but {', '.join(partial)} could not be fully "
141
145
  f"analysed.{ruled}"
142
146
  )
147
+ if coverage.unread_templates and _TEMPLATE_CALLS.intersection(advisory.reachable_symbols):
148
+ return _investigating(
149
+ f"No analysed code reaches {entries}, but a template can reach them, and the engine could "
150
+ f"not read every template the project names: {'; '.join(coverage.unread_templates)}.{ruled}"
151
+ )
143
152
  required_by = dependencies.required_by(package)
144
153
  if required_by is None:
145
154
  return _investigating(
@@ -83,6 +83,8 @@ from coretrace_python.interprocedural import (
83
83
  SummaryAnalysis,
84
84
  SummaryIndex,
85
85
  SymbolRead,
86
+ TemplateCalls,
87
+ TemplateCallsAnalysis,
86
88
  build_module_graph,
87
89
  discover_sources,
88
90
  project_symbol,
@@ -124,7 +126,10 @@ from coretrace_python.taint import (
124
126
  TaintAnalysis,
125
127
  TaintKind,
126
128
  escaped_templates,
129
+ project_templates,
127
130
  registered_routes,
131
+ request_processor,
132
+ unread_renders,
128
133
  )
129
134
  from coretrace_python.taint.urls import flow_url
130
135
 
@@ -158,6 +163,7 @@ ALL_ANALYSES: tuple[AnyAnalysis, ...] = (
158
163
  RegisteredRoutes,
159
164
  EscapedTemplates,
160
165
  ClearingAnalysis,
166
+ TemplateCallsAnalysis,
161
167
  )
162
168
 
163
169
 
@@ -198,6 +204,7 @@ class ResultsEvicted(TransformationPass):
198
204
  RegisteredRoutes,
199
205
  EscapedTemplates,
200
206
  ClearingAnalysis,
207
+ TemplateCallsAnalysis,
201
208
  }
202
209
  )
203
210
 
@@ -431,13 +438,20 @@ def analyze_project(
431
438
  for symbol, registered in _routes_of(analysable[name]).items():
432
439
  routes.setdefault(symbol, registered)
433
440
  escaped = escaped_templates(root)
441
+ templates = project_templates(root)
434
442
  clearing = models.clearing(escaped)
443
+ template_calls = models.template_calls(
444
+ templates.filters, request_processor(modules[name] for name in sorted(analysable))
445
+ )
435
446
  for manager in analysable.values():
436
447
  manager.provide(RegisteredRoutes, routes)
437
448
  manager.provide(EscapedTemplates, escaped)
438
449
  manager.provide(ClearingAnalysis, clearing)
450
+ manager.provide(TemplateCallsAnalysis, template_calls)
439
451
 
440
- configuration = _configuration_key(components, plugins, models, advisories, dependencies, routes, escaped)
452
+ configuration = _configuration_key(
453
+ components, plugins, models, advisories, dependencies, routes, escaped, template_calls
454
+ )
441
455
  keys = module_keys(
442
456
  graph,
443
457
  {name: fingerprint(configuration, str(files[name].source_id), name, files[name].text) for name in analysable},
@@ -479,6 +493,7 @@ def analyze_project(
479
493
  advisory_paths,
480
494
  _encode_routes(routes),
481
495
  tuple(sorted(escaped)),
496
+ template_calls,
482
497
  ),
483
498
  )
484
499
  for component in pending
@@ -516,7 +531,9 @@ def analyze_project(
516
531
  frozenset(),
517
532
  reads={f: tuple(r) for f, r in reads.items()},
518
533
  )
519
- context = ProjectContext(graph, dependencies, advisories, analysable, call_graphs, policy, root, functions)
534
+ context = ProjectContext(
535
+ graph, dependencies, advisories, analysable, call_graphs, policy, root, functions, templates
536
+ )
520
537
  for plugin in all_plugins:
521
538
  if isinstance(plugin, ProjectPlugin):
522
539
  findings.extend(plugin.analyze_project(context))
@@ -526,6 +543,9 @@ def analyze_project(
526
543
  findings = [_sourced(finding, origins) for finding in findings]
527
544
  accepted = tuple(f for f in findings if policy.accepts(f))
528
545
  kept, suppressed = partition(apply_policy(policy, findings), _text_of(sources))
546
+ unread = list(templates.unread)
547
+ for name in sorted(call_graphs):
548
+ unread.extend(unread_renders(name, call_graphs[name], models, templates.names))
529
549
  return ProjectAnalysis(
530
550
  graph,
531
551
  index,
@@ -534,7 +554,7 @@ def analyze_project(
534
554
  MappingProxyType(keys),
535
555
  reused,
536
556
  advisories,
537
- Coverage(tuple(sorted(coverage, key=lambda c: c.path))),
557
+ Coverage(tuple(sorted(coverage, key=lambda c: c.path)), tuple(unread)),
538
558
  suppressed,
539
559
  accepted,
540
560
  components,
@@ -686,6 +706,7 @@ class _Batch:
686
706
  advisory_paths: tuple[Path, ...] = ()
687
707
  routes: tuple[tuple[str, str, str, int], ...] = ()
688
708
  escaped: tuple[str, ...] = ()
709
+ template_calls: TemplateCalls = field(default_factory=TemplateCalls)
689
710
 
690
711
 
691
712
  def _analyse_batch(batch: _Batch) -> dict[str, dict[str, Any]]:
@@ -713,6 +734,7 @@ def _analyse_batch(batch: _Batch) -> dict[str, dict[str, Any]]:
713
734
  manager.provide(RegisteredRoutes, routes)
714
735
  manager.provide(EscapedTemplates, escaped)
715
736
  manager.provide(ClearingAnalysis, models.clearing(escaped))
737
+ manager.provide(TemplateCallsAnalysis, batch.template_calls)
716
738
  module_plugins = tuple(p for p in all_plugins if not isinstance(p, ProjectPlugin))
717
739
  results = _analyse_managers(managers, decode_index(batch.seed), module_plugins, affected)
718
740
  return {name: encode(entry) for name, entry in results.items()}
@@ -741,6 +763,7 @@ def _configuration_key(
741
763
  dependencies: DependencyGraph,
742
764
  routes: Routes | None = None,
743
765
  escaped: frozenset[str] = frozenset(),
766
+ template_calls: TemplateCalls | None = None,
744
767
  ) -> str:
745
768
  """Everything a module's results depend on besides the project sources (§11)."""
746
769
 
@@ -758,6 +781,7 @@ def _configuration_key(
758
781
  repr(dependencies.errors),
759
782
  repr(_encode_routes(routes or {})),
760
783
  repr(sorted(escaped)),
784
+ repr(template_calls),
761
785
  )
762
786
 
763
787
 
@@ -2,7 +2,9 @@
2
2
 
3
3
  "No findings" only means something when the reader knows what was analysed. Each file
4
4
  is ``analysed``, a ``syntax-error`` (the frontend rejected it) or ``unreadable`` (it could
5
- not be decoded); analysed files count their functions and how many lowered.
5
+ not be decoded); analysed files count their functions and how many lowered. The
6
+ templates the project names but the run could not read are listed, each where the
7
+ project names it: they may call any template filter.
6
8
  """
7
9
 
8
10
  from __future__ import annotations
@@ -21,6 +23,7 @@ class FileCoverage:
21
23
  @dataclass(frozen=True)
22
24
  class Coverage:
23
25
  details: tuple[FileCoverage, ...] = ()
26
+ unread_templates: tuple[str, ...] = ()
24
27
 
25
28
  @property
26
29
  def files(self) -> int:
@@ -20,6 +20,7 @@ from coretrace_python.interprocedural.modulegraph import (
20
20
  project_symbol,
21
21
  )
22
22
  from coretrace_python.interprocedural.summaries import (
23
+ FILTER_ARGUMENTS,
23
24
  Cleared,
24
25
  Clearing,
25
26
  ClearingAnalysis,
@@ -31,10 +32,14 @@ from coretrace_python.interprocedural.summaries import (
31
32
  SummaryAnalysis,
32
33
  SummaryIndex,
33
34
  SummaryTable,
35
+ TemplateCalls,
36
+ TemplateCallsAnalysis,
37
+ TemplateFilter,
34
38
  cleared_by,
35
39
  )
36
40
 
37
41
  __all__ = [
42
+ "FILTER_ARGUMENTS",
38
43
  "Arguments",
39
44
  "CallGraph",
40
45
  "CallGraphAnalysis",
@@ -56,6 +61,9 @@ __all__ = [
56
61
  "SummaryTable",
57
62
  "SymbolRead",
58
63
  "Target",
64
+ "TemplateCalls",
65
+ "TemplateCallsAnalysis",
66
+ "TemplateFilter",
59
67
  "UnknownTarget",
60
68
  "build_module_graph",
61
69
  "cleared_by",