VerifyKitv0.5.1

Online Revocation Plugin — API Reference

@trexolab/verifykit-plugin-revocation


Overview

The revocation plugin adds online CRL (Certificate Revocation List) and OCSP (Online Certificate Status Protocol) checking to the VerifyKit verification engine. After the core WASM engine validates a PDF signature, this plugin contacts external CRL/OCSP endpoints to determine whether the signer's certificate has been revoked.

The plugin operates in two modes:

  • Proxy mode (browser) — sends revocation requests to your server handler, which fetches CRL/OCSP data on behalf of the browser. Required because browsers cannot directly reach most CRL/OCSP endpoints due to CORS and mixed-content restrictions.
  • Direct mode (Node.js) — fetches CRL/OCSP endpoints directly from the running process. No server needed.

Mode detection is automatic: if endpoint is provided, the plugin uses proxy mode; if omitted, it uses direct mode.

The package exposes four import paths, each targeting a different runtime context.


Import Paths

PathExportsWhen to use
@trexolab/verifykit-plugin-revocationrevocationPlugin, typesBrowser or Node.js client — creates the plugin instance
@trexolab/verifykit-plugin-revocation/handlerhandleRevocationServer handler using Web Standard Request/Response (Next.js, Hono, Bun, Deno, Cloudflare Workers)
@trexolab/verifykit-plugin-revocation/handler/expressexpressHandlerServer handler for Express
@trexolab/verifykit-plugin-revocation/handler/coreprocessRevocationRaw data-in/data-out function for custom frameworks, testing, or Fastify

revocationPlugin(options?)

Creates a revocation checking plugin that conforms to the VerifyKitPlugin interface.

ts
import { revocationPlugin } from '@trexolab/verifykit-plugin-revocation'
 
function revocationPlugin(options?: RevocationPluginOptions): VerifyKitPlugin

Parameters:

ParameterTypeRequiredDescription
optionsRevocationPluginOptionsNoPlugin configuration. See RevocationPluginOptions for all fields.

Returns: VerifyKitPlugin — a plugin object with name: 'revocation' and a revocation property containing checkCRL and/or checkOCSP methods.

Mode detection:

  • endpoint present in options --> proxy mode (browser-safe)
  • endpoint absent --> direct mode (Node.js)

The returned plugin object has this shape:

ts
{
  name: 'revocation',
  revocation: {
    checkCRL?: (cert: CertificateInfo, urls: string[]) => Promise<RevocationCheckResult>,
    checkOCSP?: (cert: CertificateInfo, issuer: CertificateInfo, urls: string[]) => Promise<RevocationCheckResult>,
  }
}

If crl is set to false, the checkCRL method is omitted. If ocsp is set to false, the checkOCSP method is omitted.

Proxy Mode (Browser)

When endpoint is provided, every CRL or OCSP check is sent as a JSON POST request to that URL.

ts
const plugin = revocationPlugin({ endpoint: '/api/revocation' })

Internal flow:

  1. The core engine calls checkOCSP(cert, issuer, urls) or checkCRL(cert, urls).
  2. The plugin builds a RevocationRequest JSON payload:
    json
    {
      "type": "ocsp",
      "cert": { "serialNumber": "...", "authorityKeyId": "...", ... },
      "issuer": { "subjectNameHash": "...", ... },
      "urls": ["http://ocsp.example.com"]
    }
  3. The plugin sends POST <endpoint> with Content-Type: application/json and the JSON body.
  4. Custom headers (static or dynamic) are merged into the request if configured.
  5. An AbortController enforces the configured timeout (default: 10 seconds).
  6. The server handler returns a RevocationCheckResult JSON response.
  7. If the request fails (network error, timeout, non-2xx status), the onError callback is invoked (if configured), and the plugin returns { status: 'unknown', source: 'proxy error (<endpoint>)' }.

Request format:

