Security & cryptographic posture

Built so the worst-case
isn't catastrophic.

Centilio Vault is zero-knowledge by architecture, not by marketing. If our database is stolen, the attacker walks away with ciphertexts and a schema. Your secrets stay yours.

How keys flow

Five steps.
Four of them happen in your browser.

1

Master password

Stays in the user's browser memory. Never sent across the wire. Never written to disk.

2

Argon2id KDF

Memory-hard key derivation (m=64 MB, t=3, p=4) turns the master password into a Master Key. GPU- and ASIC-resistant.

3

HKDF → KEK

HKDF-SHA256 with org salt + info-tag derives a Key-Encryption-Key, also client-only.

4

AES-GCM-256 wrap

Each item gets a random 256-bit DEK. Items are AES-GCM-encrypted with the DEK; the DEK is wrapped under the KEK.

5

Server stores ct

Server receives ciphertext + wrapped DEK. Steals nothing useful if breached.

Full diagram in docs/architecture/crypto-zero-knowledge.md.

The crown jewels

What lives where —
and what protects it.

From our public threat model. No hand-waving.

AssetWhere it livesWhat protects it
Master passwordClient RAM onlyNever sent; KDF transformation
Per-item DEKsClient RAM (transient)Wrapped under KEK before persisting
Wrapped DEKs at restPostgres ciphers tableKEK is client-only; server can't unwrap
Login proofsBCrypt-hashed in DBBCrypt + login rate-limit
JWT signing secretServer env varNot in repo; rotation playbook
Audit logAppend-only DB tableService-role-only writes; hash-chain target
Posture, in public

What we've fixed.
What's still on the list.

We publish what's open as well as what's closed. Vague claims help nobody. Full ledger in docs/security/findings-log.md.

Closed (recent)

  • Auth filter bypasses (extension whitelisting) — 6 vectors closed
  • CORS wildcard for chrome-extension://* — closed
  • Hardcoded JWT fallback secret — closed
  • TRACE-level logging leaking SQL params — closed
  • application{,-dev}.properties shipped to prod — closed
  • hbm2ddl.auto=update silently rewriting schema — closed (Hibernate now in validate mode)
  • 6 React dangerouslySetInnerHTML XSS sites — closed
  • AdminToolServe column-name SQL injection — closed
  • MySQL driver hardcoded in PG-only DbConnection — closed
  • /user/public-key user enumeration — closed

Open + tracked

  • PBKDF2-100k → Argon2id KDF

    Migration in flight. Argon2id is the target; PBKDF2 is current. Rotation runbook exists.

  • TOTP secrets unencrypted at rest

    Tracked. Encrypting under user KEK in next quarter.

  • Criteria value-injection SQLi (R&D)

    Identified, fix queued. Not user-reachable today.

  • No JUnit harness, near-zero unit tests

    Test scaffold landing this quarter. Smoke tests in CI today.

  • No external pen test on record

    Vendor-gated. Engaging Q3 for first formal pen test.

Found something? Tell us.

We respond to security reports within 48 hours and credit discoverers in our public CHANGELOG.

Disclose privately

[email protected] — PGP fingerprint in SECURITY.md.

Email

Read the source

Vault is MIT-licensed. Read the code, run the build, audit it yourself.

View on GitHub

Threat model + posture

Public docs: threat-model.md, posture.md, findings-log.md.

Open docs

Bring your security review.

Send us your standard vendor questionnaire. We answer it, share our threat model, and walk your team through the architecture. Honest answers, in writing.

Or email us directly at [email protected]