Why Adobe Reader Says "Signature Validity Is Unknown" — and How to Verify It in a Web App
You open a signed PDF in Adobe Acrobat Reader and, instead of the reassuring green check, you get a yellow warning triangle: "At least one signature has problems", and in the Signature Panel, "Signature validity is UNKNOWN." The document looks fine. Nothing has been tampered with. So what is Adobe actually telling you — and how do you reproduce that same verdict in a browser or Node.js app?
This post explains what "unknown" really means, why it is different from "invalid," and how VerifyKit models the exact same three-way verdict.
Adobe's three verdicts
Adobe does not give a simple yes/no. Every signature lands in one of three states:
- Valid (green check) — the cryptography checks out and the signer's certificate chains up to a trusted anchor.
- Unknown (yellow triangle / question mark) — the cryptography is fine, but Adobe cannot establish trust in the signer's identity.
- Invalid (red X) — something is actually wrong: the document was altered after signing, or the signature does not verify against the signer's key.
The trap is reading "unknown" as "invalid." They are not the same. "Invalid" means do not trust this document. "Unknown" means the document is intact and the math is correct, but I can't prove who signed it.
Why "unknown" happens
A digital signature ties a document to a certificate, and that certificate has to chain up to a root that the verifier already trusts. Adobe trusts two things by default: the certificates in the Adobe Approved Trust List (AATL), and (optionally) your operating system's trust store. If the signer's certificate does not lead to one of those roots, Adobe has no basis to trust the identity — so the verdict is "unknown."
The usual causes:
- Self-signed certificate. Common in testing, internal tools, or documents signed with an ad-hoc certificate. There is no chain to any public root at all.
- A private or corporate CA. Your company runs its own certificate authority. It is perfectly legitimate — Adobe just has never heard of it.
- A CA that is not in the AATL. Plenty of real certificate authorities are not on Adobe's list.
- Missing intermediate certificates. The signer's certificate is fine, but the intermediate CA certificate that links it to the root was not embedded in the PDF, so the chain cannot be completed.
In every one of these cases the byte-range integrity check passes and the CMS/PKCS#7 signature verifies. The only thing missing is trust.
Reproducing Adobe's verdict on the web
PDF.js can render a signed PDF, but it does not compute any of this — it never evaluates the signature cryptography or the certificate chain, so it cannot tell you "valid," "invalid," or "unknown" at all. (We covered that gap in VerifyKit vs PDF.js.) To get Adobe-style verdicts you need an actual verification pipeline.
VerifyKit runs an 8-point pipeline and deliberately mirrors Adobe's three-way semantics. Each signature comes back with an overallStatus of valid, warning, invalid, or unknown, plus a breakdown of the eight individual checks — integrity, signature, certificate chain, expiry, timestamp, revocation, algorithm strength, and extended key usage.
The key detail: when the certificate chain cannot reach a trusted root, VerifyKit reports the certificate-chain check as unknown and the overall verdict as unknown — exactly like Adobe. The integrity and signature checks still pass. It does not silently downgrade an untrusted-but-intact document to "invalid," because that would be wrong.
import { createVerifier } from '@trexolab/verifykit-core'
import { readFile } from 'node:fs/promises'
const verifier = await createVerifier()
try {
const buffer = await readFile('signed-contract.pdf')
const result = await verifier.verify(buffer, 'signed-contract.pdf')
for (const sig of result.signatures) {
console.log(`${sig.name}: ${sig.overallStatus}`)
console.log(` integrity: ${sig.integrityCheck.status}`)
console.log(` signature: ${sig.signatureCheck.status}`)
console.log(` chain/trust: ${sig.certificateChainCheck.status} — ${sig.certificateChainCheck.detail}`)
}
} finally {
verifier.dispose()
}For an "unknown" document you will typically see integrity: valid, signature: valid, and chain/trust: unknown — the machine-readable version of Adobe's yellow triangle.
Turning "unknown" into "valid" — the right way
"Unknown" is not a bug to suppress. It is information: I could not establish trust. There are two legitimate ways to resolve it, and one thing you should never do.
1. Add the missing trust anchor. If documents are signed by your own corporate CA, tell the verifier to trust that CA's root. Then the chain completes and the verdict becomes "valid" — the same thing you would do by adding your CA to Adobe's trusted certificates.
import { createVerifier } from '@trexolab/verifykit-core'
const verifier = await createVerifier({
trustStore: {
// PEM string(s) for your internal root CA
certificates: [myCorporateRootPem],
mode: 'merge', // keep the built-in AATL roots, add yours on top
},
})2. Let the verifier fetch missing intermediates. When the chain breaks only because an intermediate certificate was not embedded, VerifyKit can chase the Authority Information Access (AIA) URLs in the certificate to fetch it and complete the chain automatically. This is on by default (enableAIA: true); set it to false if you want zero network requests during verification.
What you should never do is treat "unknown" as "valid" across the board by ignoring the chain check. That throws away the entire point of verification — you would be showing a green badge for documents signed by anyone, including an attacker with a self-signed certificate. Trust is the part that makes a signature mean something.
When it is genuinely "invalid"
For contrast, VerifyKit (like Adobe) returns invalid — not unknown — when trust is not the problem and something is actually wrong:
- the document was modified after signing, so the byte-range hash no longer matches;
- the CMS/PKCS#7 signature does not verify against the signer's public key;
- the signer's certificate was revoked (via CRL/OCSP) and no timestamp protects the signing time;
- the signature uses a cryptographically broken algorithm such as MD5.
Those are real failures. "Unknown" is not — it is the verdict for an intact document from a signer you have not chosen to trust yet.
The takeaway
"Signature validity is unknown" almost always means one thing: the document is fine, but the signer's certificate does not chain to a root you trust. The fix is to establish that trust deliberately — add the right anchor, or complete the chain — not to paper over the warning. If you are building this into a web app or a server pipeline and want Adobe-parity verdicts (valid / unknown / invalid) with the full eight-check breakdown, that is exactly what VerifyKit is built to do.
Try it on your own signed PDF in the live demo — everything runs in your browser, and the file is never uploaded. For the underlying model, see Core Concepts and the Revocation Checking guide.
Need PDF signature verification in production?
VerifyKit is a commercial SDK — try the live demo, then get in touch for a license.