CriticalPDF

Credentials & secrets

Where CriticalPDF keeps SMTP passwords, OAuth tokens, license keys, and PDF encryption passwords — and how each is protected.

CriticalPDF deliberately splits its secrets across two places: most configuration goes in a per-user JSON file, but the sensitive credentials never touch that file — they go into the Windows Credential Manager.

The two stores

Per-user GUI config — config.json

Your desktop-app configuration lives in a per-user file:

C:\ProgramData\CriticalPDF\users\<username>\config.json

Each Windows account gets its own. It holds templates, email / SMTP settings (host, port, username — but not the password), the licence identity (licensee name, company, email, key) and the cached licence snapshot, savings-calculator costs, and UI preferences.

The file is written with an atomic temp-file-plus-rename, so a crash can’t leave it half-written, and the JSON keys are sorted deterministically so diffs stay clean.

Windows Credential Manager — the actual secrets

Three values are never written to config.json. They go into the Windows Credential Manager, DPAPI-encrypted and scoped to the Windows user:

SecretUsed for
smtpPassCustom SMTP / Computer Team account password
gmailTokenGmail OAuth refresh token
msaTokenMicrosoft 365 OAuth refresh token

When CriticalPDF loads config.json, it overlays these secret values from the Credential Manager at runtime. If you open config.json in a text editor, you will not find a password or token in it — if an older config ever had a plaintext secret, it’s migrated into the Credential Manager on first launch and scrubbed from the file.

What’s not in the Credential Manager

A couple of things people expect to be secrets live in config.json by design:

  • Licence key and identity. The licName / CompName / Email / Key fields are in config.json. The cached verification result that lets you keep working offline is HMAC-signed (licSignature), so it can’t be hand-edited to forge or extend a licence.
  • PDF encryption passwords. Owner and user passwords for a template’s PDF encryption are part of that template’s definition, inside config.json.

The service’s own secret

The background service has one secret of its own, in its machine-wide config:

C:\ProgramData\CriticalPDF\serviceconfig.json

EncryptionPassword is the key the service uses to seal dead-lettered captures on disk. It’s stored in serviceconfig.json as plain text:

"EncryptionPassword": "CHANGE-ME-use-a-strong-password",

The installer generates a random value. If you ever see the literal CHANGE-ME string, change it and restart the service.

Locking down the folder

config.json still contains the licence and any PDF encryption passwords, and serviceconfig.json contains the EncryptionPassword. On a machine with untrusted standard users — a shared workstation or an RDP / RDS host — review the permissions on C:\ProgramData\CriticalPDF\ and restrict read access:

# Inspect the current ACL
icacls C:\ProgramData\CriticalPDF

The DPAPI-protected Credential Manager entries are safe regardless — they’re tied to each Windows account and can’t be read by another user even with file access.

Diagnostic bundles redact secrets

Send diagnostics to support builds a zip with logs, an environment summary, and a copy of the configuration with known secret fields redacted. Review the staged bundle in Explorer before it sends — the Credential Manager entries are never included.

Revoking access

SecretHow to revoke
Gmail OAuthmyaccount.google.com/permissions → remove CriticalPDF
Microsoft 365 OAuthYour account’s privacy panel or your tenant admin’s app consent panel
Custom SMTP passwordRotate at the SMTP server, then update Settings → Email Settings
License keySettings → Licensing → Release license to return the seat
EncryptionPassword (service)Edit serviceconfig.json, set a new value, restart the CriticalPDF Service. Existing dead-lettered captures sealed with the old password become unrecoverable — drain the dead-letter queue first if those captures matter.

Was this page helpful? Let us know.