Installation
ComplyTest is distributed as a single npm package. It runs anywhere Node 22+ is available — local machines, GitHub-hosted runners, GitLab CI, or self-hosted CI agents.
Run without installing
The fastest way to try ComplyTest. npx
fetches the latest release, runs the scan, and cleans up.
$ npx complytest scan
https://your-site.com
npx [email protected] so reports stay byte-stable across runs.
Install globally
Skip the network round-trip on subsequent runs. Choose the manager your team uses.
$ npm install -g complytest $ pnpm add -g complytest $ bun add -g complytest
The scan command
Runs all 69 rules against the target URL. Returns exit 0 (pass), 1 (warnings),
or 2 (critical failures) — adjustable with --fail-on.
complytest scan <url> command Scan a URL with the full rule set and write reports.
| Flag | Default | Description |
|---|---|---|
-o, --output <dir> | reports | Destination directory for generated report files. |
--format <formats> | json | Output formats (comma-separated): html, json, csv, sarif, pdf, complicer. |
--timeout <ms> | 30000 | Per-page timeout in milliseconds. |
--viewport <preset> | desktop | Viewport preset: desktop (1366×900) or mobile (375×812). |
--fail-on <pred> | — | Exit non-zero on: critical, score<N, rule:pattern, eaa. |
--custom-rules <dir> | — | Directory of custom JSON/YAML rule files (IDs must start with custom.). |
--jurisdiction <id> | — | Apply jurisdiction-specific rule overlays (e.g. eaa). |
--api-key <key> | — | API key for auto-upload to Complicer. |
--no-upload | — | Disable auto-upload, even if a key is configured. |
The run command
Full compliance audit driven by complytest.config.json. Supports baselines, SLOs, ownership routing, evidence signing, and Sigstore
attestation.
complytest run command Config-driven scan with baselines, ownership, SLOs, and signed evidence.
| Flag | Default | Description |
|---|---|---|
-o, --output <dir> | reports | Output directory. |
--format <formats> | html,json | Report formats to emit. |
--baseline <file> | — | Apply a baseline JSON of known issues to suppress. |
--write-baseline <file> | — | Write a baseline from the current failures. |
--quarantine <file> | — | Temporary ignore rules from a quarantine JSON. |
--flaky-window <n> | — | Window of previous runs used for flakiness detection. |
--slo <file> | — | SLO configuration for compliance guardrails. |
--owners <file> | — | Owner mapping for failure attribution. |
--jira | — | Create Jira tickets on SLO breaches. |
--attest | — | Generate an evidence manifest with attestation. |
--sigstore | — | Use cosign to sign / verify the manifest. |
--jurisdictions <csv> | — | Comma-separated policy IDs (EU, US). |
The diff, validate and digest commands
complytest diff <runA> <runB>
compares two scan results to track regressions over time.
complytest validate <config>
checks a config file without scanning.
complytest digest
produces a weekly compliance digest with optional Slack posting.
Rules: Consent & Privacy
19 rules19 rules covering GDPR consent, ePrivacy cookie handling, Google Consent Mode v2, and DSA dark-pattern detection.
| Rule ID | Severity | Standard | What it checks |
|---|---|---|---|
consent.reject_first_layer.present | critical | EDPB 03/2022 | First-layer banner must offer equally prominent Accept and Reject. |
consent.cookies_before_consent | critical | GDPR Art 7 | No non-essential cookies set before explicit consent. |
consent.third_party_cookies | critical | ePrivacy | Third-party tracking cookies require explicit consent. |
consent.cookie_expiration | major | EDPB | Non-essential cookies must not exceed 12-month expiration. |
consent.banner_language_clear | major | GDPR Art 12 | Banner text must use clear, plain language. |
consent.withdrawal_mechanism | major | GDPR Art 7(3) | Users must be able to withdraw consent easily. |
consent.cookie_descriptions | major | EDPB 03/2022 | Banner must provide clear descriptions of cookie purposes. |
consent.no_cookie_walls | critical | EDPB 05/2020 | Sites must not make access conditional on accepting cookies. |
consent.visual_parity | major | EDPB 03/2022 | Accept and Reject buttons must have equal visual prominence. |
consent.google_consent_mode | critical | Google CM v2 | Google Consent Mode v2 mandatory for Google services in EEA. |
consent.effectiveness | critical | ePrivacy | After declining consent, no tracking requests should fire. |
consent.privacy_sandbox_disclosure | major | EDPB | Privacy Sandbox APIs require transparent disclosure. |
consent.granular_controls | critical | EDPB 03/2022 | Consent must offer granular per-purpose controls. |
consent.partial_consent | critical | GDPR Art 7 | Partial consent must be respected per selected purposes. |
consent.tier_separation | major | TCF 2.2 | Consent tiers must maintain strict cookie category separation. |
consent.dsa_preticked_checkboxes | critical | DSA Art 25 | Consent checkboxes must not be pre-selected. |
consent.dsa_confirmation_shaming | major | DSA Art 25 | Reject option must not use manipulative or shaming language. |
consent.dsa_fake_urgency | major | DSA Art 25 | Banners must not create false urgency to accept. |
consent.withdrawal_ineffective | critical | GDPR Art 7(3) | After withdrawing consent, tracking must actually stop. |
Rules: Accessibility
21 rules21 rules including all 9 new WCAG 2.2 success criteria and the existing WCAG 2.1 baseline.
| Rule ID | Severity | Standard | What it checks |
|---|---|---|---|
accessibility.focus_visible | major | WCAG 2.4.7 | Interactive elements must have a visible focus indicator. |
accessibility.page_title | major | WCAG 2.4.2 | Each page must have a descriptive and unique title. |
accessibility.color_contrast | major | WCAG 1.4.3 | Text must have a sufficient color contrast ratio. |
accessibility.alt_text | critical | WCAG 1.1.1 | All images must have alternative text. |
accessibility.form_labels | critical | WCAG 3.3.2 | Form inputs must have associated labels. |
accessibility.keyboard_navigation | major | WCAG 2.1.1 | All functionality must be keyboard accessible. |
accessibility.aria_valid | major | WCAG 4.1.2 | ARIA attributes must be used correctly. |
accessibility.skip_navigation | major | WCAG 2.4.1 | Pages should provide skip-navigation links. |
accessibility.heading_hierarchy | major | WCAG 1.3.1 | Headings must follow a proper hierarchy. |
accessibility.responsive_text | major | WCAG 1.4.4 | Text must remain readable when resized up to 200%. |
accessibility.focus_not_obscured | major | WCAG 2.4.11 | Focused elements must not be hidden by sticky content. |
accessibility.target_size | major | WCAG 2.5.8 | Interactive targets must be at least 24×24px. |
accessibility.accessible_auth | major | WCAG 3.3.8 | Auth must not rely on cognitive function tests. |
accessibility.consistent_help | major | WCAG 3.2.6 | Help mechanisms must appear in a consistent location. |
accessibility.consent_banner_wcag | critical | WCAG / GDPR | Consent banners must be dialog-role, focus-trapped, and keyboard operable. |
accessibility.no_overlay_widgets | minor | EAA | Accessibility overlays are not valid compliance solutions. |
accessibility.focus_not_obscured_enhanced | minor | WCAG 2.4.12 AAA | Focused element must be fully visible, not partially obscured. |
accessibility.focus_appearance | minor | WCAG 2.4.13 AAA | Focus indicator must meet minimum area and contrast. |
accessibility.dragging_alternative | major | WCAG 2.5.7 | Drag operations must have a single-pointer alternative. |
accessibility.redundant_entry | major | WCAG 3.3.9 | Previously entered info must be auto-populated or selectable. |
accessibility.accessible_auth_no_exception | minor | WCAG 3.3.8 AAA | Auth with no cognitive function exception. |
Rules: Security & Privacy
23 rules23 rules across security headers, cookies, TLS, CORS, PCI DSS payment-page integrity, and Privacy Sandbox observability.
| Rule ID | Severity | Standard | What it checks |
|---|---|---|---|
security.csp_present | major | OWASP | Content-Security-Policy header should be present. |
security.x_frame_options | major | OWASP | X-Frame-Options protects against clickjacking. |
security.x_content_type_options | major | OWASP | X-Content-Type-Options prevents MIME-sniffing attacks. |
security.hsts | critical | OWASP | HSTS header ensures HTTPS-only connections. |
security.referrer_policy | major | OWASP | Referrer-Policy prevents information leakage. |
security.https_only | critical | PCI DSS | Site must use HTTPS for all resources. |
security.secure_cookies | major | OWASP | Cookies must have the Secure flag on HTTPS sites. |
security.permissions_policy | minor | OWASP | Permissions-Policy restricts browser features. |
security.csp_quality | major | OWASP | CSP must be configured with sufficient directives. |
security.csp_no_unsafe_inline | major | OWASP | CSP should not allow unsafe-inline in script-src. |
security.csp_no_unsafe_eval | major | OWASP | CSP should not allow unsafe-eval. |
security.coop | minor | OWASP | Cross-Origin-Opener-Policy prevents cross-origin attacks. |
security.coep | minor | OWASP | Cross-Origin-Embedder-Policy enables cross-origin isolation. |
security.sri | major | PCI DSS 4.0 | External scripts must use Subresource Integrity. |
security.httponly_cookies | major | OWASP | Session cookies must use HttpOnly to prevent XSS theft. |
security.samesite_cookies | major | OWASP | Cookies should use SameSite to prevent CSRF. |
security.cors_misconfigured | critical | OWASP | CORS must not use wildcard origin with credentials. |
security.tls_version | critical | PCI DSS | TLS 1.2 or higher required for secure connections. |
security.cert_expiry | major | PCI DSS | TLS certificate must not expire within 14 days. |
security.payment_page_integrity | major | PCI DSS 11.6.1 | Payment pages must have HTTPS + CSP + HSTS. |
privacy.topics_api_usage | minor | Privacy Sandbox | Topics API detected via Permissions-Policy. |
privacy.attribution_reporting_usage | minor | Privacy Sandbox | Attribution Reporting API headers or JS API detected. |
privacy.chips_usage | minor | Privacy Sandbox | Partitioned cookie attribute detected. |
Rules: Transparency
6 rules6 rules verifying policy presence, controller identification, and DSA-aligned reachability.
| Rule ID | Severity | Standard | What it checks |
|---|---|---|---|
transparency.privacy_policy | critical | GDPR Art 13 | Site must have an accessible privacy policy. |
transparency.terms_of_service | major | DSA Art 14 | Site should have terms of service. |
transparency.data_controller | major | GDPR Art 13.1 | Privacy policy must identify the data controller. |
transparency.contact_info | major | DSA Art 24 | Site must provide contact information. |
transparency.complaint_mechanism | major | DSA Art 20 | Platforms must provide complaint mechanisms. |
transparency.ad_disclosure | minor | FTC | Advertising content should be clearly labeled. |
GitHub Actions
Run on every pull request, upload SARIF to the Security tab, and gate the merge on critical failures.
name: Compliance
on: [pull_request]
jobs:
compliance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npx complytest scan ${{ env.PREVIEW_URL }} --format=sarif --fail-on=critical
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: compliance.sarif SARIF integration
The SARIF output format integrates directly with GitHub's Security tab. Compliance violations appear as code-scanning alerts alongside your regular security findings.
Exit codes
| Code | Meaning |
|---|---|
| 0 | All rules passed (within configured severity threshold). |
| 1 | Warnings present, no critical failures. |
| 2 | Critical failures present — build should block. |
Enterprise — Complicer
ComplyTest is the open-source scanner. For continuous monitoring with team routing, SLO enforcement, and legal-grade audit trails, see Complicer.
Automated daily scans
Continuous monitoring with trend tracking and regression detection.
Team routing
Auto-assign violations to Privacy, Accessibility, or Platform teams with Jira ticket creation.
SLO monitoring
Set guardrails like "pre-consent cookies must not exceed 2" with breach alerts.
Cryptographic evidence
Sigstore signing creates tamper-proof audit trails that satisfy GDPR Art 30.
Browse the rule implementations, file an issue, or contribute a new check. MIT-licensed; PRs welcome.