← Back to Blog

PQC in CI/CD Pipelines

PQC in CI/CD Pipelines - QNSQY post-quantum encryption guide

CI/CD pipelines are the conveyor belts of modern software development. Every commit goes through a pipeline that compiles, tests, and ships the result. The pipeline is also where security checks happen: static analysis, dependency scanning, container hardening, and signature verification. As post-quantum cryptography becomes a real production concern, the CI/CD pipeline is where teams should add their PQC checks.

This piece walks through how to integrate PQC validation into common CI/CD systems, what kinds of checks make sense at each stage, and how to test for PQC correctness without making the pipeline so slow that nobody runs it.

Why CI/CD Is the Right Place for PQC Validation

Cryptographic code is unusual because most of its bugs are silent. A buggy sort function fails noisy: outputs are wrong, tests detect it. A buggy AES implementation might produce ciphertexts that decrypt to nothing useful, but a buggy ML-KEM implementation might produce ciphertexts that decrypt correctly today and reveal secret keys via timing leaks tomorrow. The bugs are not visible in the output.

This is why cryptographic implementations need automated validation. Known-answer tests catch wrong outputs. Constant-time tests catch timing leaks. Property-based tests catch edge cases. Each of these can run in a CI pipeline, and a pipeline that runs them on every commit catches regressions before they ship.

CI/CD is also the right place for policy enforcement. If your organization decides that all artifacts must be signed with ML-DSA after a certain date, the policy check can live in the pipeline. The pipeline rejects unsigned or improperly signed artifacts, which keeps the policy from drifting into noncompliance.

Pre-Commit Hooks

The earliest stage to catch issues is in a pre-commit hook on the developer's machine. Tools like pre-commit can run small checks before allowing a commit to land.

For PQC, useful pre-commit checks include:

Static analysis for cryptographic patterns. Tools like Semgrep have rule packs for cryptography. The rules can flag any direct call to RSA generation, suggest ML-KEM as the replacement, or flag use of deprecated hash functions in new code.

Linting for hardcoded keys. The CWE-798 pattern (hardcoded credentials) is easy to detect with pattern matching. A pre-commit hook that refuses commits containing what look like cryptographic keys catches a real category of mistake.

Format and import checks. If your codebase has a policy about which crypto libraries to use (for example: only the wrapper module, never the raw library), a pre-commit check enforces it.

Pre-commit hooks should be fast. Anything that takes more than a few seconds annoys developers and gets disabled. Save the heavier checks for CI.

For more on PQC code patterns, see crypto-agility-explained.

Pull Request CI Checks

When a pull request is opened, the CI pipeline runs more thorough checks. This is where the bulk of PQC validation belongs.

Known-answer test (KAT) validation. The NIST submissions include KAT vectors for each algorithm. ML-KEM has 100 official ACVP vectors, ML-DSA has dozens, and SLH-DSA has its own set. A CI step that runs these vectors against the production code path catches any regression in the cryptographic implementation. KAT validation is fast (seconds) and high signal.

For more on KAT testing, see the test vector references at csrc.nist.gov.

Constant-time validation. Tools like dudect and ctgrind detect timing variability in code paths that handle secrets. Running these against PQC code paths catches a class of side-channel bugs. The tools require a specific test harness, so this is more setup than KAT validation, but the payoff is catching bugs that humans cannot see.

Property-based fuzzing. Tools like cargo-fuzz, libFuzzer, and AFL can run for hours generating random inputs. For PQC code, fuzzing catches edge cases in serialization, parameter validation, and error handling. A short fuzz run (10 minutes) on every PR catches obvious bugs; longer runs in scheduled jobs catch deeper ones.

Dependency scanning. Tools like Snyk, Dependabot, and OSV-Scanner catch known vulnerabilities in third-party dependencies. For PQC, this includes any library that provides cryptographic primitives. As CVEs are reported in liboqs, OpenSSL, and other PQ libraries, the scanner alerts the team.

For more on CVEs in PQC libraries, see cwe-cve-pqc.

Build-Time Signature Verification

Once the code passes its tests, the build process produces artifacts. The build itself should produce signed artifacts using approved algorithms.

GitHub Actions has built-in artifact attestation that signs build outputs via Sigstore. The attestation is in-toto format, signed with ECDSA today, and Sigstore's roadmap includes ML-DSA. When ML-DSA support ships, the same attestation flow uses the new algorithm with no workflow changes.

GitLab CI has similar capabilities through its supply chain attestation features.

Self-hosted CI systems can use cosign directly to sign build outputs. The signing identity comes from an OIDC token, a hardware key, or a static key. As cosign adds ML-DSA support, the same flow gets the new algorithm.

For more on signing supply chain artifacts, see software-supply-chain-pqc.

Deployment Gates

After artifacts are built and signed, deployment gates verify them before letting them reach production. This is the final layer of CI/CD PQC enforcement.

Container admission. Kubernetes admission controllers like Kyverno or Sigstore policy-controller check signatures on container images at admission time. The policy can require that signatures be present, that they verify, and that they use approved algorithms. As policies are updated to require ML-DSA, the admission controllers enforce the new requirement.

Package management. For deployments that use traditional packages (RPM, DEB, MSI), the package signature is checked at install time by the package manager. Configuring the package manager to require specific signature algorithms is the deployment gate.

Configuration validation. For deployments using GitOps (ArgoCD, Flux), the configuration itself is signed. The deployment gate checks that the configuration signature is valid and uses an approved algorithm.

Testing PQC Correctness

PQC correctness testing has several layers:

