coretrace-python-analyzer 0.14.0__py3-none-any.whl → 0.15.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.14.0"
3
+ __version__ = "0.15.0"
4
4
 
@@ -1,12 +1,26 @@
1
- """Open redirect: attacker-controlled input reaching a open redirect sink."""
1
+ """Open redirect: attacker-controlled input reaching a open redirect sink.
2
+
3
+ The rule draws its verdict from what the target's constant text proves (``taint.urls``),
4
+ as a browser resolves it. A reference on the current site (``/profile/``, ``?page=``,
5
+ ``profile/``) keeps the browser on the site, where any further redirect is the project's
6
+ own code, analysed on its own: refuted. A fixed absolute host sends the browser there,
7
+ but the input chooses the path, where that host may redirect again: a hotspot. Anything
8
+ unproven, ``"/" + next`` included, stays a vulnerability.
9
+ """
2
10
 
3
11
  from __future__ import annotations
4
12
 
5
13
  from typing import ClassVar
6
14
 
15
+ from coretrace_python.abstract.strings import ModuleStringsAnalysis
16
+ from coretrace_python.analysis import AnyAnalysis
7
17
  from coretrace_python.findings import Severity
8
- from coretrace_python.plugins import TaintDetector
9
- from coretrace_python.taint import TaintKind
18
+ from coretrace_python.findings.refutation import Status, Verdict
19
+ from coretrace_python.hir import nodes
20
+ from coretrace_python.ir.ssa import SSAAnalysis
21
+ from coretrace_python.plugins import PluginContext, TaintDetector
22
+ from coretrace_python.taint import TaintFlow, TaintKind
23
+ from coretrace_python.taint.urls import flow_url
10
24
 
11
25
 
12
26
  class OpenRedirectPlugin(TaintDetector):
@@ -15,3 +29,19 @@ class OpenRedirectPlugin(TaintDetector):
15
29
  kind: ClassVar[TaintKind] = TaintKind.REDIRECT
16
30
  severity: ClassVar[Severity] = Severity.MEDIUM
17
31
  title: ClassVar[str] = "Open redirect"
32
+ requires: ClassVar[frozenset[AnyAnalysis]] = TaintDetector.requires | {SSAAnalysis, ModuleStringsAnalysis}
33
+
34
+ def judge(self, ctx: PluginContext, function: nodes.Function, flow: TaintFlow, verdict: Verdict) -> Verdict:
35
+ ssa = ctx.get(SSAAnalysis, function)
36
+ defs = {i.result: i for block in ssa.blocks for i in block.instructions if i.result is not None}
37
+ target = flow_url(flow, defs, ctx.get(ModuleStringsAnalysis))
38
+ if target.relative:
39
+ return Verdict(flow, Status.REFUTED, f"the browser stays on the site: the target starts with {target.text!r}")
40
+ if target.origin is not None and verdict.status is Status.VULNERABILITY:
41
+ return Verdict(
42
+ flow,
43
+ Status.HOTSPOT,
44
+ f"the browser goes to the host fixed by {target.origin!r}, but the input chooses the path, "
45
+ "where that host may redirect again",
46
+ )
47
+ return verdict
@@ -1,7 +1,7 @@
1
1
  name = "open-redirect"
2
2
  version = "1.0.0"
3
3
  plugin_api = ">=1,<2"
4
- requires = ["taint.flows", "findings.refutation"]
4
+ requires = ["taint.flows", "findings.refutation", "ir.ssa", "abstract.module_strings"]
5
5
  provides = ["vulnerability.open-redirect"]
6
6
 
7
7
  [entrypoint]
@@ -1,21 +1,18 @@
1
1
  """Server-side request forgery: attacker-controlled input reaching a SSRF sink.
2
2
 
3
- How the URL is built, with ``+`` and f-strings, can prove part of its destination. Constant
4
- text fixing ``scheme://host`` and ending the authority with ``/``, ``?`` or ``#`` before
5
- any input keeps the input from choosing the host; the input still chooses the path, which
6
- may reach a sensitive resource of that host, and a redirect may lead elsewhere, so the
7
- flow is a hotspot. With the path fixed too, the input reaching the query or fragment
8
- only, and redirects disabled in the call, the destination is fixed and the flow is
9
- refuted. Anything unproven, a base of unknown value or a URL built in a helper function,
10
- stays a vulnerability.
3
+ The rule draws its verdict from what the URL's constant text proves (``taint.urls``).
4
+ A fixed host keeps the input from choosing it, but the input still chooses the path,
5
+ which may reach a sensitive resource of that host, and a redirect may lead elsewhere: a
6
+ hotspot. With the path fixed too, the input reaching the query or fragment only, and
7
+ redirects disabled in the call, the destination is fixed: refuted. Anything unproven,
8
+ a base of unknown value or a URL built in a helper function, stays a vulnerability.
11
9
  """