ts
interface RevocationRequest {
  type: 'crl' | 'ocsp'
  cert: CertificateInfo
  issuer?: CertificateInfo   // present for OCSP, absent for CRL
  urls: string[]
}

Response format:

ts
interface RevocationCheckResult {
  status: 'good' | 'revoked' | 'revokedAfterSigning' | 'revokedNoTimestamp' | 'unknown'
  revocationDate?: Date
  reason?: string
  source?: string
}

Timeout handling:

The plugin creates an AbortController and aborts the fetch after timeout milliseconds (default: 10000). On abort, the onError callback fires and the result falls back to { status: 'unknown' }.

Custom headers:

Static headers:

ts
revocationPlugin({
  endpoint: '/api/revocation',
  headers: { 'Authorization': 'Bearer my-token' },
})

Dynamic headers (evaluated on each request):

ts
revocationPlugin({
  endpoint: '/api/revocation',
  headers: () => ({ 'Authorization': `Bearer ${getToken()}` }),
})

Headers are merged into the request after the default Content-Type: application/json header.

Error handling and the onError callback:

When a proxy request fails, the plugin:

  1. Catches the error.
  2. Wraps it as an Error if it is not already one.
  3. Calls onError(error, { type, url }) if the callback is configured.
  4. Returns { status: 'unknown', source: 'proxy error (<endpoint>)' }.

The verification still completes — only the revocation field is affected.

ts
revocationPlugin({
  endpoint: '/api/revocation',
  onError: (err, ctx) => {
    console.warn(`Revocation ${ctx.type} failed for ${ctx.url}:`, err.message)
    // ctx.type is 'crl' or 'ocsp'
    // ctx.url is the endpoint URL
  },
})

Direct Mode (Node.js)

When endpoint is omitted, the plugin fetches CRL and OCSP endpoints directly using fetch().

ts
const plugin = revocationPlugin()
// or with options:
const plugin = revocationPlugin({ timeout: 15000, maxCrlSize: 5 * 1024 * 1024 })

Internal flow:

  1. For CRL: fetches the CRL file (DER-encoded) from each URL in cert.crlDistributionPoints, parses the ASN.1 structure, and checks whether the certificate's serial number appears in the revokedCertificates list.
  2. For OCSP: builds a minimal DER-encoded OCSP request using cert.authorityKeyId (as issuerKeyHash), issuer.subjectNameHash (as issuerNameHash), and cert.serialNumber, then POSTs it to each OCSP responder URL and parses the DER response.
  3. The maxCrlSize option (default: 10 MB) limits the maximum CRL download size.
  4. No server handler is needed.

handleRevocation(options?)

Creates a Web Standard request handler for revocation checking. Compatible with any framework that uses the Web Standard Request/Response API.

ts
import { handleRevocation } from '@trexolab/verifykit-plugin-revocation/handler'
 
function handleRevocation(options?: HandlerOptions): (req: Request) => Promise<Response>

Parameters:

ParameterTypeRequiredDescription
optionsHandlerOptionsNoServer handler configuration. See HandlerOptions.

Returns: An async function (req: Request) => Promise<Response>.

Request validation:

The handler parses the request body as JSON and checks for the presence of type, cert, and urls. If any are missing, it returns a 400 response.

SSRF protection:

Before fetching any URL, the handler applies the urlFilter function (or the default filter) to each URL in the request. URLs that do not pass the filter are excluded. If no URLs remain, the result is { status: 'unknown', source: 'no allowed URLs' }.

Response format:

HTTP StatusBodyWhen
200RevocationCheckResult JSONCheck completed (any status including unknown)
400{ "error": "Invalid request" }Missing type, cert, or urls in request body
500{ "status": "unknown", "source": "handler error" }Unhandled exception

Next.js App Router

ts
// app/api/revocation/route.ts
import { handleRevocation } from '@trexolab/verifykit-plugin-revocation/handler'
 
export const POST = handleRevocation()

Hono

