coretrace-python-analyzer 0.13.0__py3-none-any.whl → 0.14.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.
- coretrace_python/__init__.py +1 -1
- coretrace_python/abstract/strings.py +98 -0
- coretrace_python/bundled/security/ssrf/plugin.toml +1 -1
- coretrace_python/bundled/security/ssrf/ssrf.py +50 -3
- coretrace_python/engine.py +2 -0
- coretrace_python/plugins/detectors.py +13 -2
- {coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/METADATA +1 -1
- {coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/RECORD +12 -11
- {coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/WHEEL +0 -0
- {coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/entry_points.txt +0 -0
- {coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/licenses/LICENSE +0 -0
- {coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/licenses/NOTICE +0 -0
coretrace_python/__init__.py
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""The constant text a string starts with (architecture §18): what ``+`` and f-strings
|
|
2
|
+
build from string literals and from module-level names bound once to one. Anything
|
|
3
|
+
else, a parameter, a call result, an import, ``%`` or ``format``, is text of unknown
|
|
4
|
+
value."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from collections.abc import Mapping
|
|
9
|
+
from types import MappingProxyType
|
|
10
|
+
from typing import ClassVar
|
|
11
|
+
|
|
12
|
+
from coretrace_python.analysis import Analysis, AnalysisContext, AnyAnalysis
|
|
13
|
+
from coretrace_python.cfg import CFGError
|
|
14
|
+
from coretrace_python.hir import nodes
|
|
15
|
+
from coretrace_python.ir.lowering import (
|
|
16
|
+
MODULE_BODY,
|
|
17
|
+
LoweringError,
|
|
18
|
+
PyIRAnalysis,
|
|
19
|
+
analyzable_functions,
|
|
20
|
+
)
|
|
21
|
+
from coretrace_python.ir.model import (
|
|
22
|
+
BinaryOp,
|
|
23
|
+
BuildString,
|
|
24
|
+
Constant,
|
|
25
|
+
ForNext,
|
|
26
|
+
Global,
|
|
27
|
+
Instruction,
|
|
28
|
+
SetGlobal,
|
|
29
|
+
StoreLocal,
|
|
30
|
+
Value,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def leading_text(value: Value, defs: Mapping[Value, Instruction], strings: Mapping[str, str]) -> tuple[str, bool]:
|
|
35
|
+
"""The constant text ``value`` starts with, and whether that text is all of it, given
|
|
36
|
+
the definitions of the function's values and the module's ``strings``."""
|
|
37
|
+
|
|
38
|
+
made = defs.get(value)
|
|
39
|
+
if isinstance(made, Constant):
|
|
40
|
+
return (made.value, True) if isinstance(made.value, str) else ("", False)
|
|
41
|
+
if isinstance(made, Global):
|
|
42
|
+
known = strings.get(made.name)
|
|
43
|
+
return ("", False) if known is None else (known, True)
|
|
44
|
+
if isinstance(made, BinaryOp) and made.operator == "add":
|
|
45
|
+
left, whole = leading_text(made.left, defs, strings)
|
|
46
|
+
if not whole:
|
|
47
|
+
return left, False
|
|
48
|
+
right, whole = leading_text(made.right, defs, strings)
|
|
49
|
+
return left + right, whole
|
|
50
|
+
if isinstance(made, BuildString):
|
|
51
|
+
text = ""
|
|
52
|
+
for part in made.parts:
|
|
53
|
+
piece, whole = leading_text(part, defs, strings)
|
|
54
|
+
text += piece
|
|
55
|
+
if not whole:
|
|
56
|
+
return text, False
|
|
57
|
+
return text, True
|
|
58
|
+
return "", False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ModuleStringsAnalysis(Analysis[Mapping[str, str]]):
|
|
62
|
+
"""The module-level names bound once, to a string literal, and never rebound: by no
|
|
63
|
+
other statement of the module body, no function assigning them as ``global``, no
|
|
64
|
+
definition of that name. A module that does not lower entirely has none."""
|
|
65
|
+
|
|
66
|
+
name: ClassVar[str] = "abstract.module_strings"
|
|
67
|
+
requires: ClassVar[frozenset[AnyAnalysis]] = frozenset({PyIRAnalysis})
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def compute(cls, ctx: AnalysisContext) -> Mapping[str, str]:
|
|
71
|
+
try:
|
|
72
|
+
functions = [ctx.get(PyIRAnalysis, function) for function in analyzable_functions(ctx.module)]
|
|
73
|
+
except (LoweringError, CFGError):
|
|
74
|
+
return MappingProxyType({})
|
|
75
|
+
body = next((function for function in functions if function.name == MODULE_BODY), None)
|
|
76
|
+
if body is None:
|
|
77
|
+
return MappingProxyType({})
|
|
78
|
+
defs = {i.result: i for block in body.blocks for i in block.instructions if i.result is not None}
|
|
79
|
+
stored: dict[str, list[Value | None]] = {}
|
|
80
|
+
for block in body.blocks:
|
|
81
|
+
for instruction in block.instructions:
|
|
82
|
+
if isinstance(instruction, StoreLocal):
|
|
83
|
+
stored.setdefault(instruction.name, []).append(instruction.value)
|
|
84
|
+
if isinstance(block.terminator, ForNext):
|
|
85
|
+
# A ``for`` binds its target to each item.
|
|
86
|
+
stored.setdefault(block.terminator.target, []).append(None)
|
|
87
|
+
rebound = {
|
|
88
|
+
i.name for function in functions for block in function.blocks for i in block.instructions
|
|
89
|
+
if isinstance(i, SetGlobal)
|
|
90
|
+
}
|
|
91
|
+
rebound |= {s.name for s in ctx.module.body if isinstance(s, nodes.Function | nodes.Class)}
|
|
92
|
+
found: dict[str, str] = {}
|
|
93
|
+
for name, values in stored.items():
|
|
94
|
+
value = values[0] if len(values) == 1 and name not in rebound else None
|
|
95
|
+
made = defs.get(value) if value is not None else None
|
|
96
|
+
if isinstance(made, Constant) and isinstance(made.value, str):
|
|
97
|
+
found[name] = made.value
|
|
98
|
+
return MappingProxyType(found)
|
|
@@ -1,12 +1,37 @@
|
|
|
1
|
-
"""Server-side request forgery: attacker-controlled input reaching a SSRF sink.
|
|
1
|
+
"""Server-side request forgery: attacker-controlled input reaching a SSRF sink.
|
|
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.
|
|
11
|
+
"""
|
|
2
12
|
|
|
3
13
|
from __future__ import annotations
|
|
4
14
|
|
|
15
|
+
import re
|
|
5
16
|
from typing import ClassVar
|
|
6
17
|
|
|
18
|
+
from coretrace_python.abstract.strings import ModuleStringsAnalysis, leading_text
|
|
19
|
+
from coretrace_python.analysis import AnyAnalysis
|
|
7
20
|
from coretrace_python.findings import Severity
|
|
8
|
-
from coretrace_python.
|
|
9
|
-
from coretrace_python.
|
|
21
|
+
from coretrace_python.findings.refutation import Status, Verdict
|
|
22
|
+
from coretrace_python.hir import nodes
|
|
23
|
+
from coretrace_python.ir.ssa import SSAAnalysis
|
|
24
|
+
from coretrace_python.plugins import PluginContext, TaintDetector
|
|
25
|
+
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")
|
|
10
35
|
|
|
11
36
|
|
|
12
37
|
class SsrfPlugin(TaintDetector):
|
|
@@ -15,3 +40,25 @@ class SsrfPlugin(TaintDetector):
|
|
|
15
40
|
kind: ClassVar[TaintKind] = TaintKind.SSRF
|
|
16
41
|
severity: ClassVar[Severity] = Severity.HIGH
|
|
17
42
|
title: ClassVar[str] = "Server-side request forgery"
|
|
43
|
+
requires: ClassVar[frozenset[AnyAnalysis]] = TaintDetector.requires | {SSAAnalysis, ModuleStringsAnalysis}
|
|
44
|
+
|
|
45
|
+
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
|
+
ssa = ctx.get(SSAAnalysis, function)
|
|
49
|
+
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:
|
|
53
|
+
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:
|
|
57
|
+
if no_redirects:
|
|
58
|
+
return Verdict(flow, Status.REFUTED, f"the destination is fixed by {text!r} and redirects are disabled")
|
|
59
|
+
left = "a redirect may lead elsewhere"
|
|
60
|
+
else:
|
|
61
|
+
left = "the input chooses the path" + ("" if no_redirects else ", and a redirect may lead elsewhere")
|
|
62
|
+
if verdict.status is not Status.VULNERABILITY:
|
|
63
|
+
return verdict
|
|
64
|
+
return Verdict(flow, Status.HOTSPOT, f"the host is fixed by {host.group(0)!r}, but {left}")
|
coretrace_python/engine.py
CHANGED
|
@@ -17,6 +17,7 @@ from typing import Any, ClassVar
|
|
|
17
17
|
|
|
18
18
|
from coretrace_python import __version__
|
|
19
19
|
from coretrace_python.abstract import ConstantPropagation, HeapAnalysis, RangeAnalysis
|
|
20
|
+
from coretrace_python.abstract.strings import ModuleStringsAnalysis
|
|
20
21
|
from coretrace_python.analysis import (
|
|
21
22
|
AnalysisContext,
|
|
22
23
|
AnalysisManager,
|
|
@@ -143,6 +144,7 @@ ALL_ANALYSES: tuple[AnyAnalysis, ...] = (
|
|
|
143
144
|
DefUseAnalysis,
|
|
144
145
|
ConstantPropagation,
|
|
145
146
|
RangeAnalysis,
|
|
147
|
+
ModuleStringsAnalysis,
|
|
146
148
|
HeapAnalysis,
|
|
147
149
|
CallGraphAnalysis,
|
|
148
150
|
SummaryAnalysis,
|
|
@@ -13,13 +13,14 @@ from typing import ClassVar
|
|
|
13
13
|
|
|
14
14
|
from coretrace_python.analysis import AnyAnalysis
|
|
15
15
|
from coretrace_python.findings import Confidence, Finding, Severity
|
|
16
|
-
from coretrace_python.findings.refutation import RefutationAnalysis, Status
|
|
16
|
+
from coretrace_python.findings.refutation import RefutationAnalysis, Status, Verdict
|
|
17
|
+
from coretrace_python.hir import nodes
|
|
17
18
|
from coretrace_python.interprocedural import CallGraphAnalysis
|
|
18
19
|
from coretrace_python.ir.model import Call, Instruction, Symbol, Value
|
|
19
20
|
from coretrace_python.ir.ssa import SSAAnalysis
|
|
20
21
|
from coretrace_python.plugins.api import Plugin, PluginContext
|
|
21
22
|
from coretrace_python.semantic.symbols import SymbolId
|
|
22
|
-
from coretrace_python.taint import TaintAnalysis, TaintKind
|
|
23
|
+
from coretrace_python.taint import TaintAnalysis, TaintFlow, TaintKind
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class TaintDetector(Plugin):
|
|
@@ -40,6 +41,9 @@ class TaintDetector(Plugin):
|
|
|
40
41
|
if not flow.kinds & self.kind:
|
|
41
42
|
continue
|
|
42
43
|
verdict = verdicts.verdict(flow)
|
|
44
|
+
if verdict.status is Status.REFUTED:
|
|
45
|
+
continue
|
|
46
|
+
verdict = self.judge(ctx, function, flow, verdict)
|
|
43
47
|
if verdict.status is Status.REFUTED:
|
|
44
48
|
continue
|
|
45
49
|
message = f"{self.title}: {flow.source.label} input reaches {flow.sink.symbol}"
|
|
@@ -70,6 +74,13 @@ class TaintDetector(Plugin):
|
|
|
70
74
|
)
|
|
71
75
|
return findings
|
|
72
76
|
|
|
77
|
+
def judge(self, ctx: PluginContext, function: nodes.Function, flow: TaintFlow, verdict: Verdict) -> Verdict:
|
|
78
|
+
"""This rule's verdict on ``flow``, given the refutation's: the same, unless the rule
|
|
79
|
+
knows more about its own sinks. The refutation's verdict, which other consumers
|
|
80
|
+
of the flow read, does not change."""
|
|
81
|
+
|
|
82
|
+
return verdict
|
|
83
|
+
|
|
73
84
|
|
|
74
85
|
def _lower(confidence: Confidence) -> Confidence:
|
|
75
86
|
return {Confidence.HIGH: Confidence.MEDIUM}.get(confidence, Confidence.LOW)
|
{coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: coretrace-python-analyzer
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.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
|
{coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/RECORD
RENAMED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
coretrace_python/__init__.py,sha256=
|
|
1
|
+
coretrace_python/__init__.py,sha256=kY0Q5RzkkixmFjJXYSXgYgHOkh327TcAyqMH9u0a_M0,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=
|
|
5
|
+
coretrace_python/engine.py,sha256=yICn93LZyoWOdDoZEIqoWATuhPQhLPW8ANLxJPskDwM,32371
|
|
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
|
|
9
9
|
coretrace_python/abstract/ranges.py,sha256=zEl9ee55u3E02tkYzzIvCCud5mYRKIUgZd9h_0-crCM,11547
|
|
10
|
+
coretrace_python/abstract/strings.py,sha256=G5EGlhxjrpjU9TuXQifuVO-6MNMrUtZ_4S3nkMEvIuQ,4095
|
|
10
11
|
coretrace_python/abstract/values.py,sha256=SQmgR8jo7cd8KJFDokejg-cFTjJU1CTBUPYyEvbMg-4,1739
|
|
11
12
|
coretrace_python/analysis/__init__.py,sha256=hE7lDwXOdA05_aSZaERRgMv0C2ev8jjJbz4xvrja4Og,728
|
|
12
13
|
coretrace_python/analysis/manager.py,sha256=suoIrPwimyu1AjF6BJwpqAkJBwe6XxzQu9JwV2TN2aQ,5843
|
|
@@ -63,8 +64,8 @@ coretrace_python/bundled/security/plaintext_credentials/plaintext_credentials.py
|
|
|
63
64
|
coretrace_python/bundled/security/plaintext_credentials/plugin.toml,sha256=W56wUdAdf7NNirfQhTdKrn-cCwebqmvkRJg9OVFJUyM,263
|
|
64
65
|
coretrace_python/bundled/security/sql_injection/plugin.toml,sha256=U35h6YdbbM93Ar_msWrwY98_bb6rN-qaa1e7XOtPeSo,224
|
|
65
66
|
coretrace_python/bundled/security/sql_injection/sql_injection.py,sha256=W-ppZngb9mLwRjJPGkh__8kaDqYdSrVbciv0mPdYFNE,545
|
|
66
|
-
coretrace_python/bundled/security/ssrf/plugin.toml,sha256=
|
|
67
|
-
coretrace_python/bundled/security/ssrf/ssrf.py,sha256=
|
|
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
69
|
coretrace_python/bundled/security/xss/plugin.toml,sha256=o6aZWoDNCG6CJ11JDa5lVR0v6NHh-Jg5QpNRxoGSJaw,185
|
|
69
70
|
coretrace_python/bundled/security/xss/xss.py,sha256=hzhoblPMivtwoWZ4v7YyAb15GGisX_imGWgxFzCDeqA,532
|
|
70
71
|
coretrace_python/bundled/syntax/dangerous_eval/dangerous_eval.py,sha256=_ktrigLDf-XTKjWtYX-_wZ9-Gb3G4bCzRhpU0Xj-c1g,723
|
|
@@ -124,7 +125,7 @@ coretrace_python/ir/printer.py,sha256=otBIhZUvB_UfB68gid_FbPcSjBUSmxH3v7vBMZZQVk
|
|
|
124
125
|
coretrace_python/ir/ssa.py,sha256=cIYbcv90PI6AOeMrw2ZWp88fy7E2ZO4P3tqjtPHra7g,11116
|
|
125
126
|
coretrace_python/plugins/__init__.py,sha256=xRKqkvkvQMmfQACHHoBioYhIyyK4HoMAVogy6EZG8tg,1398
|
|
126
127
|
coretrace_python/plugins/api.py,sha256=FcIe2c4sFB-PAPtYcJkidvdZJkr_xFKT8SvlBP5l38o,8603
|
|
127
|
-
coretrace_python/plugins/detectors.py,sha256=
|
|
128
|
+
coretrace_python/plugins/detectors.py,sha256=9c6yaLvf5nwtiiIskLd9WE_R4IE_RcqjOD5c-SH0SuI,6274
|
|
128
129
|
coretrace_python/plugins/loader.py,sha256=Use-lHTL4-IJYQBZmODC89zhJbYKGvDSLZHWjZa5NaI,3885
|
|
129
130
|
coretrace_python/plugins/manifest.py,sha256=F24pgQSwApRUL6ZihRSLv9wL_M03A_pZjrj9Zi4Ku3Q,3438
|
|
130
131
|
coretrace_python/plugins/registry.py,sha256=ixKcT2YDky96TWCFckdzKnGRmFn1dbBVMSZLPvdxvY8,1177
|
|
@@ -147,9 +148,9 @@ coretrace_python/taint/engine.py,sha256=rEAbwjR5v294PqBzBlu6f9WiMvVmwV83FqdsWbT4
|
|
|
147
148
|
coretrace_python/taint/models.py,sha256=8AwPKKdmwAHmE7CxwUbtWn5w7JVkEJ06_Is7xQWTx38,17066
|
|
148
149
|
coretrace_python/taint/routes.py,sha256=UAJKXcw_sM9shf58FfDroxVO9bNSm4qrQdZknwUB0lo,6110
|
|
149
150
|
coretrace_python/taint/templates.py,sha256=8Ojb43VXuWxOVifeXRpi3_2mjZfnvIC7GQ-AW80GUYk,11148
|
|
150
|
-
coretrace_python_analyzer-0.
|
|
151
|
-
coretrace_python_analyzer-0.
|
|
152
|
-
coretrace_python_analyzer-0.
|
|
153
|
-
coretrace_python_analyzer-0.
|
|
154
|
-
coretrace_python_analyzer-0.
|
|
155
|
-
coretrace_python_analyzer-0.
|
|
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,,
|
{coretrace_python_analyzer-0.13.0.dist-info → coretrace_python_analyzer-0.14.0.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|