refutescan
A two-LLM, refute-first agentic source-code vulnerability scanner.
Most LLM code scanners have the same problem: they hallucinate. Point a model at a repo and it will confidently report SQL injection in a parameterized query and SSRF behind an allowlist. The noise buries the real bugs.
refutescan splits the job across two models:
- Navigate (wide net). A fast tool-calling model explores the repo with
read-only tools (
list_dir/read_file/grep), traces untrusted input toward dangerous sinks, and records candidate findings. It's cheap and it over-reports on purpose. - Refute (skeptic). A stronger model re-reads the actual code slice around each candidate from disk — ground truth, not the navigator's paraphrase — and is prompted to refute it. Sanitized? Parameterized? Gated by auth? Not reachable? It's culled, with the reason kept. Only what survives is reported.
You get the recall of an agentic scanner without the false-positive flood.
Every scan runs jailed in an ephemeral docker sandbox by default: git URLs are cloned inside a container (no host mounts), then audited in a second container with no network, read-only, no capabilities, non-root, and only the repo mounted. A hostile repo (malicious submodule, hook, symlink) touches neither your filesystem nor the network.
Install
pip install refutescan # core kernel
pip install 'refutescan[openai]' # + the OpenAI adapter for the CLI
For sandboxed scans (recommended), build the jail image once:
refutescan-build-sandbox
(Requires Docker. Without it, refutescan falls back to a guarded in-process scan.)
CLI
export OPENAI_API_KEY=sk-...
refutescan https://github.com/owner/repo
refutescan ./path/to/local/repo --judge-model gpt-4o --json
Exit code is non-zero when confirmed findings exist, so it drops straight into CI.
Library
from refutescan import scan, ScanConfig
from refutescan.adapters import openai_navigator_factory, openai_judge_factory
result = scan(
"https://github.com/owner/repo",
navigator_factory=openai_navigator_factory("gpt-4o-mini"),
judge_factory=openai_judge_factory("gpt-4o"),
config=ScanConfig(sandbox="docker"), # auto | docker | inprocess
progress=lambda phase: print(phase),
)
for f in result.findings:
print(f["severity"], f["title"], f"{f['file']}:{f['line']}")
print(" ", f["reasoning"])
print(" fix:", f["recommendation"])
result.culled holds the refuted candidates with the reason each was rejected —
useful for tuning and for trusting the tool.
Bring your own model
refutescan never imports a provider SDK in its core. Pass any LangChain-style chat model through two factories:
navigator_factory() -> chat_model— supports.bind_tools(...)+.invoke(...)judge_factory() -> judge(prompt, schema) -> instance— one structured-output call
So a local model (vLLM/Ollama via the OpenAI shim, --base-url), Anthropic,
Azure OpenAI, or a corporate gateway all work — wire the factory and go. See
refutescan/providers.py.
What it is and isn't
- Is: an agentic, read-only, false-positive-resistant first-pass auditor for the common web-app vuln classes (injection, authz/IDOR, SSRF, path traversal, unsafe deserialization, hardcoded secrets, weak crypto, XSS, auth flaws).
- Isn't: a replacement for a full SAST suite, a proof of exploitability, or a patch generator. It finds and explains; a human confirms and fixes.
License
MIT.
Metadata
Release files for refutescan 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| refutescan-0.1.0.tar.gz | 29.7 kB | With provenance | Details for refutescan-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| refutescan-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for refutescan-0.1.0-py3-none-any.whl |
Total release size: 62.1 kB
Release files / refutescan-0.1.0.tar.gz
| Download URL | refutescan-0.1.0.tar.gz |
|---|---|
| Size | 29.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
255aa752429007c3f2704b77e4891a9dacf904f970a24cb70ae78838c82134c0
|
|
BLAKE2b-256 checksum How to use checksums |
f82f111671f5d92650751e68d5e93134d02116af1359da0e638924086af71b1c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.
Transparency logRelease files / refutescan-0.1.0-py3-none-any.whl
| Download URL | refutescan-0.1.0-py3-none-any.whl |
|---|---|
| Size | 32.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
17de1e7504616656df3866e20adae3fdd7d4c0b1d8583a9d643f9164c46a6f24
|
|
BLAKE2b-256 checksum How to use checksums |
2d6d0192afff4bad893f063a610d1fcee48e7653631ecdda4ce2a6fb72df97ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.
Transparency logSecurity for refutescan 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for refutescan-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.