ts
import { Hono } from 'hono'
import { handleRevocation } from '@trexolab/verifykit-plugin-revocation/handler'
 
const app = new Hono()
const handler = handleRevocation()
 
app.post('/api/revocation', (c) => handler(c.req.raw))
 
export default app

Bun

ts
import { handleRevocation } from '@trexolab/verifykit-plugin-revocation/handler'
 
const handler = handleRevocation()
 
Bun.serve({
  port: 3000,
  async fetch(req) {
    const url = new URL(req.url)
    if (url.pathname === '/api/revocation' && req.method === 'POST') {
      return handler(req)
    }
    return new Response('Not found', { status: 404 })
  },
})

Deno

ts
import { handleRevocation } from '@trexolab/verifykit-plugin-revocation/handler'
 
const handler = handleRevocation()
 
Deno.serve({ port: 3000 }, async (req) => {
  const url = new URL(req.url)
  if (url.pathname === '/api/revocation' && req.method === 'POST') {
    return handler(req)
  }
  return new Response('Not found', { status: 404 })
})

expressHandler(options?)

Creates an Express-compatible request handler for revocation checking.

ts
import { expressHandler } from '@trexolab/verifykit-plugin-revocation/handler/express'
 
function expressHandler(options?: HandlerOptions): (req: any, res: any) => Promise<void>

Parameters:

ParameterTypeRequiredDescription
optionsHandlerOptionsNoServer handler configuration. See HandlerOptions.

Returns: An Express middleware function (req, res) => Promise<void>.

Prerequisite: The express.json() middleware must be applied before this handler so that req.body is parsed. Without it, req.body will be undefined and the handler will return a 400 error.

Example

ts
import express from 'express'
import { expressHandler } from '@trexolab/verifykit-plugin-revocation/handler/express'
 
const app = express()
app.use(express.json())
app.post('/api/revocation', expressHandler())
 
app.listen(3000, () => {
  console.log('Revocation handler listening on port 3000')
})

Example with options

ts
import express from 'express'
import { expressHandler } from '@trexolab/verifykit-plugin-revocation/handler/express'
 
const app = express()
app.use(express.json())
app.post('/api/revocation', expressHandler({
  timeout: 15000,
  maxCrlSize: 5 * 1024 * 1024,
  urlFilter: (url) => {
    const u = new URL(url)
    return u.hostname.endsWith('.example-ca.com')
  },
}))
 
app.listen(3000)

processRevocation(payload, options?)

Framework-agnostic core function. Takes a plain RevocationRequest object and returns a plain RevocationCheckResult. No Request/Response objects involved.

ts
import { processRevocation } from '@trexolab/verifykit-plugin-revocation/handler/core'
 
function processRevocation(
  payload: RevocationRequest,
  options?: HandlerOptions,
): Promise<RevocationCheckResult>

Parameters:

ParameterTypeRequiredDescription
payloadRevocationRequestYesThe revocation check request containing type, cert, optional issuer, and urls.
optionsHandlerOptionsNoHandler configuration. See HandlerOptions.

Returns: Promise<RevocationCheckResult>

Behavior:

  1. Applies the urlFilter to all URLs in payload.urls. If no URLs pass, returns { status: 'unknown', source: 'no allowed URLs' }.
  2. For type: 'crl': calls the internal CRL checker with the filtered URLs.
  3. For type: 'ocsp': verifies that payload.issuer is present (returns { status: 'unknown', source: 'OCSP requires issuer certificate' } if missing), then calls the internal OCSP checker.

When to use:

  • Custom frameworks that don't use Web Standard Request/Response or Express (e.g., Fastify, Koa, tRPC)
  • Testing and scripting
  • Building your own handler wrapper

Fastify example

ts
import Fastify from 'fastify'
import { processRevocation } from '@trexolab/verifykit-plugin-revocation/handler/core'
 
const fastify = Fastify()
 
