parryai.dev
Solutions

One verdict from every engine, reconciled by fingerprint.

Running multiple security scanners side by side produces overlapping findings, drift across reruns, and a triage channel the team learns to ignore. Parry collapses every engine's output into one finding per real issue, with a stable lifecycle that survives refactors.

What goes wrong without reconciliation

The four failure modes of a multi-scanner stack

  • Same issue, three findings

    Your secrets scanner flags an AWS key on line 42. The container scanner's secrets module flags the same key. A regex post-commit hook flags it again. Three rows, one underlying secret. Multiply across a 200-file diff and a security review becomes a deduplication exercise.

  • The lifecycle drifts on every rerun

    A scanner that re-asks every question on every run is not a security tool — it's a notification firehose. Without lifecycle, a fixed finding looks the same as a new one, a suppression evaporates after a refactor, and the team learns to ignore the channel.

  • Triage decisions don't survive code changes

    You marked a SAST finding as 'won't fix — false positive on a test fixture' three months ago. Someone renamed the file. The next scan resurrects the finding under a new ID and you triage it again. And again.

  • No way to prove a scanner ran

    Procurement asks: 'Do you scan for secrets, SAST, deps, IaC, containers?' Yes. 'Show me.' You have five tool logs, three retention windows, and no single artifact. The reconciled report is the artifact.

How reconciliation actually works

Five steps, one verdict

  1. 01

    Run every engine in its own sandbox

    Each scanner runs in an isolated container — no network egress by default, read-only mount of your code, bounded CPU and memory, hard time limit. A bug in one engine cannot affect the rest of the scan.

  2. 02

    Normalize output into a common shape

    Every engine speaks a different dialect — SARIF, JSON, custom YAML. Adapters translate each engine's output into one schema: rule id, severity, file, line, snippet. Adapters are small, fixture-tested, and replaceable.

  3. 03

    Compute a stable fingerprint per finding

    Fingerprint = sha256(tool | rule_id | file | trimmed_snippet). The same secret detected by two engines collapses to one fingerprint. A rename or whitespace edit does not perturb it. A real new finding has a new fingerprint.

  4. 04

    Reconcile against the previous scan

    New fingerprint → open. Previously-open + present this scan → still open. Previously-open + absent this scan → fixed. Suppressed and accepted states are preserved. The transition table is one file. No replication elsewhere.

  5. 05

    Emit one Check Run, one drawer, one SBOM

    The reconciled view lands on the GitHub pull request as one Check Run, in the Parry web app as one finding drawer with provenance back to every engine that flagged it, and as one CycloneDX SBOM for procurement.

What we reconcile across

The engines under the hood

Open, auditable, swappable. Pinned by digest, updated on our cadence. You can verify what ran and how.

ScopeEngineHow we use it
SecretsOpen-source secrets scanning + live provider-API validationLive-verified — a regex match against an inactive token does not become a finding.
SASTOpen-source static analysisReadable rule format. Reachability filtering before the finding is emitted.
DependenciesOpen-source dependency scanning against the public CVE / OSV feedThe same feed major code hosts, registries, and language ecosystems publish to. Reachable-only CVEs by call-graph.
ContainersOpen-source layer-by-layer image scanningEvery layer, including the base image. Same finding feed as the rest.
IaCTwo reconciled open-source enginesOne for Terraform / CloudFormation, one for Kubernetes manifests. Output reconciled before it reaches you.
Supply-chain postureIndustry-standard open posture benchmarkPer-repo grade. Reproducible, published, not a vendor-private risk score.
DASTOpen-source baseline scanSpider-and-passive against a staging URL you supply. Same finding feed.
Custom policyOpen policy engineDrop a policy file in policy/ — runs on every push, gates the merge.
What this is not

Things we don't pretend to do

  • We do not invent a proprietary scanner

    Every vendor with a proprietary-engine marketing line is asking you to trust a black box. We run the engines the security community already runs in production. The differentiation is reconciliation, lifecycle, and the verdict on the commit — not a rebranded rule pack.

  • We do not replace human review

    A scanner without lifecycle is a notification firehose; a scanner with reconciliation and AI Review is a triage assistant. The merge decision is still yours.

  • We do not score 'risk' with a hidden model

    Severity comes from the engine that flagged the finding, mapped to SARIF levels. Reachability comes from call-graph analysis you can re-run. We don't multiply numbers together and call the product a risk score.

One Check Run per push. Lifecycle that survives the refactor.

Free for public repositories. Flat per-org for private. No per-committer billing.