When Document Authenticity is enabled for the account, OneSpan Sign additionally inspects PDF attachments for signs that the file was altered after it was issued: whether the tool that produced the PDF is consistent with a genuine issued document, whether content was appended after the file was first written, whether the file's own timestamps are consistent, and whether the file was modified long after the date printed on it. It runs for eleven of the seventeen document types — the statements, bills, returns, invoices, contracts and insurance and registration documents — and not for photo identity documents, void cheques or employment letters.
Document Tampering Detection is an addition to NIGO Document Validation. When a signer uploads a supporting document — a bank statement, pay stub, utility bill, or tax return — OneSpan Sign can also check whether the document shows signs of having been altered, before anyone relies on it. Tampering Detection results appear in the same document preview modal that NIGO validation already uses.
Document Tampering Detection is gated by an account-level flag. With this setting off, no integrity analysis runs and no signals are produced. To enable this feature, contact our Support Team.
Four rule-based checks run on each uploaded PDF:
Unexpected source. Reads the PDF's producer and creator metadata. A document that should have come from an institution but was produced in a consumer editor (such as Canva, Word, or Photoshop) or by an AI generator is flagged. Ordinary re-savers and print-to-PDF tools (Preview, Microsoft Print to PDF, Chrome) are treated as normal. A blank or unrecognized producer is reported as source unverified rather than as a problem.
Edited after creation. Inspects the file's internal structure for appended revisions, which indicate the document was changed after it was first created. Fillable forms are exempt, so normal form-filling does not trigger this check.
Inconsistent file dates. Flags impossible or future-dated timestamps, such as a file modified before it was created, or dated in the future. A tolerance is built in to absorb clock and timezone differences.
Dated after its period. Compares the file's last-modified date against the document's own date, drawn from NIGO's existing extraction, and flags a file saved long after the period it covers.
How the Verdict Is Formed
Each check that fires contributes to a combined score, which maps to one of four tiers: Clear, Low, Medium, or High.
No single check can produce a High result on its own, with one exception: the Unexpected Source check. For every other check, a High result requires two or more independent signals to fire together. This keeps a legitimately re-downloaded statement from being flagged, while still catching a document that, for example, was produced in Canva, edited after creation, and dated months after its period.
Where Results Appear
An Integrity section in the document preview modal shows the overall verdict alongside each individual check in its pass or fail state, with a plain-language reason for anything flagged. The combined verdict also drives the document's status chip in the document list.
The same result — status, confidence, and reasons — is available on the API payload and via webhooks. Tampering checks run server-side regardless of whether the transaction originated in the Sender UI or through the API.
Reviewer Actions
Document Tampering Detection is advisory: nothing is auto-blocked. A flagged document can still be uploaded, signed, and completed. The existing reject-or-request affordance (see Rejecting a Document) remains the action available to the reviewer, who decides how to proceed.
Every flag is explainable, and every evaluation and reviewer action is logged with a timestamp, the document, the signals that fired, and the actor.
Limitations — what it does not detect
This is a set of heuristics over a PDF's structure and metadata. It is not fraud detection, and it cannot establish that a document is genuine.
It does not read the content of the document to judge whether the content is true. It cannot tell you that an income figure was altered, that a name is not the signer's, or that the document was issued to someone else.
It is largely blind on scanned and photographed documents. A PDF that is entirely a scanned image supports only the check on the producing tool; every other check reports as not assessed. A photo or screenshot uploaded directly as an image supports none of the checks. Because a great many legitimate attachments are scans or phone photos, not assessed is a common and expected outcome — and it is not a pass.
Detection of the producing tool reads only the PDF's own metadata. A file whose producer and creator fields have been stripped, or set to something unrecognised, reports as not assessed rather than a failure. Anyone able to edit a PDF is also able to edit those fields.
A finding is not proof, and the absence of findings is not proof of authenticity. Re-saving a bank statement through a browser's print-to-PDF, or downloading a statement months after its stated period, are ordinary behaviours that can produce a warning.
Using Tamper Detection
extractionResult.preflight carries the document integrity findings. It is null unless all of the following hold: the account has Document Authenticity enabled, the document type is one of the eleven supported for integrity analysis, the file is a PDF or an image, and extraction was submitted. Because integrity analysis runs before field extraction, it is also present on a result whose extractionStatus is FAILED. It is absent, with extractionResult itself null, whenever extraction was not submitted — a type mismatch, an unrecognised type, a quality failure, or extraction not enabled — so no findings are lost in those cases; none were produced.
The eleven supported types are BANK_STATEMENT, UTILITY_BILL, TAX_RETURN, PAY_STUB, INVOICE, CONTRACT, T4_SLIP_CA, AUTO_INSURANCE_CERTIFICATE, PROPERTY_INSURANCE, LIFE_INSURANCE_POLICY and VEHICLE_REGISTRATION. Photo identity documents, void cheques and employment letters are excluded: the signals rely on the structure of an issued PDF and do not apply to a photograph of a card.
This block is available through the API only. The Sender UI does not display integrity findings.
Four independent checks run over the file, and each reports one of four outcomes:
check | What it looks for |
|---|---|
SOURCE | Whether the tool recorded in the PDF's metadata as having produced or created it is consistent with a genuine issued document — as opposed to a consumer design tool, an online PDF editor, or an AI document generator |
EDITS_AFTER_CREATION | Structural evidence that content was appended or revised after the file was first written |
FILE_DATES | Whether the PDF's own creation and modification timestamps are internally consistent and not in the future |
PERIOD_DATE | Whether the PDF's last-modified timestamp is far later than the date printed on the document, and whether dates printed on the document contradict each other |
status | Meaning |
|---|---|
PASS | The check ran and found nothing wrong |
WARNING | The check ran and found something that casts doubt without proving alteration |
FAIL | The check ran and found a strong signal of alteration |
NOT_ASSESSED | The check could not run for this input, or ran and found no evidence to judge. Not a pass — render it distinctly |
{
"checks": [
{
"check": "SOURCE",
"status": "FAIL",
"messageKey": "esl.error.preflight_check.unexpected_source",
"params": { "tool": "Canva", "field": "CREATOR", "matchedValue": "WWW.CANVA.COM" }
}
],
"verifiability": { "inputType": "VERIFIABLE_PDF" },
"tier": "HIGH"
}Field | Notes |
|---|---|
checks | One entry per integrity check, always complete, ordered problems-first |
checks[].messageKey | A translation key for this specific outcome. Determined by which variant fired, not by the check — two failures of the same check can carry different keys, so resolve by messageKey, never derive a label from check alone |
checks[].params | Substitution values for a parameterized label, for example {"months": "7"}. Empty when the label takes none. Keys vary by outcome and may be added over time — read by key, never assume a fixed set |
verifiability.inputType | How much of the file could be inspected: VERIFIABLE_PDF (all four checks), IMAGE_ONLY_PDF (a scanned PDF — only SOURCE runs, the rest are NOT_ASSESSED), or NATIVE_IMAGE (a photo or screenshot — nothing runs) |
tier | The overall rating: CLEAR (every check ran and passed on a fully inspectable file), LOW, MEDIUM, or HIGH (enough alteration signals fired to warrant attention). A file that could not be fully inspected never rates CLEAR, however clean it looks |
Render tier as delivered. It is the single overall verdict, and it already accounts for how much of the document could be inspected as well as what the individual checks found. Do not re-derive it from the check statuses.
params.matchedValue on a SOURCE outcome is text taken from the uploaded document's own metadata. It is sanitized and truncated, but it originates from an untrusted file — HTML-escape it before rendering.