rce-path 0.1.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 (39) hide show
  1. rce_path-0.1.0/.github/workflows/ci.yml +29 -0
  2. rce_path-0.1.0/.github/workflows/publish.yml +49 -0
  3. rce_path-0.1.0/.gitignore +15 -0
  4. rce_path-0.1.0/CONTRIBUTING.md +23 -0
  5. rce_path-0.1.0/LICENSE +21 -0
  6. rce_path-0.1.0/PKG-INFO +79 -0
  7. rce_path-0.1.0/README.md +45 -0
  8. rce_path-0.1.0/docs/providers.md +34 -0
  9. rce_path-0.1.0/docs/releasing.md +63 -0
  10. rce_path-0.1.0/docs/usage.md +169 -0
  11. rce_path-0.1.0/examples/investigate.py +15 -0
  12. rce_path-0.1.0/examples/rce-path.toml +23 -0
  13. rce_path-0.1.0/pyproject.toml +63 -0
  14. rce_path-0.1.0/rce-path_spec.md +144 -0
  15. rce_path-0.1.0/scripts/check_install.py +52 -0
  16. rce_path-0.1.0/src/rce_path/__init__.py +8 -0
  17. rce_path-0.1.0/src/rce_path/__main__.py +4 -0
  18. rce_path-0.1.0/src/rce_path/_worker.py +149 -0
  19. rce_path-0.1.0/src/rce_path/cfg.py +76 -0
  20. rce_path-0.1.0/src/rce_path/cli.py +78 -0
  21. rce_path-0.1.0/src/rce_path/config.py +100 -0
  22. rce_path-0.1.0/src/rce_path/findings.py +108 -0
  23. rce_path-0.1.0/src/rce_path/flow.py +590 -0
  24. rce_path-0.1.0/src/rce_path/ingest.py +309 -0
  25. rce_path-0.1.0/src/rce_path/llm/__init__.py +103 -0
  26. rce_path-0.1.0/src/rce_path/llm/contract.py +195 -0
  27. rce_path-0.1.0/src/rce_path/llm/providers/__init__.py +4 -0
  28. rce_path-0.1.0/src/rce_path/llm/providers/base.py +163 -0
  29. rce_path-0.1.0/src/rce_path/llm/providers/ollama.py +93 -0
  30. rce_path-0.1.0/src/rce_path/llm/providers/openai.py +82 -0
  31. rce_path-0.1.0/src/rce_path/py.typed +0 -0
  32. rce_path-0.1.0/src/rce_path/reports.py +87 -0
  33. rce_path-0.1.0/src/rce_path/rules.py +60 -0
  34. rce_path-0.1.0/src/rce_path/symbols.py +59 -0
  35. rce_path-0.1.0/tests/fixtures/phase1.json +74 -0
  36. rce_path-0.1.0/tests/test_packaging.py +30 -0
  37. rce_path-0.1.0/tests/test_phase1.py +81 -0
  38. rce_path-0.1.0/tests/test_providers.py +306 -0
  39. rce_path-0.1.0/tests/test_safety.py +227 -0