fastify.post('/api/revocation', async (request, reply) => {
  const result = await processRevocation(request.body as any, {
    timeout: 15000,
  })
  reply.send(result)
})
 
await fastify.listen({ port: 3000 })

Testing example

ts
import { processRevocation } from '@trexolab/verifykit-plugin-revocation/handler/core'
 
const result = await processRevocation({
  type: 'crl',
  cert: {
    serialNumber: 'aa:bb:cc:dd',
    subject: 'CN=Test',
    issuer: 'CN=Root',
    // ... other CertificateInfo fields
  } as any,
  urls: ['http://crl.example.com/root.crl'],
})
 
console.log(result.status) // 'good', 'revoked', or 'unknown'

Types

RevocationPluginOptions

Options passed to revocationPlugin(options?).

ts
interface RevocationPluginOptions {
  endpoint?: string
  timeout?: number
  crl?: boolean
  ocsp?: boolean
  maxCrlSize?: number
  headers?: Record<string, string> | (() => Record<string, string>)
  onError?: (error: Error, context: { type: 'crl' | 'ocsp'; url: string }) => void
}
OptionTypeDefaultDescription
endpointstringundefinedServer handler URL for proxy mode. When provided, the plugin sends POST requests to this URL instead of fetching CRL/OCSP directly. Omit for direct mode (Node.js).
timeoutnumber10000HTTP request timeout in milliseconds. In proxy mode, this is the timeout for the POST request to the server handler. In direct mode, this is the timeout for each individual CRL/OCSP fetch.
crlbooleantrueEnable CRL (Certificate Revocation List) checking. Set to false to disable CRL checks entirely.
ocspbooleantrueEnable OCSP (Online Certificate Status Protocol) checking. Set to false to disable OCSP checks entirely.
maxCrlSizenumber10485760Maximum CRL download size in bytes (default: 10 MB). Only applies in direct mode. In proxy mode, the server handler's maxCrlSize option controls this.
headersRecord<string, string> | () => Record<string, string>undefinedCustom headers for proxy requests (browser mode only). Pass a static object or a function that returns headers dynamically (useful for auth tokens that expire). Headers are merged after the default Content-Type: application/json.
onError(error: Error, context: { type: 'crl' | 'ocsp'; url: string }) => voidundefinedError callback invoked when a proxy request fails (timeout, network error, non-2xx response). context.type is 'crl' or 'ocsp'. context.url is the endpoint URL.

HandlerOptions

Options passed to handleRevocation(options?), expressHandler(options?), and processRevocation(payload, options?).

ts
interface HandlerOptions {
  timeout?: number
  maxCrlSize?: number
  urlFilter?: (url: string) => boolean
}
OptionTypeDefaultDescription
timeoutnumber10000Timeout in milliseconds for each outgoing CRL/OCSP fetch. If a CRL endpoint or OCSP responder does not respond within this time, the request is aborted.
maxCrlSizenumber10485760Maximum CRL download size in bytes (default: 10 MB). If the CRL response exceeds this size (checked via Content-Length header and actual body length), the download is aborted.
urlFilter(url: string) => booleanSee SSRF ProtectionFilter function for SSRF protection. Called for each URL in the request. Return true to allow the URL, false to block it.

RevocationRequest

The payload sent from the browser plugin to the server handler. Also the first parameter of processRevocation().

ts
interface RevocationRequest {
  type: 'crl' | 'ocsp'
  cert: CertificateInfo
  issuer?: CertificateInfo
  urls: string[]
}
FieldTypeRequiredDescription
type'crl' | 'ocsp'YesThe type of revocation check to perform.
certCertificateInfoYesThe signer's certificate. Must include serialNumber. For OCSP, must also include authorityKeyId.
issuerCertificateInfoFor OCSPThe issuer certificate (second certificate in the chain). Must include subjectNameHash for OCSP. Not required for CRL.
urlsstring[]YesCRL distribution point URLs (for type: 'crl') or OCSP responder URLs (for type: 'ocsp'). Extracted from the signer certificate's extensions.

