slopaudit 1.0.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.
- slopaudit-1.0.0/.gitignore +12 -0
- slopaudit-1.0.0/CHANGELOG.md +113 -0
- slopaudit-1.0.0/LICENSE +21 -0
- slopaudit-1.0.0/PKG-INFO +273 -0
- slopaudit-1.0.0/README.md +238 -0
- slopaudit-1.0.0/action.yml +85 -0
- slopaudit-1.0.0/benchmarks/compare.py +261 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_abstract.py +11 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_add_tool.py +8 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_allowlist_command.py +12 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_confirmed_delete.py +10 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_constant_eval.py +3 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_env_key.py +5 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_json_output.py +8 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_literal_eval.py +7 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_logged_except.py +12 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_parameterised_sql.py +5 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_real_imports.py +9 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_token_cap.py +5 -0
- slopaudit-1.0.0/benchmarks/corpus/safe/safe_user_message.py +9 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/gap_cross_function.py +8 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/gap_instance_attribute.py +12 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/hal03_typo.py +6 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/inc_chat_residue.py +5 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/inc_placeholder.py +5 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/inc_stub.py +7 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/inc_swallow.py +6 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm01_format.py +9 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm01_system_dict.py +8 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm01_system_prompt.py +9 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm02_eval_openai.py +7 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm02_exec_langchain.py +4 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm03_shell.py +8 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm04_sql.py +5 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm05_path.py +6 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm06_url.py +8 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm08_shell_tool.py +10 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm08_toolkit.py +6 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm09_delete_tool.py +11 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/llm12_unbounded.py +5 -0
- slopaudit-1.0.0/benchmarks/corpus/vulnerable/sec_password.py +6 -0
- slopaudit-1.0.0/benchmarks/realworld.py +137 -0
- slopaudit-1.0.0/docs/PRD.md +11 -0
- slopaudit-1.0.0/docs/README.md +32 -0
- slopaudit-1.0.0/docs/benchmarks.md +86 -0
- slopaudit-1.0.0/docs/beyond-scanning.md +82 -0
- slopaudit-1.0.0/docs/ci-integration.md +123 -0
- slopaudit-1.0.0/docs/clean-room.md +29 -0
- slopaudit-1.0.0/docs/cli.md +138 -0
- slopaudit-1.0.0/docs/configuration.md +137 -0
- slopaudit-1.0.0/docs/decisions/0001-javascript-typescript.md +37 -0
- slopaudit-1.0.0/docs/decisions/0002-what-1-0-promises.md +30 -0
- slopaudit-1.0.0/docs/decisions/0003-renamed-to-slopaudit.md +27 -0
- slopaudit-1.0.0/docs/faq.md +97 -0
- slopaudit-1.0.0/docs/getting-started.md +133 -0
- slopaudit-1.0.0/docs/how-it-works.md +89 -0
- slopaudit-1.0.0/docs/privacy-and-safety.md +52 -0
- slopaudit-1.0.0/docs/python-api.md +79 -0
- slopaudit-1.0.0/docs/real-world-check.md +36 -0
- slopaudit-1.0.0/docs/releasing.md +100 -0
- slopaudit-1.0.0/docs/rules.md +320 -0
- slopaudit-1.0.0/docs/suppressing-findings.md +58 -0
- slopaudit-1.0.0/docs/writing-rules.md +115 -0
- slopaudit-1.0.0/examples/SPEC.md +12 -0
- slopaudit-1.0.0/examples/github-workflow.yml +22 -0
- slopaudit-1.0.0/examples/slopguard.toml +16 -0
- slopaudit-1.0.0/examples/vulnerable_agent/app.py +34 -0
- slopaudit-1.0.0/pyproject.toml +82 -0
- slopaudit-1.0.0/src/slopaudit/__init__.py +24 -0
- slopaudit-1.0.0/src/slopaudit/__main__.py +4 -0
- slopaudit-1.0.0/src/slopaudit/api.py +103 -0
- slopaudit-1.0.0/src/slopaudit/bench.py +136 -0
- slopaudit-1.0.0/src/slopaudit/cli.py +465 -0
- slopaudit-1.0.0/src/slopaudit/config.py +233 -0
- slopaudit-1.0.0/src/slopaudit/context.py +170 -0
- slopaudit-1.0.0/src/slopaudit/docgen.py +89 -0
- slopaudit-1.0.0/src/slopaudit/drift.py +137 -0
- slopaudit-1.0.0/src/slopaudit/engine.py +189 -0
- slopaudit-1.0.0/src/slopaudit/gentests.py +118 -0
- slopaudit-1.0.0/src/slopaudit/llm.py +193 -0
- slopaudit-1.0.0/src/slopaudit/manifest.py +119 -0
- slopaudit-1.0.0/src/slopaudit/models.py +127 -0
- slopaudit-1.0.0/src/slopaudit/py.typed +0 -0
- slopaudit-1.0.0/src/slopaudit/registry.py +137 -0
- slopaudit-1.0.0/src/slopaudit/regress.py +190 -0
- slopaudit-1.0.0/src/slopaudit/repair.py +182 -0
- slopaudit-1.0.0/src/slopaudit/reporters.py +153 -0
- slopaudit-1.0.0/src/slopaudit/rules/__init__.py +35 -0
- slopaudit-1.0.0/src/slopaudit/rules/drift.py +156 -0
- slopaudit-1.0.0/src/slopaudit/rules/hallucination.py +314 -0
- slopaudit-1.0.0/src/slopaudit/rules/incomplete.py +344 -0
- slopaudit-1.0.0/src/slopaudit/rules/llm_agents.py +220 -0
- slopaudit-1.0.0/src/slopaudit/rules/llm_flow.py +159 -0
- slopaudit-1.0.0/src/slopaudit/rules/secrets.py +134 -0
- slopaudit-1.0.0/src/slopaudit/rules/virtual.py +65 -0
- slopaudit-1.0.0/src/slopaudit/sandbox.py +170 -0
- slopaudit-1.0.0/src/slopaudit/spec.py +352 -0
- slopaudit-1.0.0/src/slopaudit/taint.py +530 -0
- slopaudit-1.0.0/tests/conftest.py +108 -0
- slopaudit-1.0.0/tests/test_api.py +57 -0
- slopaudit-1.0.0/tests/test_bench.py +60 -0
- slopaudit-1.0.0/tests/test_cli.py +206 -0
- slopaudit-1.0.0/tests/test_docs.py +55 -0
- slopaudit-1.0.0/tests/test_drift.py +86 -0
- slopaudit-1.0.0/tests/test_gentests.py +106 -0
- slopaudit-1.0.0/tests/test_hallucination.py +182 -0
- slopaudit-1.0.0/tests/test_incomplete.py +92 -0
- slopaudit-1.0.0/tests/test_llm.py +85 -0
- slopaudit-1.0.0/tests/test_llm_flow.py +112 -0
- slopaudit-1.0.0/tests/test_llm_phase2.py +183 -0
- slopaudit-1.0.0/tests/test_realworld_regressions.py +190 -0
- slopaudit-1.0.0/tests/test_regress.py +91 -0
- slopaudit-1.0.0/tests/test_repair.py +162 -0
- slopaudit-1.0.0/tests/test_sandbox.py +82 -0
- slopaudit-1.0.0/tests/test_secrets.py +47 -0
- slopaudit-1.0.0/tests/test_spec.py +140 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are listed here. The format follows [Keep a Changelog](https://keepachangelog.com/),
|
|
4
|
+
and versions follow [Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## [1.0.0] - 2026-11-04
|
|
7
|
+
|
|
8
|
+
First stable release, and the first on PyPI. **Renamed from `slopguard` to `slopaudit`**, because PyPI
|
|
9
|
+
refused the old name as too similar to existing projects ([decision 0003](docs/decisions/0003-renamed-to-slopaudit.md)).
|
|
10
|
+
The command is `slopaudit`, the config file `slopaudit.toml`, and suppressions are `# slopaudit: ignore[...]`.
|
|
11
|
+
|
|
12
|
+
**What 1.0 promises:** the scanner (`scan`, every rule not marked experimental, the
|
|
13
|
+
output formats, configuration, baselines and suppressions), `regress`, `bench`, the Python API, the GitHub
|
|
14
|
+
Action and the pre-commit hook. Breaking changes to these wait for 2.0.
|
|
15
|
+
|
|
16
|
+
**Experimental, outside that promise:** `scan --spec --llm`, `gen-tests`, `fix` and the Docker sandbox
|
|
17
|
+
backend. They are tested against local stand-ins, not live services, and may change in a minor release.
|
|
18
|
+
Rules marked `experimental` in `slopaudit rules` may also change. See
|
|
19
|
+
[decision 0002](docs/decisions/0002-what-1-0-promises.md).
|
|
20
|
+
|
|
21
|
+
### Fixed since 1.0.0rc2
|
|
22
|
+
|
|
23
|
+
- HAL-04 now reads uv and PDM dev dependencies, Hatch environments, `setup.cfg` and `Pipfile`, so packages
|
|
24
|
+
declared there are no longer reported as undeclared.
|
|
25
|
+
- A `pyproject.toml` or `setup.cfg` that only holds tool settings (such as `[tool.ruff]` or `[flake8]`) no
|
|
26
|
+
longer counts as a manifest that declares nothing, which made HAL-04 flag every third-party import.
|
|
27
|
+
|
|
28
|
+
## [1.0.0rc2] - TestPyPI only, as `slopguard`
|
|
29
|
+
|
|
30
|
+
Fixes from running slopaudit on a real project (an agent with fixture packages and a Postgres store).
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- HAL-01 and HAL-04 no longer report a package's own modules as unknown when they are imported by absolute
|
|
35
|
+
name from inside a fixture or test folder. Every folder or module in the project now counts as local.
|
|
36
|
+
- HAL-04 reads `requirements*.txt` and `pyproject.toml` from the file's folder and every folder above it, so
|
|
37
|
+
subprojects and fixtures can declare their own dependencies.
|
|
38
|
+
- HAL-03 no longer calls `psycopg` (psycopg 3) a typo of `psycopg2`; other legitimate neighbours of popular
|
|
39
|
+
names were added too.
|
|
40
|
+
- SEC-01 reports credentials named like test data (`FAKE_KEY`, `TEST_API_KEY`) as low severity, so they no
|
|
41
|
+
longer fail builds. Normal names stay critical, and "latest" is not mistaken for "test".
|
|
42
|
+
|
|
43
|
+
## [1.0.0rc1] - TestPyPI only, as `slopguard`
|
|
44
|
+
|
|
45
|
+
First release candidate. Not yet published to PyPI.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- `slopaudit scan` with terminal, JSON, Markdown and SARIF 2.1.0 output; `--diff`, `--staged`,
|
|
50
|
+
baselines, inline suppressions, and `slopaudit.toml` or `[tool.slopaudit]` configuration.
|
|
51
|
+
- Rules: SEC-01; LLM-01 to LLM-06, LLM-08, LLM-09, LLM-12; HAL-01 to HAL-04; INC-01, INC-02,
|
|
52
|
+
INC-04, INC-05, INC-06, INC-08. See [docs/rules.md](docs/rules.md).
|
|
53
|
+
- A taint tracker for model output, untrusted input and agent-tool arguments (within one function).
|
|
54
|
+
- `scan --spec` requirement checking (SPC-02), with an offline heuristic and optional model judging.
|
|
55
|
+
- Opt-in style drift rules DRF-01 to DRF-03.
|
|
56
|
+
- `slopaudit regress` for deleted, skipped or weakened tests and tests that stopped passing (REG-01, REG-02).
|
|
57
|
+
- `slopaudit gen-tests` with a sandbox (Docker, Linux namespaces, or explicit local).
|
|
58
|
+
- `slopaudit fix`, a verify-and-repair loop that is a dry run unless `--apply` is given.
|
|
59
|
+
- LLM clients for Anthropic, OpenAI and Ollama over plain HTTPS.
|
|
60
|
+
- `slopaudit bench`, a labelled corpus, `benchmarks/compare.py` and `benchmarks/realworld.py`.
|
|
61
|
+
- A composite GitHub Action that uploads SARIF, a pre-commit hook, CI and release workflows.
|
|
62
|
+
|
|
63
|
+
### Changed after the real-world check
|
|
64
|
+
|
|
65
|
+
Scanning 1.5 million lines of well-reviewed packages found many false positives, and the rules
|
|
66
|
+
were tightened ([details](docs/real-world-check.md)):
|
|
67
|
+
|
|
68
|
+
- SEC-01 no longer flags environment-variable names, endpoints, dotted keys, values that repeat
|
|
69
|
+
the variable name, key headers without key material, or documented example keys.
|
|
70
|
+
- SEC-01 now also finds variables named exactly `token`, `secret` or `password` (they were missed).
|
|
71
|
+
- INC-01 only flags imperative placeholders such as "add your code here".
|
|
72
|
+
- INC-02 reports hollow methods and typed `...` stubs as low severity, and skips functions whose
|
|
73
|
+
docstring explains the intent (hook, override, no-op).
|
|
74
|
+
- INC-04 flags only broad or bare `except ... : pass` with no explanatory comment.
|
|
75
|
+
- HAL-01 knows more import-name aliases and recent stdlib modules, and reports optional, lazy and
|
|
76
|
+
`TYPE_CHECKING` imports as medium.
|
|
77
|
+
|
|
78
|
+
### Added since the first draft of this release
|
|
79
|
+
|
|
80
|
+
- `slopaudit.scan()` and `slopaudit.scan_source()`, a supported Python API with a `py.typed` marker.
|
|
81
|
+
- `[packages] private` to tell the HAL rules about imports from a private index.
|
|
82
|
+
- Generated reference pages (`slopaudit.docgen`) kept in sync by tests, a full documentation set, and
|
|
83
|
+
contributor files: code of conduct, support guide, issue and pull-request templates, Dependabot,
|
|
84
|
+
`Makefile`, `.editorconfig` and a pre-commit config.
|
|
85
|
+
- A release workflow that dry-runs to TestPyPI and publishes to PyPI by trusted publishing.
|
|
86
|
+
|
|
87
|
+
### Release pipeline
|
|
88
|
+
|
|
89
|
+
- The PyPI description no longer has broken relative links: the build rewrites them to absolute GitHub
|
|
90
|
+
URLs, and `scripts/check_dist.py` fails the build if any remain.
|
|
91
|
+
- The publishing action is pinned to a commit, and repeated TestPyPI dry runs no longer fail on an
|
|
92
|
+
existing version.
|
|
93
|
+
|
|
94
|
+
### Safety
|
|
95
|
+
|
|
96
|
+
- `slopaudit fix` never sends a file containing a hardcoded credential to a model.
|
|
97
|
+
- The terminal output warns when no supported files were found, so an unsupported language is not mistaken for a clean scan.
|
|
98
|
+
|
|
99
|
+
### Fixed
|
|
100
|
+
|
|
101
|
+
- The docs now say `python3` where macOS has no `python`, and `make` defaults to `python3`.
|
|
102
|
+
|
|
103
|
+
### Removed
|
|
104
|
+
|
|
105
|
+
- The `[llm] max_tokens` setting, which was accepted but never used.
|
|
106
|
+
|
|
107
|
+
### Known limitations
|
|
108
|
+
|
|
109
|
+
- The taint tracker does not follow values across functions or through instance attributes.
|
|
110
|
+
- The LLM clients and the Docker sandbox backend have not been run against live services.
|
|
111
|
+
- The spec checker without a model can show that code exists, not that it behaves correctly.
|
|
112
|
+
- Python only; see [docs/decisions/0001-javascript-typescript.md](docs/decisions/0001-javascript-typescript.md).
|
|
113
|
+
- The benchmark corpus is small and written by the maintainers.
|
slopaudit-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 slopaudit contributors
|
|
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.
|
slopaudit-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: slopaudit
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Verify AI-generated code: LLM-app security, hallucinated packages, stubs and spec drift.
|
|
5
|
+
Project-URL: Homepage, https://github.com/patsypppe/slopaudit
|
|
6
|
+
Project-URL: Repository, https://github.com/patsypppe/slopaudit
|
|
7
|
+
Project-URL: Issues, https://github.com/patsypppe/slopaudit/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/patsypppe/slopaudit/blob/main/CHANGELOG.md
|
|
9
|
+
Author: slopaudit contributors
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai-generated-code,llm,sarif,security,static-analysis
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Security
|
|
25
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Requires-Dist: rich>=13
|
|
28
|
+
Requires-Dist: tomli>=2; python_version < '3.11'
|
|
29
|
+
Requires-Dist: typer>=0.12
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# slopaudit
|
|
37
|
+
|
|
38
|
+
[](https://pypi.org/project/slopaudit/)
|
|
39
|
+
[](https://pypi.org/project/slopaudit/)
|
|
40
|
+
[](https://github.com/patsypppe/slopaudit/actions/workflows/ci.yml)
|
|
41
|
+
[](https://github.com/patsypppe/slopaudit/blob/main/LICENSE)
|
|
42
|
+
[](https://github.com/patsypppe/slopaudit/labels/good%20first%20issue)
|
|
43
|
+
|
|
44
|
+
**Check AI-written code before you trust it.** slopaudit is an open-source command-line tool for Python
|
|
45
|
+
that finds the problems AI assistants and LLM-powered apps tend to introduce, and that general scanners
|
|
46
|
+
were not built to look for.
|
|
47
|
+
|
|
48
|
+
- **Is it safe?** Does model output reach `eval`, a shell or a SQL query? Does untrusted input end up
|
|
49
|
+
in a system prompt? Does an agent tool hand the model a shell?
|
|
50
|
+
- **Is it real?** Does that imported package exist, or is it invented (or one typo from a popular one)?
|
|
51
|
+
- **Is it finished?** Stubs, "rest of code here" comments, swallowed errors, truncated files.
|
|
52
|
+
- **Is it what you asked for?** Does the code meet each requirement in your spec, and did the change
|
|
53
|
+
delete or weaken tests to get there?
|
|
54
|
+
|
|
55
|
+
It runs on your machine, never executes the code it scans, needs no account or API key, and has no telemetry.
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
You need Python 3.10 or newer. Pick one:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pipx install slopaudit # recommended: an isolated command-line tool
|
|
63
|
+
uv tool install slopaudit # same idea, if you use uv
|
|
64
|
+
python3 -m pip install slopaudit # inside a virtual environment
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Then check it works:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
slopaudit --version
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Just try it, without installing anything:**
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pipx run slopaudit scan . # or: uvx slopaudit scan .
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
<details>
|
|
80
|
+
<summary>Don't have pipx, upgrading, uninstalling, or installing from source</summary>
|
|
81
|
+
|
|
82
|
+
| I want to | Run |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| Get pipx on macOS | `brew install pipx && pipx ensurepath` |
|
|
85
|
+
| Get pipx elsewhere | `python3 -m pip install --user pipx && python3 -m pipx ensurepath` |
|
|
86
|
+
| Upgrade | `pipx upgrade slopaudit`, or `python3 -m pip install --upgrade slopaudit` |
|
|
87
|
+
| Uninstall | `pipx uninstall slopaudit`, or `python3 -m pip uninstall slopaudit` |
|
|
88
|
+
| Install a specific version | `pipx install slopaudit==1.0.0` |
|
|
89
|
+
| Install the latest unreleased code | `pipx install git+https://github.com/patsypppe/slopaudit` |
|
|
90
|
+
| Hack on it | `git clone https://github.com/patsypppe/slopaudit && cd slopaudit && make install` (or open it in [Codespaces](https://codespaces.new/patsypppe/slopaudit)) |
|
|
91
|
+
|
|
92
|
+
On macOS and most Linux systems the command is `python3`; `python: command not found` only means that.
|
|
93
|
+
On Windows use `py` instead of `python3`.
|
|
94
|
+
|
|
95
|
+
</details>
|
|
96
|
+
|
|
97
|
+
**In CI**, no install step is needed. Use the GitHub Action:
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
# .github/workflows/slopaudit.yml
|
|
101
|
+
name: slopaudit
|
|
102
|
+
on: [pull_request]
|
|
103
|
+
permissions: { contents: read, security-events: write }
|
|
104
|
+
jobs:
|
|
105
|
+
scan:
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@v4
|
|
109
|
+
- uses: patsypppe/slopaudit@v1.0.0
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Before every commit**, with [pre-commit](https://pre-commit.com):
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
# .pre-commit-config.yaml
|
|
116
|
+
repos:
|
|
117
|
+
- repo: https://github.com/patsypppe/slopaudit
|
|
118
|
+
rev: v1.0.0
|
|
119
|
+
hooks:
|
|
120
|
+
- id: slopaudit
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## See it work
|
|
124
|
+
|
|
125
|
+
```console
|
|
126
|
+
$ slopaudit scan examples/vulnerable_agent
|
|
127
|
+
vulnerable_agent/app.py
|
|
128
|
+
16 HIGH LLM-08 Tool `run_command` passes a model-chosen argument to subprocess.run() (shell)
|
|
129
|
+
↳ line 14: tool argument `command` is chosen by the model
|
|
130
|
+
↳ line 16: passed to subprocess.run()
|
|
131
|
+
21 HIGH LLM-01 Untrusted input reaches the system prompt of client.messages.create()
|
|
132
|
+
↳ line 20: untrusted input request.args
|
|
133
|
+
↳ line 20: stored in `topic`
|
|
134
|
+
↳ line 21: placed in the system prompt of client.messages.create()
|
|
135
|
+
27 CRITICAL LLM-02 Model output reaches eval() without validation
|
|
136
|
+
↳ line 21: model output from client.messages.create()
|
|
137
|
+
↳ line 21: stored in `reply`
|
|
138
|
+
↳ line 27: passed to eval()
|
|
139
|
+
30 MEDIUM INC-02 `parse_invoice` has no implementation (pass)
|
|
140
|
+
34 CRITICAL SEC-01 Hardcoded credential assignment (q9X$…(21 chars))
|
|
141
|
+
|
|
142
|
+
1 files scanned: 2 critical, 2 high, 1 medium
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Every flow finding shows the path the data took, so you can judge it in seconds. Each finding also has a
|
|
146
|
+
`fix:` line and a longer explanation: `slopaudit explain LLM-02`. No model is involved: slopaudit reads the
|
|
147
|
+
code's structure and follows values from where they come from to where they are used
|
|
148
|
+
([how it works](https://github.com/patsypppe/slopaudit/blob/main/docs/how-it-works.md)).
|
|
149
|
+
|
|
150
|
+
## Quickstart
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
slopaudit scan . # scan the current folder
|
|
154
|
+
slopaudit scan . --no-network # skip the PyPI package check
|
|
155
|
+
slopaudit scan --staged # only what you are about to commit
|
|
156
|
+
slopaudit scan . --format sarif -o out.sarif # for GitHub code scanning
|
|
157
|
+
slopaudit scan src --spec SPEC.md # check the code against a requirements file
|
|
158
|
+
slopaudit explain LLM-02 # why a rule exists, and how to fix it
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**From Python**, for example to check an assistant's answer before saving it:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
import slopaudit
|
|
165
|
+
|
|
166
|
+
blockers = [f for f in slopaudit.scan_source(answer) if f.severity >= slopaudit.Severity.HIGH]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
New to it? The [getting-started guide](https://github.com/patsypppe/slopaudit/blob/main/docs/getting-started.md) takes five minutes, and has a
|
|
170
|
+
ten-line test file that shows every kind of finding. Adopting on a big
|
|
171
|
+
codebase? Start with a [baseline](https://github.com/patsypppe/slopaudit/blob/main/docs/suppressing-findings.md#3-a-baseline-for-existing-code) so only new
|
|
172
|
+
problems fail.
|
|
173
|
+
|
|
174
|
+
## What it checks
|
|
175
|
+
|
|
176
|
+
| Family | Rules | Catches |
|
|
177
|
+
| --- | --- | --- |
|
|
178
|
+
| **LLM-app security** | LLM-01 to LLM-06, LLM-08, LLM-09, LLM-12 | Prompt-injection paths, model output reaching `eval`, shell, SQL, file paths and URLs, over-permissive agent tools, destructive tools with no confirmation, unbounded model calls |
|
|
179
|
+
| **Secrets** | SEC-01 | Hardcoded API keys, tokens and private keys (masked in all output) |
|
|
180
|
+
| **Hallucinated packages** | HAL-01 to HAL-04 | Imports that do not exist on PyPI, brand-new packages, typosquats, undeclared dependencies |
|
|
181
|
+
| **Unfinished code** | INC-01, INC-02, INC-04, INC-05, INC-06, INC-08 | Placeholder comments, stubs, swallowed exceptions, chat text pasted into files, many TODOs, truncated files |
|
|
182
|
+
| **Intent and consistency** | SPC-02, DRF-01 to DRF-03, REG-01, REG-02 | Unmet requirements, style drift from the rest of the repo, deleted or skipped tests |
|
|
183
|
+
|
|
184
|
+
The full list, with severity and fix advice for each rule, is the [rules reference](https://github.com/patsypppe/slopaudit/blob/main/docs/rules.md).
|
|
185
|
+
Beyond scanning, there are optional model-assisted commands: [`gen-tests`](https://github.com/patsypppe/slopaudit/blob/main/docs/beyond-scanning.md#generated-tests)
|
|
186
|
+
and [`fix`](https://github.com/patsypppe/slopaudit/blob/main/docs/beyond-scanning.md#repair-loop) (a dry run unless you pass `--apply`).
|
|
187
|
+
|
|
188
|
+
## How well does it work?
|
|
189
|
+
|
|
190
|
+
Three checks, each reproducible from this repository. None is a guarantee; the caveats matter.
|
|
191
|
+
|
|
192
|
+
**1. Labelled corpus** (`slopaudit bench`, 34 files). Every rule scores 1.00 precision; recall is 0.91,
|
|
193
|
+
with two labelled misses (a value that crosses a function boundary, or goes through `self`). The corpus is
|
|
194
|
+
small and was used to tune the rules, so treat it as a regression gate.
|
|
195
|
+
|
|
196
|
+
**2. Other scanners on that corpus** ([full report](https://github.com/patsypppe/slopaudit/blob/main/docs/benchmarks.md)): files flagged at medium
|
|
197
|
+
severity or higher, run as external programs.
|
|
198
|
+
|
|
199
|
+
| Tool | LLM-app security (15) | Secrets (1) | Incomplete code (4) | Hallucinated packages (1) | False alarms on 13 safe files |
|
|
200
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
201
|
+
| slopaudit | 12 | 1 | 3 | 1 | 0 |
|
|
202
|
+
| Bandit | 6 | 0 | 0 | 0 | 1 |
|
|
203
|
+
| Semgrep, public python rules | 8 | 0 | 2 | 0 | 2 |
|
|
204
|
+
| Semgrep, public ai rules | 12 | 0 | 0 | 0 | 6 |
|
|
205
|
+
| vibechck | 0 | 0 | 2 | 0 | 1 |
|
|
206
|
+
|
|
207
|
+
The corpus targets what slopaudit was built for, so it flatters slopaudit. Bandit and Semgrep are broader
|
|
208
|
+
tools not designed for these cases, and Semgrep's `ai` rules are SDK best-practice lints. Semgrep also
|
|
209
|
+
catches the two cross-function cases slopaudit misses, because it flags any dynamic `eval`.
|
|
210
|
+
|
|
211
|
+
**3. Mature packages as a false-positive control** ([report](https://github.com/patsypppe/slopaudit/blob/main/docs/real-world-check.md)): 1.5 million lines
|
|
212
|
+
across twelve well-reviewed packages, including the OpenAI, Anthropic, LangChain and LiteLLM SDKs.
|
|
213
|
+
**0 critical or high findings** after tuning. The first run had 122 critical findings and about 900 medium
|
|
214
|
+
ones; fixing them is in the [changelog](https://github.com/patsypppe/slopaudit/blob/main/CHANGELOG.md). About 25 medium and a few hundred low findings remain.
|
|
215
|
+
This measures noise only: those packages are not AI-generated.
|
|
216
|
+
|
|
217
|
+
## Honest limits
|
|
218
|
+
|
|
219
|
+
- **A clean scan is not proof of safety.** The flow rules follow values inside one function. They miss a
|
|
220
|
+
value returned from a helper and `eval`-ed elsewhere, and values stored on `self`
|
|
221
|
+
([how it works](https://github.com/patsypppe/slopaudit/blob/main/docs/how-it-works.md#what-it-cannot-see)).
|
|
222
|
+
- **Without a model, the spec check compares names and words.** It can show code exists, not that it behaves
|
|
223
|
+
correctly. In the demo it reports a requirement as met while the code does the opposite.
|
|
224
|
+
- **Experimental parts.** `scan --spec --llm`, `gen-tests`, `fix` and the Docker sandbox are tested against
|
|
225
|
+
local stand-ins, not live services, so they are outside the 1.0 stability promise
|
|
226
|
+
([what 1.0 promises](https://github.com/patsypppe/slopaudit/blob/main/docs/decisions/0002-what-1-0-promises.md)).
|
|
227
|
+
- **Python only.** JavaScript and TypeScript files are skipped, and the scan says so when it finds nothing to read.
|
|
228
|
+
- **Linux CI only.** Installing and running on macOS has been checked by hand; Windows is untested
|
|
229
|
+
([#6](https://github.com/patsypppe/slopaudit/issues/6)).
|
|
230
|
+
|
|
231
|
+
## Documentation
|
|
232
|
+
|
|
233
|
+
| | |
|
|
234
|
+
| --- | --- |
|
|
235
|
+
| [Getting started](https://github.com/patsypppe/slopaudit/blob/main/docs/getting-started.md) | Install, first scan, reading output |
|
|
236
|
+
| [Configuration](https://github.com/patsypppe/slopaudit/blob/main/docs/configuration.md) | Every `slopaudit.toml` setting |
|
|
237
|
+
| [CI integration](https://github.com/patsypppe/slopaudit/blob/main/docs/ci-integration.md) | GitHub Action, pre-commit, GitLab |
|
|
238
|
+
| [Suppressing findings](https://github.com/patsypppe/slopaudit/blob/main/docs/suppressing-findings.md) | Comments, baselines, ignores |
|
|
239
|
+
| [Beyond scanning](https://github.com/patsypppe/slopaudit/blob/main/docs/beyond-scanning.md) | Spec checks, generated tests, drift, regression, repair |
|
|
240
|
+
| [Python API](https://github.com/patsypppe/slopaudit/blob/main/docs/python-api.md) | Use it from your own code or agent |
|
|
241
|
+
| [Privacy and safety](https://github.com/patsypppe/slopaudit/blob/main/docs/privacy-and-safety.md) | What runs, what is sent, the sandbox |
|
|
242
|
+
| [How it works](https://github.com/patsypppe/slopaudit/blob/main/docs/how-it-works.md) | Pipeline and taint tracking |
|
|
243
|
+
| [FAQ and troubleshooting](https://github.com/patsypppe/slopaudit/blob/main/docs/faq.md) | Common questions and fixes |
|
|
244
|
+
| [All docs](https://github.com/patsypppe/slopaudit/blob/main/docs/README.md) | The full index |
|
|
245
|
+
|
|
246
|
+
## Contributing
|
|
247
|
+
|
|
248
|
+
Contributions are welcome: rules, false-positive reports, docs and tests. The most valuable thing you can
|
|
249
|
+
do is **report a false positive or a miss with the smallest code that shows it**; every confirmed report
|
|
250
|
+
becomes a regression test.
|
|
251
|
+
|
|
252
|
+
**Looking for something to work on?** The [contributor roadmap](https://github.com/patsypppe/slopaudit/issues/85)
|
|
253
|
+
lists every open issue by area and difficulty. Each one says why it matters, which files to change, and when
|
|
254
|
+
it is done:
|
|
255
|
+
|
|
256
|
+
| Start here | |
|
|
257
|
+
| --- | --- |
|
|
258
|
+
| [Good first issues](https://github.com/patsypppe/slopaudit/labels/good%20first%20issue) | Small and well-defined: aliases, output formats, docs, test samples |
|
|
259
|
+
| [Help wanted](https://github.com/patsypppe/slopaudit/labels/help%20wanted) | New rules and integrations |
|
|
260
|
+
| [Advanced](https://github.com/patsypppe/slopaudit/labels/advanced) | The flow tracker and bigger design questions; discuss before coding |
|
|
261
|
+
|
|
262
|
+
Comment on an issue before you start so nobody duplicates work. Setup takes one click in
|
|
263
|
+
[Codespaces](https://codespaces.new/patsypppe/slopaudit), or `make install` locally. Start with [CONTRIBUTING.md](https://github.com/patsypppe/slopaudit/blob/main/CONTRIBUTING.md) and
|
|
264
|
+
[writing a rule](https://github.com/patsypppe/slopaudit/blob/main/docs/writing-rules.md), and please follow the [code of conduct](https://github.com/patsypppe/slopaudit/blob/main/CODE_OF_CONDUCT.md).
|
|
265
|
+
Questions go in [Discussions or issues](https://github.com/patsypppe/slopaudit/blob/main/SUPPORT.md); security problems in
|
|
266
|
+
[SECURITY.md](https://github.com/patsypppe/slopaudit/blob/main/SECURITY.md).
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
[MIT](https://github.com/patsypppe/slopaudit/blob/main/LICENSE). slopaudit is independent work: it takes no code, rules, messages or structure from other
|
|
271
|
+
tools. The [clean-room record](https://github.com/patsypppe/slopaudit/blob/main/docs/clean-room.md) explains how, and why other scanners are only ever *run*,
|
|
272
|
+
never copied. Thanks to the authors of Bandit, Semgrep and vibechck for the prior art that made the
|
|
273
|
+
comparison possible.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# slopaudit
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/slopaudit/)
|
|
4
|
+
[](https://pypi.org/project/slopaudit/)
|
|
5
|
+
[](https://github.com/patsypppe/slopaudit/actions/workflows/ci.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://github.com/patsypppe/slopaudit/labels/good%20first%20issue)
|
|
8
|
+
|
|
9
|
+
**Check AI-written code before you trust it.** slopaudit is an open-source command-line tool for Python
|
|
10
|
+
that finds the problems AI assistants and LLM-powered apps tend to introduce, and that general scanners
|
|
11
|
+
were not built to look for.
|
|
12
|
+
|
|
13
|
+
- **Is it safe?** Does model output reach `eval`, a shell or a SQL query? Does untrusted input end up
|
|
14
|
+
in a system prompt? Does an agent tool hand the model a shell?
|
|
15
|
+
- **Is it real?** Does that imported package exist, or is it invented (or one typo from a popular one)?
|
|
16
|
+
- **Is it finished?** Stubs, "rest of code here" comments, swallowed errors, truncated files.
|
|
17
|
+
- **Is it what you asked for?** Does the code meet each requirement in your spec, and did the change
|
|
18
|
+
delete or weaken tests to get there?
|
|
19
|
+
|
|
20
|
+
It runs on your machine, never executes the code it scans, needs no account or API key, and has no telemetry.
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
You need Python 3.10 or newer. Pick one:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pipx install slopaudit # recommended: an isolated command-line tool
|
|
28
|
+
uv tool install slopaudit # same idea, if you use uv
|
|
29
|
+
python3 -m pip install slopaudit # inside a virtual environment
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Then check it works:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
slopaudit --version
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Just try it, without installing anything:**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pipx run slopaudit scan . # or: uvx slopaudit scan .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary>Don't have pipx, upgrading, uninstalling, or installing from source</summary>
|
|
46
|
+
|
|
47
|
+
| I want to | Run |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| Get pipx on macOS | `brew install pipx && pipx ensurepath` |
|
|
50
|
+
| Get pipx elsewhere | `python3 -m pip install --user pipx && python3 -m pipx ensurepath` |
|
|
51
|
+
| Upgrade | `pipx upgrade slopaudit`, or `python3 -m pip install --upgrade slopaudit` |
|
|
52
|
+
| Uninstall | `pipx uninstall slopaudit`, or `python3 -m pip uninstall slopaudit` |
|
|
53
|
+
| Install a specific version | `pipx install slopaudit==1.0.0` |
|
|
54
|
+
| Install the latest unreleased code | `pipx install git+https://github.com/patsypppe/slopaudit` |
|
|
55
|
+
| Hack on it | `git clone https://github.com/patsypppe/slopaudit && cd slopaudit && make install` (or open it in [Codespaces](https://codespaces.new/patsypppe/slopaudit)) |
|
|
56
|
+
|
|
57
|
+
On macOS and most Linux systems the command is `python3`; `python: command not found` only means that.
|
|
58
|
+
On Windows use `py` instead of `python3`.
|
|
59
|
+
|
|
60
|
+
</details>
|
|
61
|
+
|
|
62
|
+
**In CI**, no install step is needed. Use the GitHub Action:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
# .github/workflows/slopaudit.yml
|
|
66
|
+
name: slopaudit
|
|
67
|
+
on: [pull_request]
|
|
68
|
+
permissions: { contents: read, security-events: write }
|
|
69
|
+
jobs:
|
|
70
|
+
scan:
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
- uses: patsypppe/slopaudit@v1.0.0
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Before every commit**, with [pre-commit](https://pre-commit.com):
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
# .pre-commit-config.yaml
|
|
81
|
+
repos:
|
|
82
|
+
- repo: https://github.com/patsypppe/slopaudit
|
|
83
|
+
rev: v1.0.0
|
|
84
|
+
hooks:
|
|
85
|
+
- id: slopaudit
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## See it work
|
|
89
|
+
|
|
90
|
+
```console
|
|
91
|
+
$ slopaudit scan examples/vulnerable_agent
|
|
92
|
+
vulnerable_agent/app.py
|
|
93
|
+
16 HIGH LLM-08 Tool `run_command` passes a model-chosen argument to subprocess.run() (shell)
|
|
94
|
+
↳ line 14: tool argument `command` is chosen by the model
|
|
95
|
+
↳ line 16: passed to subprocess.run()
|
|
96
|
+
21 HIGH LLM-01 Untrusted input reaches the system prompt of client.messages.create()
|
|
97
|
+
↳ line 20: untrusted input request.args
|
|
98
|
+
↳ line 20: stored in `topic`
|
|
99
|
+
↳ line 21: placed in the system prompt of client.messages.create()
|
|
100
|
+
27 CRITICAL LLM-02 Model output reaches eval() without validation
|
|
101
|
+
↳ line 21: model output from client.messages.create()
|
|
102
|
+
↳ line 21: stored in `reply`
|
|
103
|
+
↳ line 27: passed to eval()
|
|
104
|
+
30 MEDIUM INC-02 `parse_invoice` has no implementation (pass)
|
|
105
|
+
34 CRITICAL SEC-01 Hardcoded credential assignment (q9X$…(21 chars))
|
|
106
|
+
|
|
107
|
+
1 files scanned: 2 critical, 2 high, 1 medium
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Every flow finding shows the path the data took, so you can judge it in seconds. Each finding also has a
|
|
111
|
+
`fix:` line and a longer explanation: `slopaudit explain LLM-02`. No model is involved: slopaudit reads the
|
|
112
|
+
code's structure and follows values from where they come from to where they are used
|
|
113
|
+
([how it works](docs/how-it-works.md)).
|
|
114
|
+
|
|
115
|
+
## Quickstart
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
slopaudit scan . # scan the current folder
|
|
119
|
+
slopaudit scan . --no-network # skip the PyPI package check
|
|
120
|
+
slopaudit scan --staged # only what you are about to commit
|
|
121
|
+
slopaudit scan . --format sarif -o out.sarif # for GitHub code scanning
|
|
122
|
+
slopaudit scan src --spec SPEC.md # check the code against a requirements file
|
|
123
|
+
slopaudit explain LLM-02 # why a rule exists, and how to fix it
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**From Python**, for example to check an assistant's answer before saving it:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
import slopaudit
|
|
130
|
+
|
|
131
|
+
blockers = [f for f in slopaudit.scan_source(answer) if f.severity >= slopaudit.Severity.HIGH]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
New to it? The [getting-started guide](docs/getting-started.md) takes five minutes, and has a
|
|
135
|
+
ten-line test file that shows every kind of finding. Adopting on a big
|
|
136
|
+
codebase? Start with a [baseline](docs/suppressing-findings.md#3-a-baseline-for-existing-code) so only new
|
|
137
|
+
problems fail.
|
|
138
|
+
|
|
139
|
+
## What it checks
|
|
140
|
+
|
|
141
|
+
| Family | Rules | Catches |
|
|
142
|
+
| --- | --- | --- |
|
|
143
|
+
| **LLM-app security** | LLM-01 to LLM-06, LLM-08, LLM-09, LLM-12 | Prompt-injection paths, model output reaching `eval`, shell, SQL, file paths and URLs, over-permissive agent tools, destructive tools with no confirmation, unbounded model calls |
|
|
144
|
+
| **Secrets** | SEC-01 | Hardcoded API keys, tokens and private keys (masked in all output) |
|
|
145
|
+
| **Hallucinated packages** | HAL-01 to HAL-04 | Imports that do not exist on PyPI, brand-new packages, typosquats, undeclared dependencies |
|
|
146
|
+
| **Unfinished code** | INC-01, INC-02, INC-04, INC-05, INC-06, INC-08 | Placeholder comments, stubs, swallowed exceptions, chat text pasted into files, many TODOs, truncated files |
|
|
147
|
+
| **Intent and consistency** | SPC-02, DRF-01 to DRF-03, REG-01, REG-02 | Unmet requirements, style drift from the rest of the repo, deleted or skipped tests |
|
|
148
|
+
|
|
149
|
+
The full list, with severity and fix advice for each rule, is the [rules reference](docs/rules.md).
|
|
150
|
+
Beyond scanning, there are optional model-assisted commands: [`gen-tests`](docs/beyond-scanning.md#generated-tests)
|
|
151
|
+
and [`fix`](docs/beyond-scanning.md#repair-loop) (a dry run unless you pass `--apply`).
|
|
152
|
+
|
|
153
|
+
## How well does it work?
|
|
154
|
+
|
|
155
|
+
Three checks, each reproducible from this repository. None is a guarantee; the caveats matter.
|
|
156
|
+
|
|
157
|
+
**1. Labelled corpus** (`slopaudit bench`, 34 files). Every rule scores 1.00 precision; recall is 0.91,
|
|
158
|
+
with two labelled misses (a value that crosses a function boundary, or goes through `self`). The corpus is
|
|
159
|
+
small and was used to tune the rules, so treat it as a regression gate.
|
|
160
|
+
|
|
161
|
+
**2. Other scanners on that corpus** ([full report](docs/benchmarks.md)): files flagged at medium
|
|
162
|
+
severity or higher, run as external programs.
|
|
163
|
+
|
|
164
|
+
| Tool | LLM-app security (15) | Secrets (1) | Incomplete code (4) | Hallucinated packages (1) | False alarms on 13 safe files |
|
|
165
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
166
|
+
| slopaudit | 12 | 1 | 3 | 1 | 0 |
|
|
167
|
+
| Bandit | 6 | 0 | 0 | 0 | 1 |
|
|
168
|
+
| Semgrep, public python rules | 8 | 0 | 2 | 0 | 2 |
|
|
169
|
+
| Semgrep, public ai rules | 12 | 0 | 0 | 0 | 6 |
|
|
170
|
+
| vibechck | 0 | 0 | 2 | 0 | 1 |
|
|
171
|
+
|
|
172
|
+
The corpus targets what slopaudit was built for, so it flatters slopaudit. Bandit and Semgrep are broader
|
|
173
|
+
tools not designed for these cases, and Semgrep's `ai` rules are SDK best-practice lints. Semgrep also
|
|
174
|
+
catches the two cross-function cases slopaudit misses, because it flags any dynamic `eval`.
|
|
175
|
+
|
|
176
|
+
**3. Mature packages as a false-positive control** ([report](docs/real-world-check.md)): 1.5 million lines
|
|
177
|
+
across twelve well-reviewed packages, including the OpenAI, Anthropic, LangChain and LiteLLM SDKs.
|
|
178
|
+
**0 critical or high findings** after tuning. The first run had 122 critical findings and about 900 medium
|
|
179
|
+
ones; fixing them is in the [changelog](CHANGELOG.md). About 25 medium and a few hundred low findings remain.
|
|
180
|
+
This measures noise only: those packages are not AI-generated.
|
|
181
|
+
|
|
182
|
+
## Honest limits
|
|
183
|
+
|
|
184
|
+
- **A clean scan is not proof of safety.** The flow rules follow values inside one function. They miss a
|
|
185
|
+
value returned from a helper and `eval`-ed elsewhere, and values stored on `self`
|
|
186
|
+
([how it works](docs/how-it-works.md#what-it-cannot-see)).
|
|
187
|
+
- **Without a model, the spec check compares names and words.** It can show code exists, not that it behaves
|
|
188
|
+
correctly. In the demo it reports a requirement as met while the code does the opposite.
|
|
189
|
+
- **Experimental parts.** `scan --spec --llm`, `gen-tests`, `fix` and the Docker sandbox are tested against
|
|
190
|
+
local stand-ins, not live services, so they are outside the 1.0 stability promise
|
|
191
|
+
([what 1.0 promises](docs/decisions/0002-what-1-0-promises.md)).
|
|
192
|
+
- **Python only.** JavaScript and TypeScript files are skipped, and the scan says so when it finds nothing to read.
|
|
193
|
+
- **Linux CI only.** Installing and running on macOS has been checked by hand; Windows is untested
|
|
194
|
+
([#6](https://github.com/patsypppe/slopaudit/issues/6)).
|
|
195
|
+
|
|
196
|
+
## Documentation
|
|
197
|
+
|
|
198
|
+
| | |
|
|
199
|
+
| --- | --- |
|
|
200
|
+
| [Getting started](docs/getting-started.md) | Install, first scan, reading output |
|
|
201
|
+
| [Configuration](docs/configuration.md) | Every `slopaudit.toml` setting |
|
|
202
|
+
| [CI integration](docs/ci-integration.md) | GitHub Action, pre-commit, GitLab |
|
|
203
|
+
| [Suppressing findings](docs/suppressing-findings.md) | Comments, baselines, ignores |
|
|
204
|
+
| [Beyond scanning](docs/beyond-scanning.md) | Spec checks, generated tests, drift, regression, repair |
|
|
205
|
+
| [Python API](docs/python-api.md) | Use it from your own code or agent |
|
|
206
|
+
| [Privacy and safety](docs/privacy-and-safety.md) | What runs, what is sent, the sandbox |
|
|
207
|
+
| [How it works](docs/how-it-works.md) | Pipeline and taint tracking |
|
|
208
|
+
| [FAQ and troubleshooting](docs/faq.md) | Common questions and fixes |
|
|
209
|
+
| [All docs](docs/README.md) | The full index |
|
|
210
|
+
|
|
211
|
+
## Contributing
|
|
212
|
+
|
|
213
|
+
Contributions are welcome: rules, false-positive reports, docs and tests. The most valuable thing you can
|
|
214
|
+
do is **report a false positive or a miss with the smallest code that shows it**; every confirmed report
|
|
215
|
+
becomes a regression test.
|
|
216
|
+
|
|
217
|
+
**Looking for something to work on?** The [contributor roadmap](https://github.com/patsypppe/slopaudit/issues/85)
|
|
218
|
+
lists every open issue by area and difficulty. Each one says why it matters, which files to change, and when
|
|
219
|
+
it is done:
|
|
220
|
+
|
|
221
|
+
| Start here | |
|
|
222
|
+
| --- | --- |
|
|
223
|
+
| [Good first issues](https://github.com/patsypppe/slopaudit/labels/good%20first%20issue) | Small and well-defined: aliases, output formats, docs, test samples |
|
|
224
|
+
| [Help wanted](https://github.com/patsypppe/slopaudit/labels/help%20wanted) | New rules and integrations |
|
|
225
|
+
| [Advanced](https://github.com/patsypppe/slopaudit/labels/advanced) | The flow tracker and bigger design questions; discuss before coding |
|
|
226
|
+
|
|
227
|
+
Comment on an issue before you start so nobody duplicates work. Setup takes one click in
|
|
228
|
+
[Codespaces](https://codespaces.new/patsypppe/slopaudit), or `make install` locally. Start with [CONTRIBUTING.md](CONTRIBUTING.md) and
|
|
229
|
+
[writing a rule](docs/writing-rules.md), and please follow the [code of conduct](CODE_OF_CONDUCT.md).
|
|
230
|
+
Questions go in [Discussions or issues](SUPPORT.md); security problems in
|
|
231
|
+
[SECURITY.md](SECURITY.md).
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
[MIT](LICENSE). slopaudit is independent work: it takes no code, rules, messages or structure from other
|
|
236
|
+
tools. The [clean-room record](docs/clean-room.md) explains how, and why other scanners are only ever *run*,
|
|
237
|
+
never copied. Thanks to the authors of Bandit, Semgrep and vibechck for the prior art that made the
|
|
238
|
+
comparison possible.
|