@@ -0,0 +1,29 @@
1
+ name: Test and build
2
+ on:
3
+ push:
4
+ branches: ['**']
5
+ pull_request:
6
+ permissions:
7
+ contents: read
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: '3.13'
16
+ - run: python -m pip install -e ".[dev]"
17
+ - run: python -m pytest -q
18
+ - run: python -m ruff check src tests scripts
19
+ - run: python -m mypy
20
+ - run: python -m build
21
+ - run: python -m twine check dist/*
22
+ - name: Install and smoke-test wheel
23
+ run: |
24
+ python -c "import glob,subprocess,sys; subprocess.check_call([sys.executable,'-m','pip','install','--force-reinstall','--no-deps',glob.glob('dist/*.whl')[0]])"
25
+ python scripts/check_install.py
26
+ - uses: actions/upload-artifact@v4
27
+ with:
28
+ name: distributions
29
+ path: dist/*
@@ -0,0 +1,49 @@
1
+ name: Publish to PyPI
2
+ on:
3
+ push:
4
+ tags: ['rce-path-v*']
5
+ workflow_dispatch:
6
+ permissions:
7
+ contents: read
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: '3.13'
16
+ - name: Verify release version
17
+ if: github.event_name == 'push'
18
+ run: |
19
+ python - <<'PY'
20
+ import os, tomllib
21
+ version = tomllib.load(open('pyproject.toml', 'rb'))['project']['version']
22
+ assert os.environ['GITHUB_REF_NAME'] == f'rce-path-v{version}', 'Tag/version mismatch'
23
+ PY
24
+ - run: python -m pip install -e ".[dev]"
25
+ - run: python -m pytest -q
26
+ - run: python -m ruff check src tests scripts
27
+ - run: python -m mypy
28
+ - run: python -m build
29
+ - run: python -m twine check dist/*
30
+ - name: Install and smoke-test wheel
31
+ run: |
32
+ python -c "import glob,subprocess,sys; subprocess.check_call([sys.executable,'-m','pip','install','--force-reinstall','--no-deps',glob.glob('dist/*.whl')[0]])"
33
+ python scripts/check_install.py
34
+ - uses: actions/upload-artifact@v4
35
+ with:
36
+ name: distributions
37
+ path: dist/*
38
+ publish:
39
+ needs: build
40
+ runs-on: ubuntu-latest
41
+ environment: pypi
42
+ permissions:
43
+ id-token: write
44
+ steps:
45
+ - uses: actions/download-artifact@v4
46
+ with:
47
+ name: distributions
48
+ path: dist/
49
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .mypy_cache/
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ .coverage
11
+ htmlcov/
12
+ .rce-path-cache/
13
+ .test-runs/
14
+ .smoke-venv/
15
+ .validation-ci/
@@ -0,0 +1,23 @@
1
+ # Contributing
2
+
3
+ Install `python -m pip install -e ".[dev]"`. Keep the static scanner independent
4
+ of optional AI SDKs. Run pytest, Ruff, mypy, build, and Twine before release.
5
+
6
+ `src/rce_path` follows the spec's pipeline: ingestion, symbols, CFG, flow, rules,
7
+ findings, optional `llm/providers`, reports, and CLI. Models are versioned at the
8
+ evidence boundary. Add future cross-function summaries at the flow boundary,
9
+ provider roles at the review contract, and SARIF at the report boundary. Validation
10
+ must be a separate Phase 3 component; do not execute targets to improve static
11
+ coverage. No repository-provided executable plugins are accepted.
12
+
13
+ Labeled synthetic fixtures live in `tests/fixtures/phase1.json`. Each records a
14
+ unique ID, source, expected category/negative control, and relevant diagnostics.
15
+ They are development/release fixtures, not independent holdout benchmarks. Keep
16
+ future project datasets split by project and record provenance, revisions, and
17
+ vulnerable/patched labels before tuning. No detection superiority claim follows
18
+ from this fixture suite.
19
+
20
+ Provider tests use identical scenarios for both adapters, fake transports, no
21
+ credentials, no model downloads, and no network. Optional live tests are manual
22
+ and use the operator's selected model. Never store keys or raw SDK exceptions in
23
+ reports or fixtures. See `docs/providers.md` and `docs/releasing.md`.
rce_path-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sai Teja Erukude
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,79 @@
1
+ Metadata-Version: 2.5
2
+ Name: rce-path
3
+ Version: 0.1.0
4
+ Summary: Local-first, evidence-backed Python execution-path investigation
5
+ Author: Sai Teja Erukude
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: audit,dataflow,rce,security,static-analysis
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Security
17
+ Classifier: Typing :: Typed
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: pydantic<3,>=2.7
20
+ Provides-Extra: ai
21
+ Requires-Dist: ollama<1,>=0.4.7; extra == 'ai'
22
+ Requires-Dist: openai<3,>=1.68; extra == 'ai'
23
+ Provides-Extra: dev
24
+ Requires-Dist: build>=1.2; extra == 'dev'
25
+ Requires-Dist: mypy>=1.15; extra == 'dev'
26
+ Requires-Dist: pytest<10,>=8; extra == 'dev'
27
+ Requires-Dist: ruff>=0.11; extra == 'dev'
28
+ Requires-Dist: twine>=6; extra == 'dev'
29
+ Provides-Extra: ollama
30
+ Requires-Dist: ollama<1,>=0.4.7; extra == 'ollama'
31
+ Provides-Extra: openai
32
+ Requires-Dist: openai<3,>=1.68; extra == 'openai'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # rce-path
36
+
37
+ Trace potentially untrusted Python inputs to execution sinks, with source
38
+ locations and static flow evidence. Scans local code without executing it.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ python -m pip install .
44
+ # Optional AI backends: ".[openai]" or ".[ollama]"
45
+ ```
46
+
47
+ After publishing: `pip install rce-path`.
48
+
49
+ ## Quick start
50
+
51
+ ```bash
52
+ rce-path scan ./checkout --format json --output findings.json
53
+ rce-path scan ./checkout --format markdown --output report.md
54
+ ```
55
+
56
+ ```python
57
+ from rce_path import scan
58
+
59
+ report = scan("./checkout")
60
+ print(report.summary)
61
+ ```
62
+
63
+ ## Features
64
+
65
+ - Detects `eval`, `exec`, OS shell calls, and subprocess shell execution.
66
+ - Tracks parameters, Flask request data, and local inputs through assignments,
67
+ branches, and bounded loops.
68
+ - Exports evidence, assumptions, coverage diagnostics, and stable fingerprints.
69
+ - Supports optional OpenAI and Ollama reviews.
70
+
71
+ Static findings require human review. Remote AI code transmission requires
72
+ `--allow-remote-code`. Exit codes: **0** completed, **1** findings policy failed,
73
+ **2** incomplete scan or operational error.
74
+
75
+ [Usage & limitations](docs/usage.md) · [Configuration](examples/rce-path.toml) ·
76
+ [AI providers](docs/providers.md) · [Contributing](CONTRIBUTING.md) ·
77
+ [Publishing](docs/releasing.md)
78
+
79
+ Author: Sai Teja Erukude.
@@ -0,0 +1,45 @@
1
+ # rce-path
2
+
3
+ Trace potentially untrusted Python inputs to execution sinks, with source
4
+ locations and static flow evidence. Scans local code without executing it.
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ python -m pip install .
10
+ # Optional AI backends: ".[openai]" or ".[ollama]"
11
+ ```
12
+
13
+ After publishing: `pip install rce-path`.
14
+
15
+ ## Quick start
16
+
17
+ ```bash
18
+ rce-path scan ./checkout --format json --output findings.json
19
+ rce-path scan ./checkout --format markdown --output report.md
20
+ ```
21
+
22
+ ```python
23
+ from rce_path import scan
24
+
25
+ report = scan("./checkout")
26
+ print(report.summary)
27
+ ```
28
+
29
+ ## Features
30
+
31
+ - Detects `eval`, `exec`, OS shell calls, and subprocess shell execution.
32
+ - Tracks parameters, Flask request data, and local inputs through assignments,
33
+ branches, and bounded loops.
34
+ - Exports evidence, assumptions, coverage diagnostics, and stable fingerprints.
35
+ - Supports optional OpenAI and Ollama reviews.
36
+
37
+ Static findings require human review. Remote AI code transmission requires
38
+ `--allow-remote-code`. Exit codes: **0** completed, **1** findings policy failed,
39
+ **2** incomplete scan or operational error.
40
+
41
+ [Usage & limitations](docs/usage.md) · [Configuration](examples/rce-path.toml) ·
42
+ [AI providers](docs/providers.md) · [Contributing](CONTRIBUTING.md) ·
43
+ [Publishing](docs/releasing.md)
44
+
45
+ Author: Sai Teja Erukude.
@@ -0,0 +1,34 @@
1
+ # Provider validation
2
+
3
+ `tests/test_providers.py` applies the same contract fixtures to OpenAI and Ollama:
4
+ valid JSON, malformed JSON, refusal, truncation, unavailable model, timeout, rate
5
+ limit, invalid credentials, unsupported schema/options, and invented citations.
6
+ Tests also cover repair/retry bounds, byte/token budgets, cancellation, consent,
7
+ redaction, cache-key invalidation, and preservation of the static evidence.
8
+ Tests use stubs and require no keys or downloads.
9
+
10
+ For an optional live smoke test, create a temporary file containing:
11
+
12
+ ```python
13
+ def investigate(code):
14
+ eval(code)
15
+ ```
16
+
17
+ Install the appropriate extra. Start your existing Ollama server and choose a
18
+ model you have already installed; no automatic pulls occur. Then:
19
+
20
+ ```bash
21
+ rce-path scan smoke.py --ai ollama --model YOUR_MODEL --output ollama-review.json
22
+ rce-path scan smoke.py --ai openai --model YOUR_MODEL --allow-remote-code --output openai-review.json
23
+ ```
24
+
25
+ For OpenAI, supply `OPENAI_API_KEY` through the environment. Verify `ai_status`,
26
+ cited evidence IDs, usage, static fingerprint, and provider/model identity. An
27
+ unsupported schema/model is a failed review, not a reason to silently drop options.
28
+ Do not run live tests in standard CI. Local model refusals can appear as
29
+ schema-invalid output if the model does not emit a structured refusal marker;
30
+ either result is explicitly unsuccessful.
31
+
32
+ Implementation references: [OpenAI structured output](https://developers.openai.com/api/docs/guides/structured-outputs),
33
+ [Ollama structured output](https://docs.ollama.com/capabilities/structured-outputs),
34
+ and [Ollama chat API](https://docs.ollama.com/api/chat).
@@ -0,0 +1,63 @@
1
+ # Releasing rce-path
2
+
3
+ The repository builds version 0.1.0 as a wheel and source distribution. Before a
4
+ public release, verify availability/ownership of the normalized name `rce-path`
5
+ on PyPI and TestPyPI. Configure the repository URL in project metadata after the
6
+ actual GitHub repository exists. The publishing workflow lives in
7
+ `.github/workflows/publish.yml`.
8
+
9
+ ```bash
10
+ python -m pip install -e ".[dev]"
11
+ python -m pytest
12
+ python -m ruff check src tests
13
+ python -m mypy
14
+ python -m build
15
+ python -m twine check dist/*
16
+ ```
17
+
18
+ Install the built wheel in a fresh environment and run `rce-path --version` and
19
+ `rce-path scan --help`. Run `python scripts/check_install.py` with that environment's
20
+ Python for an offline CLI, metadata, typed-marker, and non-execution smoke test.
21
+ CI runs one Ubuntu job on Python 3.13 for branch pushes and pull requests. The labeled
22
+ fixture gate checks all supported classifications, sink spans, safe controls,
23
+ top-level non-execution, and limits. Provider tests run without external access.
24
+
25
+ To test upload manually (an explicit publishing action):
26
+
27
+ ```bash
28
+ python -m twine upload --repository testpypi dist/*
29
+ ```
30
+
31
+ Use your TestPyPI credentials and install the exact version in a clean environment.
32
+ Install Pydantic from PyPI first, then install the package from TestPyPI with
33
+ `--no-deps` to avoid mixing dependency indexes. See the
34
+ [official TestPyPI guide](https://packaging.python.org/en/latest/guides/using-testpypi/).
35
+
36
+ For GitHub/PyPI trusted publishing:
37
+
38
+ 1. Create the GitHub repository and commit this project, including its workflows.
39
+ 2. Configure a pending/active PyPI publisher for `rce-path`, the repository owner
40
+ and name, workflow `publish.yml`, and environment `pypi`.
41
+ 3. Create/protect the GitHub `pypi` environment with required reviewers.
42
+ 4. Ensure `pyproject.toml`, `rce_path.__version__`, CLI version, and report version
43
+ agree; tag the commit `rce-path-v0.1.0` and push that tag.
44
+ 5. The workflow verifies version, runs tests/checks, builds and checks artifacts,
45
+ then publishes through OIDC. It does not use a stored PyPI API token.
46
+
47
+ The workflow is present but needs a GitHub repository and PyPI publisher setup.
48
+ Use a new version for each upload; PyPI does not allow overwriting a release.
49
+
50
+ After configuring the publisher, commit and push your changes, then publish 0.1.0:
51
+
52
+ ```bash
53
+ git push origin main
54
+ git tag rce-path-v0.1.0
55
+ git push origin rce-path-v0.1.0
56
+ ```
57
+
58
+ A normal branch push runs CI; publishing runs on `rce-path-v*` tags. The tag's
59
+ version must match `pyproject.toml`. Alternatively, open GitHub Actions, select
60
+ **Publish to PyPI**, and use **Run workflow** to publish the version from your
61
+ selected branch. The manual button appears once the workflow is on the default
62
+ branch. Both release paths run validation before uploading and honor the `pypi`
63
+ environment's approval rules. Branch pushes do not upload to PyPI.
@@ -0,0 +1,169 @@
1
+ # Usage and limitations
2
+
3
+ Investigate potentially untrusted Python inputs reaching execution sinks, with
4
+ reproducible source locations and ordered static evidence. Built for researchers
5
+ reviewing local checkouts. **Phase 1, version 0.1.0; Python 3.11+.**
6
+
7
+ Author: Sai Teja Erukude. License: MIT. Uses the src layout, Hatch builds, typed API,
8
+ pytest, and trusted publishing conventions of `rai-audit`.
9
+
10
+ An execution sink is not automatically a vulnerability. Static flow does not prove
11
+ exploitability, deployment exposure, or remote code execution. Reports assign no
12
+ automatic severity, CVSS, or exploitability probability.
13
+
14
+ ## Installation
15
+
16
+ From this checkout:
17
+
18
+ ```bash
19
+ python -m pip install .
20
+ python -m pip install ".[openai]" # optional official OpenAI SDK
21
+ python -m pip install ".[ollama]" # optional official Ollama client
22
+ ```
23
+
24
+ After publishing, the equivalent PyPI installation is `pip install rce-path`.
25
+ The static scanner needs only Pydantic; it does not load either AI SDK.
26
+
27
+ ## Quick start
28
+
29
+ ```bash
30
+ rce-path scan ./checkout --format json --output findings.json
31
+ rce-path scan ./checkout --format markdown --output report.md
32
+ rce-path scan ./checkout --fail-on static-path
33
+ ```
34
+
35
+ ```python
36
+ from rce_path import ScanConfig, scan
37
+
38
+ report = scan("./checkout", config=ScanConfig(ai_enabled=False))
39
+ print(report.summary)
40
+ for finding in report.findings:
41
+ print(finding.rule_id, finding.location.file, finding.location.line)
42
+ for step in finding.steps:
43
+ print(step.kind, step.location.line, step.description)
44
+ ```
45
+
46
+ `rce-path` is the distribution/command name; `rce_path` is the Python import name.
47
+ Scan a directory or an individual `.py` file. Report methods include `to_json()`
48
+ and `to_markdown()`; public records are validated, typed Pydantic models.
49
+
50
+ ## Phase 1 models
51
+
52
+ - `eval`/`exec`, including builtin imports and common aliases.
53
+ - `os.system`/`os.popen`, including module/from imports and assignment aliases.
54
+ - `subprocess.run`, `call`, `check_call`, `check_output`, `Popen` with shell execution;
55
+ `getoutput` and `getstatusoutput` always imply shell execution. Unknown shell
56
+ values carry an explicit condition. `shell=False` scenarios produce limitations.
57
+ - Function parameters, Flask `request.args`, `request.form`, `request.data`, and
58
+ `request.get_data()`. Environment, CLI, stdin, and file reads are local input.
59
+ - Assignments, reassignment, concatenation, f-strings, branches, early returns,
60
+ and bounded loop fixed points over per-scope control-flow graphs.
61
+
62
+ Literal-only sinks are negative controls. Unknown return values produce
63
+ `sink_only` findings and unresolved evidence; unknown calls never propagate an
64
+ invented path and are never automatically treated as sanitizers. A guard or
65
+ escaping function does not prove the argument safe. Branch joins are conservative
66
+ overapproximations and can retain mutually exclusive conditions.
67
+
68
+ Every finding includes a stable fingerprint, rule/schema versions, exact relative
69
+ file spans (columns are AST UTF-8 byte offsets, zero based), source category,
70
+ evidence tier, ordered evidence, assumptions, unresolved calls, and review state.
71
+ `network_source_modeled` means a modeled network input, with authentication and
72
+ deployment still unknown. Fingerprints exclude AI annotations and absolute roots.
73
+ Content hashes cover read source files; revision is unknown unless supplied by a
74
+ future trusted provenance integration. Dependency-version provenance is empty in
75
+ Phase 1 because its rules are not dependency-version-sensitive.
76
+
77
+ ## Safety, completion, and coverage
78
+
79
+ Targets are read as data: no imports, package installation, target build hooks,
80
+ deserialization, or checkpoint loading. Excluded environments/build trees and
81
+ skipped files appear in diagnostics. Symlinks/reparse points are not followed.
82
+ Isolated parser/analysis workers enforce wall time, memory, AST, flow, and evidence
83
+ budgets. Windows uses Job Objects; POSIX uses `RLIMIT_AS`. If enforcement fails,
84
+ the worker fails and the report is incomplete. Source inventory and the static
85
+ scan also have overall time/file/inventory limits. The total scan deadline includes
86
+ requested AI reviews; each review also has its own timeout and token budget.
87
+
88
+ Exit codes: **0** completed and selected policy passed; **1** findings policy
89
+ failed; **2** operational/configuration error, incomplete static scan, or requested
90
+ AI review failed. `--fail-on none` is the default. Incomplete status wins over a
91
+ findings policy. A complete empty report says only **“No modeled findings.”**
92
+ Read coverage diagnostics even when the status is completed.
93
+
94
+ Supported target syntax follows the running Python interpreter (recorded in each
95
+ report). A Python 3.11 runtime cannot parse newer syntax. Cross-file/function flow,
96
+ closures, dynamic dispatch, complex heap mutation, comprehensions, and precise
97
+ exception/finally flow are outside Phase 1 coverage. Known unsupported constructs
98
+ produce diagnostics. Parsing is isolated and bounded, but this scanner is not a
99
+ general-purpose sandbox for running hostile code. Avoid concurrently modifying
100
+ the checkout during a scan.
101
+
102
+ ## Configuration
103
+
104
+ Use [`examples/rce-path.toml`](../examples/rce-path.toml) as a starter. `scan(path)`
105
+ and the CLI discover `rce-path.toml` at the scan root. Passing `ScanConfig` directly
106
+ uses exactly that configuration; the CLI also accepts `--config PATH`.
107
+ Unknown keys and invalid budgets fail explicitly. Exclusion patterns use forward
108
+ slashes. Repository configuration cannot enable AI, supply credentials, or grant
109
+ remote transmission permission. AI model/provider settings take effect only after
110
+ runtime opt-in. Repository AI endpoints are ignored unless the operator supplies
111
+ `--accept-config-ai-endpoint`; an explicit `--endpoint` takes precedence.
112
+
113
+ ## Optional AI annotations
114
+
115
+ ```bash
116
+ rce-path scan ./checkout --ai ollama --model YOUR_MODEL --format markdown
117
+ rce-path scan ./checkout --ai openai --model YOUR_MODEL --allow-remote-code
118
+ ```
119
+
120
+ Set `OPENAI_API_KEY` in the operator environment for OpenAI. Model names are always
121
+ operator-selected. OpenAI uses the official Responses API with strict structured
122
+ output and `store=False`; this is not a zero-retention promise. Ollama uses native
123
+ `/api/chat` with a JSON schema; the default is `http://127.0.0.1:11434`.
124
+
125
+ OpenAI and non-loopback Ollama endpoints require `--allow-remote-code`. Numeric
126
+ loopback addresses are recognized; hostnames, including `localhost`, conservatively
127
+ require consent to avoid DNS trust assumptions. No automatic cloud fallback.
128
+ Only bounded evidence slices are sent, with best-effort known-secret redaction.
129
+ Redaction can miss secrets; review your inputs before allowing transmission.
130
+ The scanner does not log raw prompts/source or provider exception bodies.
131
+
132
+ Both providers share `review(EvidenceBundle, ReviewConfig) -> ReviewResult`, validate
133
+ cited evidence IDs, and annotate without altering findings. Malformed output gets
134
+ at most one repair. Refusals/authentication failures do not trigger repairs.
135
+ Only transient failures retry with backoff and jitter. Requests are serial per
136
+ provider, with timeout, input/output size, context, review-count, and total token
137
+ budgets. Byte-based input token reservations are deliberately conservative;
138
+ actual tokenizer/context accounting varies by model. Temperature is omitted
139
+ unless explicitly declared supported through `ReviewConfig`.
140
+
141
+ `ai_status` distinguishes completed, refused, invalid_output, unsupported,
142
+ unavailable, and budget_exceeded. Failed reviews never appear successful.
143
+ Cancellation is available through `Cancellation` when constructing a provider;
144
+ in-flight transport completes or times out before cancellation takes effect.
145
+ No application cache is enabled or persisted; a versioned `cache_key()` helper is
146
+ provided for a future operator-controlled cache. Unknown model revisions remain
147
+ explicit. See [provider testing](providers.md) for optional live smoke tests.
148
+
149
+ ## Development and publishing
150
+
151
+ ```bash
152
+ python -m pip install -e ".[dev]"
153
+ python -m pytest
154
+ python -m ruff check src tests
155
+ python -m mypy
156
+ python -m build
157
+ python -m twine check dist/*
158
+ ```
159
+
160
+ See [CONTRIBUTING.md](../CONTRIBUTING.md) and [release instructions](releasing.md)
161
+ for TestPyPI, PyPI trusted publishing, and the version/tag checks. Nothing in a
162
+ normal scan uploads code. No publishing occurs when running the tests/build.
163
+
164
+ The full [specification](../rce-path_spec.md) guides module boundaries. Phase 2 will
165
+ add bounded local call summaries, deserialization/version-aware rules, framework
166
+ and process models, independent AI review, evaluation, and SARIF. Phase 3 will add
167
+ separate human-approved validation and evidence bundles. Those phases are not
168
+ implemented in this release. Phase 1's P1 external rule-file enhancement is deferred.
169
+
@@ -0,0 +1,15 @@
1
+ """Library usage. The specified target is inspected, never imported."""
2
+
3
+ from pathlib import Path
4
+
5
+ from rce_path import ScanConfig, scan
6
+
7
+ if __name__ == "__main__":
8
+ import argparse
9
+
10
+ parser = argparse.ArgumentParser()
11
+ parser.add_argument("target")
12
+ args = parser.parse_args()
13
+ report = scan(args.target, ScanConfig(ai_enabled=False))
14
+ Path("findings.json").write_text(report.to_json(), encoding="utf-8")
15
+ print(report.summary)
@@ -0,0 +1,23 @@
1
+ [scan]
2
+ rules = ["python.eval", "python.exec", "os.system", "os.popen", "subprocess.shell"]
3
+ excludes = [".git", ".venv", "venv", "__pycache__", "build", "dist", "node_modules", "site-packages"]
4
+ max_file_bytes = 1000000
5
+ max_files = 10000
6
+ parser_timeout_seconds = 10.0
7
+ parser_memory_mb = 256
8
+ scan_timeout_seconds = 120.0
9
+ max_ast_nodes = 30000
10
+ max_flow_steps = 20000
11
+ loop_iterations = 8
12
+ max_evidence_steps = 64
13
+
14
+ [ai]
15
+ provider = "ollama"
16
+ model = "YOUR_MODEL"
17
+ timeout_seconds = 30.0
18
+ max_reviews = 20
19
+ max_input_bytes = 16000
20
+ max_output_tokens = 1024
21
+ total_token_budget = 50000
22
+ # Runtime --ai is required. Endpoint settings require explicit acceptance.
23
+ # endpoint = "http://127.0.0.1:11434"
@@ -0,0 +1,63 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "rce-path"
7
+ version = "0.1.0"
8
+ description = "Local-first, evidence-backed Python execution-path investigation"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ authors = [{name = "Sai Teja Erukude"}]
13
+ requires-python = ">=3.11"
14
+ keywords = ["security", "static-analysis", "dataflow", "rce", "audit"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
23
+ "Topic :: Security",
24
+ "Typing :: Typed",
25
+ ]
26
+ dependencies = ["pydantic>=2.7,<3"]
27
+
28
+ [project.optional-dependencies]
29
+ openai = ["openai>=1.68,<3"]
30
+ ollama = ["ollama>=0.4.7,<1"]
31
+ ai = ["openai>=1.68,<3", "ollama>=0.4.7,<1"]
32
+ dev = ["pytest>=8,<10", "build>=1.2", "twine>=6", "ruff>=0.11", "mypy>=1.15"]
33
+
34
+ [project.scripts]
35
+ rce-path = "rce_path.cli:main"
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["src/rce_path"]
39
+
40
+ [tool.hatch.build.targets.sdist]
41
+ include = ["/src", "/tests", "/docs", "/examples", "/scripts", "/README.md", "/LICENSE", "/pyproject.toml", "/rce-path_spec.md", "/.github", "/CONTRIBUTING.md"]
42
+
43
+ [tool.pytest.ini_options]
44
+ testpaths = ["tests"]
45
+ pythonpath = ["src"]
46
+ addopts = "--import-mode=importlib"
47
+
48
+ [tool.ruff]
49
+ target-version = "py311"
50
+ line-length = 100
51
+
52
+ [tool.ruff.lint]
53
+ select = ["E4", "E7", "E9", "F", "I", "UP"]
54
+
55
+ [tool.mypy]
56
+ python_version = "3.11"
57
+ files = ["src/rce_path"]
58
+ check_untyped_defs = true
59
+
60
+ [[tool.mypy.overrides]]
61
+ # The static/dev installation intentionally excludes these optional AI SDKs.
62
+ module = ["openai.*", "ollama.*"]
63
+ ignore_missing_imports = true