RevocationCheckResult

Returned by all revocation functions. Defined in @trexolab/verifykit-core.

ts
interface RevocationCheckResult {
  status: 'good' | 'revoked' | 'revokedAfterSigning' | 'revokedNoTimestamp' | 'unknown'
  revocationDate?: Date
  reason?: string
  source?: string
}
StatusMeaningEffect on signature
'good'Certificate is not revoked. The serial number was not found in the CRL, or the OCSP responder returned "good".revocationCheck.status set to 'valid'. overallStatus unchanged.
'revoked'Certificate is revoked.revocationCheck.status set to 'invalid'. overallStatus set to 'invalid'. overallMessage updated to indicate revocation.
'revokedAfterSigning'Certificate was revoked, but the revocation date is after the signature's trusted timestamp. The signature was valid when created.revocationCheck.status set to 'valid'. overallStatus unchanged. Timestamp protects the signature.
'revokedNoTimestamp'Certificate is revoked and the signature has no trusted timestamp to prove it was signed before revocation.revocationCheck.status set to 'invalid'. overallStatus set to 'invalid'.
'unknown'Revocation status could not be determined. This happens when: no CRL/OCSP URLs are in the certificate, all endpoints are unreachable, the response cannot be parsed, or both CRL and OCSP are disabled.revocationCheck left unchanged (stays 'unknown'). overallStatus unchanged.

The optional fields:

FieldTypeDescription
revocationDateDateWhen the certificate was revoked. Present when status is 'revoked', 'revokedAfterSigning', or 'revokedNoTimestamp'.
reasonstringCRL revocation reason code (e.g., 'keyCompromise', 'cessationOfOperation').
sourcestringHuman-readable description of where the result came from. Examples: 'online CRL (http://crl.example.com/root.crl)', 'online OCSP (http://ocsp.example.com)', 'proxy error (/api/revocation)'.

CertificateInfo

Defined in @trexolab/verifykit-core. Key fields used by the revocation plugin:

ts
interface CertificateInfo {
  serialNumber: string                // e.g. "aa:bb:cc:dd:ee"
  authorityKeyId?: string             // hex, used as OCSP issuerKeyHash
  subjectNameHash?: string            // SHA-1 of DER-encoded subject name (hex)
  crlDistributionPoints?: string[]    // CRL URLs from the certificate
  ocspUrls?: string[]                 // OCSP responder URLs from the certificate
  // ... other fields omitted for brevity
}

How CRL Checking Works

Step-by-step internal process:

  1. Normalize serial number. Strip colon separators from cert.serialNumber and convert to lowercase hex.
  2. Fetch CRL. For each URL in the CRL distribution points list, send an HTTP GET request with the configured timeout and maximum size.
  3. Parse ASN.1 DER. The CRL is DER-encoded ASN.1. Parse the outer SEQUENCE, then the tbsCertList SEQUENCE inside it.
  4. Locate revokedCertificates. Walk the fields of tbsCertList to find the revokedCertificates field (a SEQUENCE OF entries, typically the 5th or 6th field).
  5. Match serial number. For each entry in revokedCertificates, read the userCertificate INTEGER field and compare its hex value (with leading zeros stripped) against the target serial.
  6. Return result. If the serial is found, return { status: 'revoked' }. If the serial is not found, return { status: 'good' }. If all URLs fail, return { status: 'unknown' }.

How OCSP Checking Works

