Repository navigation
Getting Started
pip install coretrace-python-analyzerNo runtime dependency, and the analysis runs offline.
coretrace-python-analyzer --check src/Every .py file under src/ is analysed as one project, and findings are printed one per
line, followed by a count and a coverage line:
src/app.py:44:26: high command-injection: Command injection: http input reaches python.os.system through services.run_command [command_injection]
src/app.py:71:14: high dangerous-eval: call to python.builtins.eval executes dynamically built code [code_injection]
2 findings
coverage: 2/2 files, 12/12 functions
The coverage line matters: it tells "no findings" apart from "nothing analysed".
| Status | Meaning |
|---|---|
0 |
Nothing was reported |
1 |
Findings were reported |
2 |
Usage or analysis error |
So the command gates a pipeline as it is. --fail-on high keeps reporting every finding but
fails only from that severity up.
Given a directory, every .py file below it is a module of one project, named after its package
(app/views.py is app.views).
Skipped: hidden directories, node_modules, __pycache__, build, dist, and any virtual
environment — recognised by its pyvenv.cfg whatever its name.
Also read: dependency files at the root (requirements*.txt, pyproject.toml,
poetry.lock, uv.lock) build a dependency graph; configuration files under the root (.env,
YAML, TOML, JSON, INI, properties) are scanned for secrets.
Analysed as functions: functions and methods, but also the module body and the bodies of
top-level classes, as <module> and Cls.<body>. So application = get_asgi_application() in
asgi.py, email = forms.EmailField() in a form class, and a module-level
os.system(input()) are all seen.
The analyzer says so rather than staying silent:
- A function using syntax outside the supported subset is reported as an
unsupported-syntaxnote, and the other functions are still analysed. - A file Python itself cannot parse is reported as a
syntax-error. - The coverage line and the JSON report's per-file detail distinguish the two from a clean run.
HTTP input is recognised for Flask, FastAPI, Django, aiohttp, Tornado and Bottle: route
handlers, class-based views and registered URL patterns. A method a handler class inherits from
its framework base — self.get_argument, self.request — denotes the base's.
Further sources: click and Typer commands (argv), input(), sys.argv, environment
variables, the output of local processes, and the responses of HTTP clients.
Three of those are operator-controlled and deliberately do not carry the matching kinds: a command-line tool opens the paths it is given, a command or path built from the environment is the operator's own doing, and a path read from a local process is not a traversal. A downloaded script piped into a shell remains a command injection.