Roundtrip testing. Generate a key, encapsulate, decapsulate, and verify the shared secret matches. This catches gross errors in the implementation. Roundtrip tests run quickly and should be on every PR.

Cross-implementation testing. Generate a ciphertext with one library, decapsulate with another. If the two libraries are correctly implementing the same algorithm, the roundtrip should succeed. This catches divergence between implementations.

Adversarial testing. Try invalid inputs: ciphertexts with wrong sizes, public keys with invalid coefficients, signatures with bit flips. The implementation should reject these cleanly, not crash or accept them.

Performance testing. Track the time to perform each operation. A regression in performance can indicate a bug or an unintended optimization regression. Performance tests are noisier than correctness tests, so use averaging and trend tracking.

For broader PQC algorithm context, see ml-kem-explained.

Pipeline Performance Considerations

Adding PQC validation to a pipeline takes time. Some perspective on costs:

KAT validation runs in seconds. Even for ML-KEM with 100 official vectors, the full set finishes in well under a minute on modern hardware. Unless you have a particularly slow runner, KAT validation does not slow the pipeline noticeably.

Constant-time validation takes longer because the tools observe many iterations. A reasonable run takes 1 to 5 minutes per algorithm. This is fine for PR validation if amortized across other checks.

Fuzzing is the most expensive check. A 10-minute fuzz run is the minimum useful duration; longer is better. Most teams run short fuzzes on every PR and longer ones on a schedule (nightly, weekly).

Cross-implementation testing depends on how many implementations you compare. If you have one production implementation and you test it against PQClean, the roundtrip is fast. If you compare across multiple language bindings, the test setup is more involved.

In practice, a well-configured PQC pipeline adds maybe 5 minutes to a typical PR check, which is acceptable for the security benefit.

Real CI/CD Examples

A GitHub Actions workflow for a Rust project that uses pqcrypto typically does the following:

The workflow runs on every push and PR. It checks out the code, installs Rust, and runs cargo build with the production feature flags. After build, it runs cargo test with KAT validation. Then it runs cargo bench briefly for regression detection.

A separate scheduled workflow runs nightly and includes long-form fuzzing with cargo-fuzz. Any new findings post to a security channel.

For a Python project, the equivalent uses pytest for the KAT validation, hypothesis for property-based testing, and a custom step for any constant-time tools. The dependency scanning is handled by Dependabot's GitHub integration.

For a Go project, the standard library's testing framework runs the KATs, and the project may use Sigstore's Go libraries for the signing portion.

Hybrid CI/CD: Both Classical and PQ Tests

During the migration period, pipelines should validate both classical and post-quantum code paths. This is hybrid testing applied to CI/CD.

A pipeline that runs the same tests against both an ECDSA signing path and an ML-DSA signing path detects regressions in either. A pipeline that builds artifacts with classical signatures and a parallel artifact with hybrid signatures catches issues with the hybrid wrapping logic.

The cost is roughly double, but the confidence is much higher than testing only one path.

For more on hybrid encryption, see hybrid-encryption.

Pipeline Secrets and PQC Keys

CI/CD pipelines store secrets: API keys, signing keys, deployment credentials. As PQC adoption grows, these include ML-DSA private keys for signing.

The same secret management practices apply. Use the platform's secret store (GitHub Actions secrets, GitLab CI variables, AWS Secrets Manager). Never check keys into source. Rotate keys on a schedule.

For ML-DSA specifically, the private key is much larger than an ECDSA key. Storage formats may need to handle the size: some secret stores have size limits that ECDSA fits comfortably in but ML-DSA-87 does not. Check your secret store's limits before committing to a workflow.

Policy as Code

Many teams define their CI/CD policies as code. Tools like Open Policy Agent (OPA) and HashiCorp's Sentinel let you write rules that the pipeline evaluates against artifacts.

For PQC, useful policy rules include:

"All artifacts deployed to production must have an ML-DSA signature." "Build provenance attestations must be signed by an approved CA." "No artifact may use SHA-1 in any signature path." "Container images must be built from approved base images that use PQC-capable libraries."

Policy as code lets the rules evolve over time without changing pipeline scripts. As the organization matures its PQC posture, the policies tighten, and the pipeline enforcement adjusts automatically.

For more on policy and SSDF, see ssdf-pqc-requirements.

Frequently Asked Questions

How long does it take to add PQC validation to an existing pipeline? For a project that already has a CI pipeline, adding KAT validation and basic dependency scanning takes a few hours to a day. Adding constant-time and fuzzing takes longer.

Will PQC tests slow my pipeline significantly? KAT validation is fast (under a minute). Fuzzing is slower but typically scheduled rather than per-PR. A well-tuned PQC pipeline adds 5 to 10 minutes to PR validation.

Should I run KAT vectors in production builds or only in CI? CI is the primary place. Running KATs at startup of a production binary is also reasonable for high-assurance deployments and adds startup time but provides extra confidence.

Can I use the same fuzzing tools for PQC as for classical crypto? Yes. cargo-fuzz, libFuzzer, AFL, and Hypothesis all work with PQC code. The harnesses are different but the tools are the same.

Where do I find official PQC test vectors? NIST publishes ACVP test vectors for ML-KEM and ML-DSA at csrc.nist.gov. The submissions also include KAT vectors. The PQClean repository has cleaned-up test vectors for several algorithms.

Sources

Related Articles

Protect Your Data Before Q-Day Arrives

QNSQY's NIST-standardized post-quantum encryption protects files against both current and quantum-era threats.

Try QNSQY