Read this first
Six findings in QuantaCipher, an encryption product, and no data-exposure path. The material issue was accuracy: a pre-standard Kyber-768 implementation sold as FIPS 203 ML-KEM-1024, a runtime returning a hardcoded algorithm label, and an unmaintained dependency carrying the KyberSlash timing advisory. One dependency migration closed all three, and we verified it against the published build. Two findings remain open: build provenance is still unverifiable, and gateway metadata still travels in the clear. The full review is at quantakrypto.com/audits/xaexaex/quantacipher.
Read a post-quantum datasheet and you will be told which standard the product implements. It is the one claim a buyer cannot check without unpacking the binary, and it is the claim most likely to be out of date, because the standards moved and the code did not.
QuantaCipher advertised NIST ML-KEM and FIPS 203. What it shipped was the pre-standard round-3 Kyber submission, at the 768 parameter set, while the marketing described NIST Level 5. Two things were true at once: the algorithm was not the standardised one, and the delivered security level was Level 3 rather than the Level 5 on the page.
What was sound
Starting here is not politeness, it is the finding that took the longest to establish. We found no data-exposure path, and the construction is built correctly.
- Correct CSPRNG throughout. KEM keygen and encapsulation use
OsRng, nonces use the AEAD'sOsRng, and in WASM that resolves to Web CryptogetRandomValues. No weak randomness anywhere. - A sound KEM/DEM construction: AES-256-GCM, a fresh 96-bit random nonce per operation, and a fresh KEM shared secret per message, so key reuse and nonce reuse are structurally impossible rather than merely avoided.
- The local-only claim substantially holds. The encryption path does not phone home.
That matters for how the rest of this reads. A product with a broken construction and an accurate datasheet is in worse shape than this one. The defects here are in what the product says about itself.
The label the runtime returned
Alongside the mismatch, the runtime reported its algorithm as a hardcoded constant rather than deriving it from the implementation in use.
This is a small defect with a long tail. Downstream policy engines, CBOM generators and attestation tooling record whatever the runtime tells them. A constant string means those records are wrong wherever the constant is wrong, and they are wrong silently, in someone else's compliance evidence, months later. An inventory built from that output describes a deployment that does not exist.
One migration, three findings
The KEM came from pqc_kyber, an unmaintained crate carrying the KyberSlash advisory: a timing side channel in the key-recovery class, CVSS 7.4. Exploitability in a local-only usage model is low, since an attacker has to be positioned to measure decapsulation. Shipping an unmaintained crate with an unfixed advisory is the problem regardless of the day's exploitability, because nobody is going to fix the next one either.
So the highest-leverage recommendation was a single line of work: migrate to the maintained ml-kem crate at the 1024 parameter set. That makes the FIPS 203 claim true, closes the parameter-set discrepancy, and removes the advisory. Three findings collapse into one migration.
We measured the fix
They made the migration. We did not take it on report.
The published WASM build now returns a public key of 1568 bytes and a secret key of 3168 bytes. Those are the FIPS 203 ML-KEM-1024 sizes, and they are not the Kyber-768 sizes the previous build produced, so the byte counts alone settle both the algorithm question and the parameter-set question. The runtime now reports an algorithm string that agrees with them. The core's dependency manifest no longer carries pqc_kyber. The SDK's default gateway resolves, and refuses plain HTTP outside localhost.
Four of six fixed, each linked on the audit page to the published release that closed it: quantacipher-core 0.3.5, quantacipher-wasm 0.4.4, quantacipher-sdk 1.4.3.
The two that are still open
Both remain open for the same reason the others closed. We can check one and not the other.
The source repository is not public, so nobody outside the vendor can rebuild the artifacts and confirm they correspond to any source. For a product whose value proposition is that you do not have to trust the network, being unable to verify what you are running is a structural gap rather than a bug. Everything we verified above, we verified by measuring the shipped binary, which is exactly the technique a customer should not have to use.
And gateway metadata is still posted alongside the ciphertext in the clear. The zero-trust claim is that the operator learns nothing. Whoever runs the gateway learns who is talking, about what kind of record, and when. The payload is protected. The pattern of use is not, and for many threat models the pattern is the sensitive part.
The point
The gap between what a product says and what it ships is not usually dishonesty. It is a standard that changed under a codebase, a datasheet written once, and a version string typed as a constant because at the time it was true. The result is the same for the buyer either way: a compliance claim that fails the first time anyone checks it.
Which is why we publish the byte sizes. A number a reader can reproduce against the published artifact outlives any grade we could put on the page, and it is the only form of this claim that stays true without us.
References
- The full review at quantakrypto.com, with every finding and its status
- FIPS 203 at csrc.nist.gov
- KyberSlash at kyberslash.cr.yp.to
- quantacipher-core 0.3.5 on crates.io
If your product claims a standard, the cheapest way to find out whether it still ships one is to have someone measure it. Talk to us.