Step-by-step internal process:

  1. Validate inputs. Check that cert.authorityKeyId and cert.serialNumber are present. Check that issuer.subjectNameHash is present. If any are missing, return { status: 'unknown' }.
  2. Prepare OCSP data.
    • issuerKeyHash = bytes from cert.authorityKeyId (hex-decoded). This is the SHA-1 hash of the issuer's public key.
    • issuerNameHash = bytes from issuer.subjectNameHash (hex-decoded). This is the SHA-1 hash of the issuer's DER-encoded subject distinguished name.
    • serialNumber = bytes from cert.serialNumber (hex-decoded).
  3. Build OCSP request. Construct a minimal DER-encoded OCSPRequest structure:
    OCSPRequest -> SEQUENCE {
      tbsRequest -> SEQUENCE {
        requestList -> SEQUENCE OF {
          Request -> SEQUENCE {
            reqCert -> CertID -> SEQUENCE {
              hashAlgorithm: SHA-1 (OID 1.3.14.3.2.26)
              issuerNameHash: OCTET STRING
              issuerKeyHash: OCTET STRING
              serialNumber: INTEGER
            }
          }
        }
      }
    }
    
  4. POST to OCSP responder. Send the DER bytes with Content-Type: application/ocsp-request to each OCSP URL.
  5. Parse OCSP response. Read the response DER:
    • Check that responseStatus is 0 (successful).
    • Scan for certStatus context tags in the SingleResponse:
      • 0x80 0x00 = good (certificate is not revoked)
      • 0xA1 ... = revoked (certificate is revoked; contains revocationTime)
      • 0x82 0x00 = unknown (OCSP responder does not know this certificate)
  6. Return result. First successful non-unknown result wins. If all URLs fail, return { status: 'unknown' }.

Check Priority

The core engine calls revocation plugin methods in this order:

  1. OCSP first — if ocsp is enabled and the signer certificate has ocspUrls, the engine calls checkOCSP(). OCSP is preferred because it is faster (small request/response) and provides real-time status.
  2. CRL fallback — if OCSP returns 'unknown' or throws, and crl is enabled and the certificate has crlDistributionPoints, the engine calls checkCRL().
  3. First non-unknown result wins. If either OCSP or CRL returns 'good' or 'revoked', that result is applied immediately and no further checks are performed for that signature.
  4. If both methods fail or return 'unknown', the revocation status remains 'unknown'.

This order is hardcoded in the core engine's runRevocationPlugins() function and is not configurable from the plugin options.


Error Handling

ScenarioBehaviorPlugin returnsHow to debug
Proxy request times outAbortController aborts the fetch. onError is called.{ status: 'unknown', source: 'proxy error (<endpoint>)' }Increase timeout. Check server handler logs.
Proxy returns non-2xx HTTP statusError is thrown. onError is called.{ status: 'unknown', source: 'proxy error (<endpoint>)' }Check server handler response. Ensure handler is mounted at the correct path.
Proxy network error (server down, DNS failure)Fetch throws. onError is called.{ status: 'unknown', source: 'proxy error (<endpoint>)' }Verify server is running. Check network connectivity.
CRL endpoint unreachableDirect fetch throws. Plugin tries next URL.{ status: 'unknown', source: 'online CRL (all URLs failed)' } if all URLs failCheck firewall rules. Try fetching the URL with curl.
CRL response exceeds maxCrlSizeError thrown. Plugin tries next URL.{ status: 'unknown' } if all URLs failIncrease maxCrlSize option.
CRL ASN.1 parse errorCaught internally. Treated as "serial not found" (safe default).{ status: 'good' } (may be inaccurate)Check that the CRL URL returns valid DER data.
OCSP responder returns non-zero statusOCSP response skipped. Plugin tries next URL.{ status: 'unknown' } if all URLs failOCSP responder may be overloaded or rate-limiting.
OCSP missing issuer.subjectNameHashCheck aborted immediately.{ status: 'unknown', source: 'OCSP (issuer subjectNameHash not available)' }Ensure you are using a recent version of @trexolab/verifykit-core which computes subjectNameHash in the WASM core.
OCSP missing cert.authorityKeyIdCheck aborted immediately.{ status: 'unknown', source: 'OCSP (insufficient cert info)' }Certificate may not have the AKI extension. CRL fallback should still work.
All URLs filtered by SSRF protectionNo fetch attempted.{ status: 'unknown', source: 'no allowed URLs' }Customize urlFilter to allow the CA's endpoints.
req.body missing fields (server handler)Handler returns 400.N/A (HTTP 400 error)Ensure express.json() is applied. Check client payload.
Unhandled server exceptionHandler returns 500.N/A (HTTP 500 error)Check server logs.

