Security analysis that's reproducible by design. Every finding witnessed, every result attested.
Every deterministic-core result is a function of source, a version-pinned spec set, and a pinned environment. Re-run the scan and get the same SARIF, byte for byte. The Attestor fails the build if it doesn't.
Scanipy reuses the CPG of the parent commit and replays the analysis on the affected slice. Closed-world commits rebuild in time proportional to the semantic delta, not the size of the repository.
Every result ships with a signed chain: source commit → snapshot digest → spec version → env digest → taint witness → rule id. Auditors verify findings without re-running the analysis.
SARIF · sha256:c1b…a89SARIF · sha256:c1b…a89SARIF · sha256:c1b…a89Three runs, three weeks apart. Same hash.
parent: 7f3a2c9Eight files of work for a fourteen-thousand-file repo.
Engineering teams stop trusting tools that change their minds. Scanipy is built so you don't have to.
GitHub, GitLab, Bitbucket, Azure DevOps: same conformance suite, same fingerprint across providers.
Rename a variable, extract a method, move a file. The slice fingerprint survives. No false-new on cosmetic changes.
New detection rules clear a precision floor with mathematically defensible guarantees, even under unbounded re-evaluation.
Scanipy reuses the parent commit's analysis graph and replays only the affected slice. PRs scan in seconds, not minutes.
Every finding declares its origin. Deterministic-core results carry a reproducibility theorem; oracle-passthrough results carry a measured rate. Never both, never blurred.
Language models triage and propose new specs. They never delete a finding, never sit on the detection path. Determinism is non-negotiable.
Every result links back to the exact path through your code that produced it. Hand the witness to anyone (auditor, engineer, ticket bot) and they can verify without re-running the scan.
# app/views/uploads.py from flask import request, send_file import os UPLOAD_DIR = "/var/uploads" def download(req): name = req.args["file"] path = os.path.join(UPLOAD_DIR, name) return send_file(path)
req.args["file"] flows into os.path.join without a normalisation check.
“It's the first SAST result our auditors stopped arguing with. The finding either reproduces or it doesn't. Done.”
Free for open-source. Free for the first repo. The auditor's edition is paid. Never the result.