coretrace-python-analyzer 0.17.0__py3-none-any.whl → 0.18.0__py3-none-any.whl

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.
@@ -1,4 +1,4 @@
1
1
  """CoreTrace's Python static analysis frontend."""
2
2
 
3
- __version__ = "0.17.0"
3
+ __version__ = "0.18.0"
4
4
 
@@ -835,7 +835,8 @@ def function_entry_point(
835
835
  project: SummaryIndex | None = None,
836
836
  ) -> EntryPoint | None:
837
837
  """The entry point ``function`` is: one of its decorators or, for a method, one of its
838
- class's bases matching an entry-point model, or a registration elsewhere (``routes``)."""
838
+ class's bases matching an entry-point model, a registration elsewhere (``routes``), or
839
+ a model naming the function, or its class, by its own project symbol."""
839
840
 
840
841
  owner = _owner(module, function)
841
842
  enclosing_function = _enclosing(module, function)
@@ -843,14 +844,22 @@ def function_entry_point(
843
844
  # ``app = Flask(__name__)`` inside ``create_app``: routes defined there resolve.
844
845
  instances = {**(instances or {}), **local_instances(enclosing_function, scopes, symbols)}
845
846
  entry = entry_point_of(function, models, scopes, symbols, owner, instances, project)
846
- if entry is None and routes:
847
+ if entry is None:
847
848
  qualified = function.name if owner is None else f"{owner.name}.{function.name}"
848
- entry = routes.get(project_symbol(module.name, qualified))
849
+ entry = _declared(project_symbol(module.name, qualified), models, routes)
849
850
  if entry is None and owner is not None:
850
- entry = routes.get(project_symbol(module.name, owner.name))
851
+ entry = _declared(project_symbol(module.name, owner.name), models, routes)
851
852
  return entry
852
853
 
853
854
 
855
+ def _declared(symbol: SymbolId, models: ModelTable, routes: Routes | None) -> EntryPoint | None:
856
+ """The entry point a project ``symbol`` is: registered as a handler, or named by a
857
+ model."""
858
+
859
+ registered = routes.get(symbol) if routes else None
860
+ return registered if registered is not None else models.entry_point(symbol)
861
+
862
+
854
863
  def _owner(module: nodes.Module, function: nodes.Function) -> nodes.Class | None:
855
864
  """The top-level class ``function`` is a method of, if any."""
856
865
 
@@ -891,6 +900,8 @@ def parameter_sources(
891
900
  for index in range(first, len(function.parameters)):
892
901
  if index - first < len(roles) and roles[index - first] is not None:
893
902
  continue
903
+ if entry.inputs is not None and index - first not in entry.inputs:
904
+ continue
894
905
  annotation = function.parameters[index].annotation
895
906
  text = (request is not None and index > first) or (
896
907
  annotation is not None and _scalar(annotation, symbols, enclosing)
@@ -110,12 +110,17 @@ class Sanitizer:
110
110
 
111
111
  @dataclass(frozen=True)
112
112
  class EntryPoint:
113
- """Functions decorated by ``symbol``, and methods of classes deriving from it,
114
- receive attacker-controlled parameters."""
113
+ """Functions decorated by ``symbol``, methods of classes deriving from it, and, when
114
+ ``symbol`` names a project function or class, that function or the class's methods
115
+ receive attacker-controlled parameters: those at ``inputs``, by position after
116
+ ``self`` for a method, or every parameter when ``inputs`` is None. A deployment
117
+ declaration an integration reads names a Lambda handler this way, whose event is
118
+ input and whose context is not."""
115
119
 
116
120
  symbol: SymbolId
117
121
  label: str
118
122
  kinds: TaintKind = TaintKind.ALL
123
+ inputs: tuple[int, ...] | None = None
119
124
 
120
125
 
121
126
  @dataclass(frozen=True)
@@ -15,7 +15,8 @@ it extends or includes, can output data unescaped:
15
15
 
16
16
  Templates are found under the project's ``templates`` directories, by their path below
17
17
  one. A template the engine cannot find — named by an expression, under a ``DIRS`` entry
18
- of another name, shipped by an installed package — is never assumed to escape.
18
+ of another name, shipped by an installed package — or cannot read is never assumed to
19
+ escape.
19
20
 
20
21
  A template applying a filter of Django's own libraries calls the function behind it
21
22
  whenever it is rendered, though no Python call names that function: ``{{ bio|striptags }}``
@@ -149,7 +150,7 @@ def escaped_templates(root: Path) -> frozenset[str]:
149
150
  local: dict[str, bool] = {}
150
151
  requires: dict[str, set[str]] = {}
151
152
  for name, paths in found.items():
152
- verdicts = [_inspect(_read(path)) for path in paths]
153
+ verdicts = [_verdict(path) for path in paths]
153
154
  local[name] = all(safe for safe, _ in verdicts)
154
155
  requires[name] = {needed for _, needs in verdicts for needed in needs}
155
156
  escaped = {name for name, safe in local.items() if safe}
@@ -171,6 +172,14 @@ def _read(path: Path) -> str:
171
172
  return _text(path) or ""
172
173
 
173
174
 
175
+ def _verdict(path: Path) -> tuple[bool, set[str]]:
176
+ """Whether one template file escapes all it prints, and what it needs: a file the
177
+ engine cannot read is not established to escape, like a template it cannot find."""
178
+
179
+ text = _text(path)
180
+ return (False, set()) if text is None else _inspect(text)
181
+
182
+
174
183
  def _text(path: Path) -> str | None:
175
184
  """The text of ``path``, or None when it cannot be read."""
176
185
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: coretrace-python-analyzer
3
- Version: 0.17.0
3
+ Version: 0.18.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
@@ -1,4 +1,4 @@
1
- coretrace_python/__init__.py,sha256=HRmDGjpSkbWNTv_zUrVcohlicTxeBUblXGvOBz0lia4,76
1
+ coretrace_python/__init__.py,sha256=UXlC7yIk3dOxWBAjttYzugsg0Cacccz_IG6V-LsaqSU,76
2
2
  coretrace_python/__main__.py,sha256=V8DnYtRboISK2VCKm7DGHLREKvqLbqApyWlKBOs26wU,65
3
3
  coretrace_python/cache.py,sha256=-pZv-ELm4jMCTXQWSZIobHaT9UHIjFu7IlMkOM0i4LI,13607
4
4
  coretrace_python/cli.py,sha256=G5jhb6g6RgSRSjjS7DBgziIjUM1vTFwalJGvFHVKxrg,11225
@@ -144,14 +144,14 @@ coretrace_python/source/__init__.py,sha256=0Y8fvtbkETnNCJR9Zq7RS5TSgF9c22pz3SSk1
144
144
  coretrace_python/source/manager.py,sha256=JRmMOcWfS1nocbVrdcvfQTqEfIkmnb5JP857TpGywN4,2736
145
145
  coretrace_python/source/model.py,sha256=FZnN5mlir3tzbIpWoxnn6YtRi9UcJ_y0sZM60tKr8U4,1727
146
146
  coretrace_python/taint/__init__.py,sha256=nKpD33_4IRneAkd3Dt-j7Q-cHl47rDA_eLZFDHZVH28,1827
147
- coretrace_python/taint/engine.py,sha256=B3_o8feN0-a6PAfZCyERIxMiZnF50nTMi3rP5uesHOM,48923
148
- coretrace_python/taint/models.py,sha256=EMzAMY3woBjgDlGyFi9vsVmuE5r2OjnwEvHHoe9IuWE,20026
147
+ coretrace_python/taint/engine.py,sha256=BHNdoyUryK9lDOZ-lq235GdTC9SDbeUHquoDH2DDCM8,49457
148
+ coretrace_python/taint/models.py,sha256=pCvE-6dYKYSLK7pylxhLWpeUcMfMyXlh_1VUJbzieo8,20405
149
149
  coretrace_python/taint/routes.py,sha256=UAJKXcw_sM9shf58FfDroxVO9bNSm4qrQdZknwUB0lo,6110
150
- coretrace_python/taint/templates.py,sha256=cxa2PC-Md0pAPu0NxrIUJ5XMs26zck7O-dDH30TTB2I,31023
150
+ coretrace_python/taint/templates.py,sha256=74y06rKs2F0cCOqRw_jbKwlZ8M4nUgsatOFX5ZWkRNQ,31344
151
151
  coretrace_python/taint/urls.py,sha256=kb0-uOT12ww7R3Jzs_lPKg9lFs74JI-bpa9pXX105xM,3166
152
- coretrace_python_analyzer-0.17.0.dist-info/METADATA,sha256=LCZjkte2jNcPz06rsm7jMwboXtkbiwbyrIQh9Ij4nR8,3217
153
- coretrace_python_analyzer-0.17.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
154
- coretrace_python_analyzer-0.17.0.dist-info/entry_points.txt,sha256=wdozemiraOkbt65g_Y_zgspuZpoLxJdaCVMJt1Ft3c0,72
155
- coretrace_python_analyzer-0.17.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
156
- coretrace_python_analyzer-0.17.0.dist-info/licenses/NOTICE,sha256=s3VHj5ngV0ozjW_kZJpg_35ne6JwoBK0ysOjbqVtA0w,113
157
- coretrace_python_analyzer-0.17.0.dist-info/RECORD,,
152
+ coretrace_python_analyzer-0.18.0.dist-info/METADATA,sha256=UknDXxCfvCkshCAt4gMWAGWWGp_SzsiN9laP98Gq9qo,3217
153
+ coretrace_python_analyzer-0.18.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
154
+ coretrace_python_analyzer-0.18.0.dist-info/entry_points.txt,sha256=wdozemiraOkbt65g_Y_zgspuZpoLxJdaCVMJt1Ft3c0,72
155
+ coretrace_python_analyzer-0.18.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
156
+ coretrace_python_analyzer-0.18.0.dist-info/licenses/NOTICE,sha256=s3VHj5ngV0ozjW_kZJpg_35ne6JwoBK0ysOjbqVtA0w,113
157
+ coretrace_python_analyzer-0.18.0.dist-info/RECORD,,