12
10
 
13
11
  from __future__ import annotations
14
12
 
15
- import re
16
13
  from typing import ClassVar
17
14
 
18
- from coretrace_python.abstract.strings import ModuleStringsAnalysis, leading_text
15
+ from coretrace_python.abstract.strings import ModuleStringsAnalysis
19
16
  from coretrace_python.analysis import AnyAnalysis
20
17
  from coretrace_python.findings import Severity
21
18
  from coretrace_python.findings.refutation import Status, Verdict
@@ -23,15 +20,7 @@ from coretrace_python.hir import nodes
23
20
  from coretrace_python.ir.ssa import SSAAnalysis
24
21
  from coretrace_python.plugins import PluginContext, TaintDetector
25
22
  from coretrace_python.taint import TaintFlow, TaintKind
26
-
27
- # ``scheme://`` and an authority ended by ``/``, ``?`` or ``#``. A backslash, which some
28
- # URL parsers take for a slash, does not end it here.
29
- _FIXED_HOST = re.compile(r"[A-Za-z][A-Za-z0-9+.-]*://[^/?#\\]+[/?#]")
30
- # The same with the path fixed too: what follows is query or fragment.
31
- _FIXED_PATH = re.compile(r"[A-Za-z][A-Za-z0-9+.-]*://[^/?#\\]+(?:/[^?#]*)?[?#]")
32
- # A client honours the one of these keywords it knows and rejects the other with a
33
- # ``TypeError``: either way, the call follows no redirect.
34
- _NO_REDIRECTS = ("allow_redirects", "follow_redirects")
23
+ from coretrace_python.taint.urls import flow_url, redirects_disabled
35
24
 
36
25
 
37
26
  class SsrfPlugin(TaintDetector):
@@ -43,22 +32,18 @@ class SsrfPlugin(TaintDetector):
43
32
  requires: ClassVar[frozenset[AnyAnalysis]] = TaintDetector.requires | {SSAAnalysis, ModuleStringsAnalysis}
44
33
 
45
34
  def judge(self, ctx: PluginContext, function: nodes.Function, flow: TaintFlow, verdict: Verdict) -> Verdict:
46
- if flow.through is not None:
47
- return verdict # the URL is built in the callee
48
35
  ssa = ctx.get(SSAAnalysis, function)
49
36
  defs = {i.result: i for block in ssa.blocks for i in block.instructions if i.result is not None}
50
- text, _ = leading_text(flow.argument, defs, ctx.get(ModuleStringsAnalysis))
51
- host = _FIXED_HOST.match(text)
52
- if host is None:
37
+ url = flow_url(flow, defs, ctx.get(ModuleStringsAnalysis))
38
+ if url.origin is None:
53
39
  return verdict
54
- arguments = flow.sink_arguments
55
- no_redirects = arguments is not None and any(arguments.given(name) == (True, "False") for name in _NO_REDIRECTS)
56
- if _FIXED_PATH.match(text) is not None:
40
+ no_redirects = redirects_disabled(flow.sink_arguments)
41
+ if url.path_fixed:
57
42
  if no_redirects:
58
- return Verdict(flow, Status.REFUTED, f"the destination is fixed by {text!r} and redirects are disabled")
43
+ return Verdict(flow, Status.REFUTED, f"the destination is fixed by {url.text!r} and redirects are disabled")
59
44
  left = "a redirect may lead elsewhere"
60
45
  else:
61
46
  left = "the input chooses the path" + ("" if no_redirects else ", and a redirect may lead elsewhere")
62
47
  if verdict.status is not Status.VULNERABILITY:
63
48
  return verdict
64
- return Verdict(flow, Status.HOTSPOT, f"the host is fixed by {host.group(0)!r}, but {left}")
49
+ return Verdict(flow, Status.HOTSPOT, f"the host is fixed by {url.origin!r}, but {left}")
@@ -251,7 +251,7 @@ def _condition(entry: Mapping[str, Any]) -> Condition:
251
251
  default = entry.get("default", False)