In all error cases, the verification still completes. Only the revocationCheck field on the affected signature is impacted.


SSRF Protection

The server handlers (handleRevocation, expressHandler, processRevocation) apply a URL filter before fetching any external endpoint. This prevents attackers from using the revocation handler as an open proxy to access internal services.

Default filter rules:

The default urlFilter function applies a layered check. A URL is blocked if any of these conditions are true:

  1. The URL does not parse successfully (new URL(url) throws).
  2. The protocol is not http: or https:.
  3. The hostname resolves to a private or loopback address:
    • localhost, 127.0.0.1, ::1, 0.0.0.0
    • RFC 1918 private ranges: 10.x.x.x, 172.16-31.x.x, 192.168.x.x
    • .local or .internal TLDs

If the URL passes the above checks, it is allowed if it matches any of these patterns (fast-path for known PKI URLs):

  • Hostname or path contains crl, ocsp, pki, ca., or cert
  • Path ends with .crl, .cer, or .der
  • Path contains /crl, /ocsp, /ca/, /revocation, or /repository
  • Hostname belongs to a government domain (.gov, .mil, .gov.in, .nic.in)

If none of the above patterns match, the URL is still allowed by default (the filter falls through to return true). This means the default filter is permissive for all public URLs and only blocks private/loopback addresses. If you need stricter filtering, provide a custom urlFilter.

Custom filter:

ts
handleRevocation({
  urlFilter: (url) => {
    try {
      const u = new URL(url)
      // Allow only specific CA domains
      return u.hostname.endsWith('.digicert.com') ||
             u.hostname.endsWith('.globalsign.com') ||
             u.hostname.endsWith('.letsencrypt.org')
    } catch {
      return false
    }
  },
})

Permissive filter (allow all HTTP/HTTPS URLs):

ts
handleRevocation({
  urlFilter: (url) => {
    try {
      const u = new URL(url)
      return u.protocol === 'http:' || u.protocol === 'https:'
    } catch {
      return false
    }
  },
})

UI Integration

When the revocation plugin updates a signature's revocationCheck field, the React viewer components (@trexolab/verifykit-react) automatically reflect the result.

DocumentMessageBar

The bar at the top of the viewer. If any signature's overallStatus becomes 'invalid' due to revocation, the bar displays: "At least one signature is INVALID." with a red background.

SignatureListPanel

In the expanded details for each signature, a revocation bullet point appears:

Plugin resultBullet textStatus icon
'good'"Certificate is not revoked"Green checkmark
'revoked' / 'revokedNoTimestamp'"Certificate has been revoked"Red X
'unknown'"Revocation status unknown"Gray question mark

Signature Properties Dialog (ValidityChecklist)

The full checklist in the properties dialog shows a "Revocation Status" row:

Plugin resultCheck textDetail
'good'"Certificate is not revoked (verified via online OCSP)." or "Certificate is not revoked (verified via online CRL)."Source URL
'revoked'"The signer's certificate has been revoked."Revocation date and reason if available
'revokedAfterSigning'"Certificate is not revoked (verified via revoked after signing, timestamp protects)."Source
'unknown'"Certificate revocation status is unknown."Detail from revocationCheck.detail

LTV Status

A signature is considered "LTV enabled" when it has a verified timestamp (timestampCheck.status === 'valid') and valid revocation data (revocationCheck.status === 'valid'). The SignatureListPanel displays "Signature is LTV enabled." when both conditions are met.