Skip to main content
QWED Security is a GitHub App that performs deterministic security verification on your pull requests — not another AI code reviewer. A 20-engine Evidence → Context → Policy pipeline scans every PR, emits a machine-readable Verification Context v1.0 with a proof-bound verdict, and fails the check run unless admission is ADMIT. Set it as a required check and merges gate on it.
Unlike AI reviewers that “guess,” QWED Security is deterministic. No LLM, no probabilistic pass logic — unknown states never pass silently.

How it works

  1. A developer opens or updates a pull request
  2. GitHub delivers a webhook event; the signature is verified (HMAC-SHA256)
  3. The app creates a Check Run (“QWED Security”) on the PR
  4. The pipeline runs: evidence extraction → context classification → policy
  5. A Verification Context v1.0 is emitted: verdict (VERIFIED / UNVERIFIABLE / BLOCKED), admission (ADMIT / DENY), and a SHA-256 proof_ref binding the decision to the exact scan evidence and rule-set version
  6. The check run concludes and the full Verification Context is published as a collapsible PR comment for audit

The admission contract — what a green check proves

When the QWED Security check passes and you have it configured as a required check, a mergeable PR proves:
  • Full scan — every file in the PR was scanned by the complete engine set. If the PR exceeds the 300-file cap, the scan is demoted to UNVERIFIABLE (DENY) — a capped scan can never be ADMIT (fail-closed)
  • Zero new blocking findings — admission is computed from new findings only; a PR that introduces no new BLOCK/WARNING findings gets VERIFIED (ADMIT)
  • Pre-existing debt never blocks — findings that already exist on the base branch are reported (and listed in the PR comment) but do not affect admission. QWED blocks only what the PR introduces
  • Rule-set bound in proof — the rule-set version is part of the SHA-256 proof_ref, so the bound under which the verdict was computed is part of the proof
  • Fail-closed — unknown context, unparseable manifests, missing evidence, or infrastructure failure never produce a pass. UNVERIFIABLE and BLOCKED both deny admission
A green check means “VERIFIED against the QWED rule set”, not “proven secure in absolute terms”. The bound is explicit and proof-bound — that is the contract.

What QWED Security catches

Math and logic verification (SymPy / Z3) is available through the QWED engine suite and the QWED GitHub Action; the GitHub App focuses on the security surface above.

Check run output

Every scan also posts the full Verification Context as a collapsible PR comment:
The VC is schema-validated, machine-readable, and suitable for downstream compliance pipelines.

Cryptographic attestation

VERIFIED verdicts are signed (RS256) — attestation is the trust gate, not a cosmetic badge:
  • The signed JWT is delivered inside the Verification Context at context.proof.configuration.attestation_token
  • Third parties verify it against the app’s JWKS at /.well-known/jwks.json (or the operator-configured QWED_ATTESTATION_JWKS_URL): fetch the JWKS, select the key by kid, verify the RS256 signature, then check the proof binding in the VC
  • Rotated signing keys stay published for the token lifetime plus skew, so unexpired tokens remain verifiable across key rotation
  • Operators can set QWED_REQUIRE_ATTESTATION=true to fail closed whenever no signing key is configured — an unsigned VERIFIED is never admitted
The SDK-level ES256 attestation flow for the verification API is documented separately under Cryptographic attestations. The GitHub App uses the RS256 flow described here.

Configuration (.qwed.yml)

QWED Security works out of the box with zero configuration. Repositories can tune policy with a .qwed.yml, loaded from the base branch — never the PR head, so a PR cannot weaken its own scan:
  • diff_aware (default true) — admission gating considers new findings only; release-boundary findings always apply
  • treat_unknown_as_block — unknown context resolves to BLOCK (fail-closed)
  • Suppressions — maintainer-controlled, with separator-aware path= globs: * and ? never cross / (path=tests/* stays one level deep), ** spans directories (path=tests/** covers everything under tests/, and **/foo.py also matches a root-level foo.py), and the pattern must match the whole path. Malformed globs are rejected when the config loads
  • Inline suppression# qwed-ignore or scoped # qwed-ignore: rule-id on the offending line

Operational limits

Privacy and security

  • No code storage — files are analyzed in memory and discarded
  • Webhook verification — HMAC-SHA256 signature validation on every event
  • JWT authentication — short-lived installation tokens (10-minute expiry)
  • Base-branch policy.qwed.yml is read from the base branch, never the PR head
  • Fail-closed everywhere — unknown states deny admission; infrastructure failures never pass silently
  • Suspended installations — token minting stops the moment a suspension webhook is processed, across all workers (and across instances when the shared backend is enabled)

Permissions

The app never writes to your code, branches, or settings.

Plans

Install from the GitHub Marketplace listing.

Self-hosting and multi-instance deployments

The hosted app runs the default configuration. Self-hosters should note:
  • Coordination state (dedup, in-flight claims, rate windows, revocations) is file-locked and shared by all workers of one instance by default
  • For Cloud Run scale-out across instances, an optional Firestore backend shares that state across every worker and every instance; scan claims fail closed on any backend error
  • See the self-hosting guide for deployment details

QWED Security app vs GitHub Action

The GitHub App provides automatic, zero-config PR security gating. The GitHub Action provides configurable verification within your CI/CD pipeline. They complement each other.

Support