252
252
  if not isinstance(default, bool):
253
253
  raise TypeError(f"condition default must be true or false, got {default!r}")
254
- return Condition(
254
+ condition = Condition(
255
255
  str(entry["kind"]),
256
256
  str(entry["text"]),
257
257
  None if entry.get("argument") is None else str(entry["argument"]),
@@ -259,3 +259,8 @@ def _condition(entry: Mapping[str, Any]) -> Condition:
259
259
  position,
260
260
  default,
261
261
  )
262
+ if condition.kind == "host" and (
263
+ (condition.argument is None and condition.position is None) or condition.values or condition.default
264
+ ):
265
+ raise ValueError("a host condition names the URL argument, by keyword or position, and nothing else")
266
+ return condition
@@ -10,7 +10,7 @@ are correlated here into one high-confidence ``exploitable-vulnerability`` findi
10
10
  from __future__ import annotations
11
11
 
12
12
  from collections.abc import Iterable, Mapping
13
- from dataclasses import dataclass
13
+ from dataclasses import dataclass, replace
14
14
 
15
15
  from coretrace_python.dependency.graph import (
16
16
  DIRECT,
@@ -24,6 +24,7 @@ from coretrace_python.findings.refutation import Status, Verdict, Verdicts
24
24
  from coretrace_python.interprocedural import Arguments, CallSite, ExternalSymbol
25
25
  from coretrace_python.semantic.symbols import SymbolId
26
26
  from coretrace_python.taint import Sink, TaintFlow, TaintKind
27
+ from coretrace_python.taint.urls import UrlProof, redirects_disabled
27
28
 
28
29
  Affected = Mapping[SymbolId, tuple[Advisory, ...]]
29
30
 
@@ -61,14 +62,33 @@ class ConditionCheck:
61
62
  passed: str | None = None
62
63
 
63
64
 
64
- def check_conditions(entry: AdvisoryEntryPoint | None, arguments: Arguments | None) -> ConditionCheck:
65
- """Decide ``entry``'s conditions against what the call's ``arguments`` denote."""
65
+ def check_conditions(
66
+ entry: AdvisoryEntryPoint | None,
67
+ arguments: Arguments | None,
68
+ url: UrlProof | None = None,
69
+ passed_as: frozenset[tuple[int | None, str | None]] = frozenset(),
70
+ ) -> ConditionCheck:
71
+ """Decide ``entry``'s conditions against what the call's ``arguments`` denote and, for
72
+ a ``host`` condition, what ``url`` proves of the value the attacker's input is passed
73
+ in (``passed_as``). A host the URL's constant text fixes rules the call out when the
74
+ call disables redirects; otherwise a redirect may still lead to a host the attacker
75
+ controls, and the condition stays pending with that uncertainty."""
66
76
 
67
77
  if entry is None:
68
78
  return ConditionCheck()
69
79
  met: list[Condition] = []
70
80
  pending: list[Condition] = []
71
81
  for condition in entry.conditions:
82
+ if condition.kind == "host":
83
+ origin = url.origin if url is not None and _passed_in(condition, passed_as) else None
84
+ if origin is None:
85
+ pending.append(condition)
86
+ elif redirects_disabled(arguments):
87
+ return ConditionCheck(tuple(met), tuple(pending), condition, repr(origin))
88
+ else:
89
+ text = f"the host is fixed by {origin!r}, but a redirect may lead to a host the attacker controls"
90
+ pending.append(replace(condition, text=text))
91
+ continue
72
92
  given = arguments.given(condition.argument, condition.position) if condition.checkable and arguments is not None else None
73
93
  if given is None:
74
94
  pending.append(condition)
@@ -84,6 +104,16 @@ def check_conditions(entry: AdvisoryEntryPoint | None, arguments: Arguments | No
84
104
  return ConditionCheck(tuple(met), tuple(pending))
85
105
 
86
106
 
107
+ def _passed_in(condition: Condition, passed_as: frozenset[tuple[int | None, str | None]]) -> bool:
108
+ """Whether a value passed as ``passed_as`` is the argument ``condition`` names."""
109
+
110
+ return any(
111
+ (keyword is not None and keyword == condition.argument)
112
+ or (keyword is None and position is not None and position == condition.position)
113
+ for position, keyword in passed_as
114
+ )
115
+
116
+
87
117
  def ruled_out(module: str, site: CallSite, check: ConditionCheck) -> str:
88
118
  """Which call a contradicted condition rules out, and why: ``app:12
89
119
  python.yaml.load(Loader=python.yaml.SafeLoader)``."""
@@ -120,9 +150,10 @@ def correlate(
120
150
  flows: Iterable[TaintFlow],
121
151
  verdicts: Verdicts | None,
122
152
  affected: Affected,
153
+ urls: Mapping[TaintFlow, UrlProof] | None = None,
123
154
  ) -> tuple[Finding, ...]:
124
155
  """Exploitable-vulnerability findings for the non-refuted ADVISORY flows of a function,
125
- one per advisory the sink is affected by."""
156
+ one per advisory the sink is affected by; ``urls`` holds what each flow's URL proves."""
126
157
 
127
158
  findings: list[Finding] = []
128
159
  for flow in flows:
@@ -136,7 +167,7 @@ def correlate(
136
167
  entry = advisory.entry_point(flow.sink.symbol)
137
168
  if entry is not None and not any(entry.exploitable_through(p, k) for p, k in flow.passed_as):
138
169
  continue
139
- check = check_conditions(entry, flow.sink_arguments)
170
+ check = check_conditions(entry, flow.sink_arguments, (urls or {}).get(flow), flow.passed_as)
140
171
  if check.contradicted is None:
141
172
  findings.append(_exploitable(function, flow, advisory, verdict, hotspot, check))
142
173
  return tuple(findings)
@@ -151,8 +151,10 @@ class Condition:
151
151
  ``argument`` condition names the argument by keyword, and by ``position`` when it may
152
152
  be passed positionally, and lists the ``values`` that satisfy it — symbols
153
153
  (``python.yaml.FullLoader``) or constants as Python writes them (``True``);
154
- ``default`` says an absent argument means a vulnerable value. A ``semantic``
155
- condition cannot be checked and is reported as pending review."""
154
+ ``default`` says an absent argument means a vulnerable value. A ``host`` condition
155
+ says the attacker must choose the host of the URL passed as ``argument`` (or at
156
+ ``position``); the engine decides it from what the URL's constant text proves. A
157
+ ``semantic`` condition cannot be checked and is reported as pending review."""
156
158
 
157
159
  kind: str
158
160
  text: str
@@ -126,6 +126,7 @@ from coretrace_python.taint import (
126
126
  escaped_templates,
127
127
  registered_routes,
128
128
  )
129
+ from coretrace_python.taint.urls import flow_url
129
130
 
130
131
  TOOL_NAME = "coretrace-python-analyzer"
131
132
 
@@ -770,14 +771,14 @@ def _analyse_module(
770
771
  graph = manager.get(CallGraphAnalysis)
771
772
  correlated: list[Finding] = []
772
773
  if affected:
774
+ strings = manager.get(ModuleStringsAnalysis)
773
775
  for function in supported:
776
+ flows = manager.get(TaintAnalysis, function).flows
777
+ ssa = manager.get(SSAAnalysis, function)
778
+ defs = {i.result: i for block in ssa.blocks for i in block.instructions if i.result is not None}
779
+ urls = {flow: flow_url(flow, defs, strings) for flow in flows if flow.kinds & TaintKind.ADVISORY}
774
780
  correlated.extend(
775
- correlate(
776
- graph.name_of(function),
777
- manager.get(TaintAnalysis, function).flows,
778
- manager.get(RefutationAnalysis, function),
779
- affected,
780
- )
781
+ correlate(graph.name_of(function), flows, manager.get(RefutationAnalysis, function), affected, urls)
781
782
  )
782
783
  return CachedModule(
783
784
  manager.get(EntryPointAnalysis),
@@ -0,0 +1,70 @@
1
+ """What the constant text a URL starts with proves about its destination, and whether a
2
+ call follows redirects: one proof that the rules reading URLs share, each drawing its
3
+ own verdict from it. The text is what ``+`` and f-strings build before any other value
4
+ (``abstract.strings``); the proof says nothing about the rest of the URL."""
5
+
6
+ from __future__ import annotations
7
+
8
+ import re
9
+ from collections.abc import Mapping
10
+ from dataclasses import dataclass
11
+
12
+ from coretrace_python.abstract.strings import leading_text
13
+ from coretrace_python.interprocedural import Arguments
14
+ from coretrace_python.ir.model import Instruction, Value
15
+ from coretrace_python.taint.engine import TaintFlow
16
+
17
+ # ``scheme://`` and an authority ended by ``/``, ``?`` or ``#``. A backslash, which some
18
+ # URL parsers take for a slash, does not end it here.
19
+ _ORIGIN = re.compile(r"[A-Za-z][A-Za-z0-9+.-]*://[^/?#\\]+[/?#]")
20
+ # The same with the path fixed too: what follows is query or fragment.
21
+ _PATH = re.compile(r"[A-Za-z][A-Za-z0-9+.-]*://[^/?#\\]+(?:/[^?#]*)?[?#]")
22
+ # A reference a browser resolves on the current site: ``/`` then a character that is not
23
+ # a slash, a backslash, a space or a control character (``//`` and ``/\`` name another
24
+ # host, and a browser drops tabs and newlines), a query or a fragment, or a relative path
25
+ # whose first segment ends in the text without a ``:`` that would make it a scheme.
26
+ _RELATIVE = re.compile(r"/[^/\\\x00-\x20\x7f]|[?#]|[^/\\?#:\x00-\x20\x7f][^/\\?#:]*[/?#]")
27
+ # A client honours the one of these keywords it knows and rejects the other with a
28
+ # ``TypeError``: either way, the call follows no redirect.
29
+ _NO_REDIRECTS = ("allow_redirects", "follow_redirects")
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ class UrlProof:
34
+ """What the constant ``text`` a URL starts with proves: the ``origin`` it fixes
35
+ (``scheme://authority`` and the character ending it), whether it fixes the path
36
+ too (``path_fixed``), and whether it starts a reference a browser resolves on the
37
+ current site (``relative``)."""
38
+
39
+ text: str
40
+ origin: str | None = None
41
+ path_fixed: bool = False
42
+ relative: bool = False
43
+
44
+
45
+ def url_proof(text: str) -> UrlProof:
46
+ origin = _ORIGIN.match(text)
47
+ return UrlProof(
48
+ text,
49
+ origin.group(0) if origin is not None else None,
50
+ _PATH.match(text) is not None,
51
+ _RELATIVE.match(text) is not None,
52
+ )
53
+
54
+
55
+ def flow_url(flow: TaintFlow, defs: Mapping[Value, Instruction], strings: Mapping[str, str]) -> UrlProof:
56
+ """The proof for the value ``flow`` passes to its sink, ``defs`` defining the values
57
+ of the function making the call. A flow reaching its sink in a callee proves nothing:
58
+ the value is built there."""
59
+
60
+ if flow.through is not None:
61
+ return UrlProof("")
62
+ text, _ = leading_text(flow.argument, defs, strings)
63
+ return url_proof(text)
64
+
65
+
66
+ def redirects_disabled(arguments: Arguments | None) -> bool:
67
+ """Whether the call disables redirects explicitly (``allow_redirects=False`` or
68
+ ``follow_redirects=False``); absent, a variable or unpacked options do not."""
69
+
70
+ return arguments is not None and any(arguments.given(name) == (True, "False") for name in _NO_REDIRECTS)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: coretrace-python-analyzer
3
- Version: 0.14.0
3
+ Version: 0.15.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,8 +1,8 @@
1
- coretrace_python/__init__.py,sha256=kY0Q5RzkkixmFjJXYSXgYgHOkh327TcAyqMH9u0a_M0,76
1
+ coretrace_python/__init__.py,sha256=LF0lqv_rMHWvWLyAat8Ysu4q_nrKXQ35Q-QHFk2BarI,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
5
- coretrace_python/engine.py,sha256=yICn93LZyoWOdDoZEIqoWATuhPQhLPW8ANLxJPskDwM,32371
5
+ coretrace_python/engine.py,sha256=Px9_zXYfBUbSEitgWcseEhza-h4j6hL_qFE8kuogrMY,32678
6
6
  coretrace_python/abstract/__init__.py,sha256=n5FNkV8Z4LmwG0r06KWdLj4N2CPSgAKwY3896tdmRgM,999
7
7
  coretrace_python/abstract/constants.py,sha256=z4-e7IzysxzGi58wFFff1MlEoV8l7AZsB9EL-q6b7vY,9071
8
8
  coretrace_python/abstract/heap.py,sha256=OaESXFGC0qzyhAr76xrCu4skeDVzZM4wlenQqfMTkdk,9642
@@ -56,8 +56,8 @@ coretrace_python/bundled/security/insecure_deserialization/insecure_deserializat
56
56
  coretrace_python/bundled/security/insecure_deserialization/plugin.toml,sha256=5OTVO9jZN-HBid8v__jYkxU-RnKX974Qqu7JQMFdj54,268
57
57
  coretrace_python/bundled/security/nosql_injection/nosql_injection.py,sha256=0MCTZ3DjOf5DQrLgnPPgpa80CYUd5teQ_iau3s_82O0,789
58
58
  coretrace_python/bundled/security/nosql_injection/plugin.toml,sha256=FP2qTPtH7ZCiu6vwfgadWlXfVnlKOigXJ43cv9PlorA,232
59
- coretrace_python/bundled/security/open_redirect/open_redirect.py,sha256=nUjVIgYhVh_2xBs8_1LOfcLDgQ3g3z1E7APqg2sBdpo,562
60
- coretrace_python/bundled/security/open_redirect/plugin.toml,sha256=8t4KLNG1DIpjjen6TuKxMjz2jv6GDcwVJDm_hJUalCg,224
59
+ coretrace_python/bundled/security/open_redirect/open_redirect.py,sha256=t2LiqdgoD8A_ZG0iG5kZ88ZnSEcnngpHNbZUzCM92Ek,2365
60
+ coretrace_python/bundled/security/open_redirect/plugin.toml,sha256=2SMFY7GeczfUqeX4fp600Qj24k8fUPCg4zD__JBabkw,261
61
61
  coretrace_python/bundled/security/path_traversal/path_traversal.py,sha256=MiTDZBNU6i3WWua1qaxg1swqDy3wlWwBwG6G4ClyDgw,552
62
62
  coretrace_python/bundled/security/path_traversal/plugin.toml,sha256=f0ADZimUvQatOffltF5Ihu1mkzf5rNrsaIpKBg2v39c,228
63
63
  coretrace_python/bundled/security/plaintext_credentials/plaintext_credentials.py,sha256=QaE2CXAdl0bi4dE5d2d8KnLJrsAcxUDjR76ghfsnXXo,900
@@ -65,7 +65,7 @@ coretrace_python/bundled/security/plaintext_credentials/plugin.toml,sha256=W56wU
65
65
  coretrace_python/bundled/security/sql_injection/plugin.toml,sha256=U35h6YdbbM93Ar_msWrwY98_bb6rN-qaa1e7XOtPeSo,224
66
66
  coretrace_python/bundled/security/sql_injection/sql_injection.py,sha256=W-ppZngb9mLwRjJPGkh__8kaDqYdSrVbciv0mPdYFNE,545
67
67
  coretrace_python/bundled/security/ssrf/plugin.toml,sha256=Uh0hvcc2bkOEKBQUw6tyuvpPQRq8_JzhWc9nVQAdm1Y,226
68
- coretrace_python/bundled/security/ssrf/ssrf.py,sha256=Zk3eCu4Gp9vnR4DarG_RAm9U7hNv2ESAn_oVUVUMHF8,3441
68
+ coretrace_python/bundled/security/ssrf/ssrf.py,sha256=OBe7GcYvdXLpFHsdt7wPA9-UPN6i1tBiDx6a79SL6yg,2532
69
69
  coretrace_python/bundled/security/xss/plugin.toml,sha256=o6aZWoDNCG6CJ11JDa5lVR0v6NHh-Jg5QpNRxoGSJaw,185
70
70
  coretrace_python/bundled/security/xss/xss.py,sha256=hzhoblPMivtwoWZ4v7YyAb15GGisX_imGWgxFzCDeqA,532
71
71
  coretrace_python/bundled/syntax/dangerous_eval/dangerous_eval.py,sha256=_ktrigLDf-XTKjWtYX-_wZ9-Gb3G4bCzRhpU0Xj-c1g,723
@@ -94,9 +94,9 @@ coretrace_python/dataflow/__init__.py,sha256=N5uY8VTNjEk6-ARCgDkxr6uGqQIz2NbF-U9
94
94
  coretrace_python/dataflow/lattice.py,sha256=HgYGVcKVUlexvEc0yT47aQCudLxU_SWLpHhr17igkiE,1929
95
95
  coretrace_python/dataflow/solver.py,sha256=iDsW0wujhM2DXplu2JMKC46BRsroXlNETHPEoikPeG4,3475
96
96
  coretrace_python/dependency/__init__.py,sha256=BxkxnNwIEpAYtwbshCQovG-YXJ80QbwyzkmyJdbgsVg,1184
97
- coretrace_python/dependency/advisories.py,sha256=zti7MrojcfxfYWJuGpyLXXJU3pffpT4SJnQUa_g34Lw,10274
98
- coretrace_python/dependency/correlation.py,sha256=GLtrMn5yYr4NcKYNYZTqIFpwoXOrgsqI9t6lggXxFbg,7388
99
- coretrace_python/dependency/graph.py,sha256=HtvKeWWG9cy9TzJQ7lYMGPfHjPBxoSVgwzoj71SegaE,18445
97
+ coretrace_python/dependency/advisories.py,sha256=RPtqT5M_kmRVnjs53PRnDJKUsUysdJmk8KuE3sigUOk,10564
98
+ coretrace_python/dependency/correlation.py,sha256=nr5FZ3yOT4HsKzvEAFlzzaPJxBc9_X-IuyOWtRjS67Q,9033
99
+ coretrace_python/dependency/graph.py,sha256=U9KzdVCcM7P1W6qSSSMkzMIIVEh3qlzBpBi2FAFy0y0,18633
100
100
  coretrace_python/dependency/policy.py,sha256=bsxZXL9xC0jnAzkzDh6ncnW8oKLG2H13jYmXF_q99Ng,2454
101
101
  coretrace_python/dependency/sbom.py,sha256=rzJ-t0Mwoghej8nk0N63Dpjr_wYXm6JzuOPXjD8Kqs4,3234
102
102
  coretrace_python/dependency/vex.py,sha256=YddBuXsv7UgEnHdM9Jfjpo_A700IuIqRMjQz7AHSLX4,7437
@@ -148,9 +148,10 @@ coretrace_python/taint/engine.py,sha256=rEAbwjR5v294PqBzBlu6f9WiMvVmwV83FqdsWbT4
148
148
  coretrace_python/taint/models.py,sha256=8AwPKKdmwAHmE7CxwUbtWn5w7JVkEJ06_Is7xQWTx38,17066
149
149
  coretrace_python/taint/routes.py,sha256=UAJKXcw_sM9shf58FfDroxVO9bNSm4qrQdZknwUB0lo,6110
150
150
  coretrace_python/taint/templates.py,sha256=8Ojb43VXuWxOVifeXRpi3_2mjZfnvIC7GQ-AW80GUYk,11148
151
- coretrace_python_analyzer-0.14.0.dist-info/METADATA,sha256=I6joOK1gGJSOzcn3pJ9PYii-2Yb7Ak-PSK9SmQWz4vQ,3217
152
- coretrace_python_analyzer-0.14.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
153
- coretrace_python_analyzer-0.14.0.dist-info/entry_points.txt,sha256=wdozemiraOkbt65g_Y_zgspuZpoLxJdaCVMJt1Ft3c0,72
154
- coretrace_python_analyzer-0.14.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
155
- coretrace_python_analyzer-0.14.0.dist-info/licenses/NOTICE,sha256=s3VHj5ngV0ozjW_kZJpg_35ne6JwoBK0ysOjbqVtA0w,113
156
- coretrace_python_analyzer-0.14.0.dist-info/RECORD,,
151
+ coretrace_python/taint/urls.py,sha256=kb0-uOT12ww7R3Jzs_lPKg9lFs74JI-bpa9pXX105xM,3166
152
+ coretrace_python_analyzer-0.15.0.dist-info/METADATA,sha256=MrHb31ufFhrM7ievaxqYvuwvTlqnif8HAvvQkVsfO30,3217
153
+ coretrace_python_analyzer-0.15.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
154
+ coretrace_python_analyzer-0.15.0.dist-info/entry_points.txt,sha256=wdozemiraOkbt65g_Y_zgspuZpoLxJdaCVMJt1Ft3c0,72
155
+ coretrace_python_analyzer-0.15.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
156
+ coretrace_python_analyzer-0.15.0.dist-info/licenses/NOTICE,sha256=s3VHj5ngV0ozjW_kZJpg_35ne6JwoBK0ysOjbqVtA0w,113
157
+ coretrace_python_analyzer-0.15.0.dist-info/RECORD,,