Client-side Encryption — The Security Boundary

One sentence: framework's client-side encryption is obfuscation, not a security barrier. Real security comes from HTTPS + backend auth.

Where encryption is used

framework encrypts in 4 places (all AES-CBC + random IV):

WhereEntry pointEncrypted content
CookieuseCookie('xxx') (utils/cookie.ts)tokenInfo / deviceId / channel_code / share_code
localStorageuseLocal('xxx', init)AccountInfo (username / password / "remember me") and any business data
sessionStorageuseSession('xxx', init)Business data
API requestsrequest plugin auto-encrypts POST bodyVia aes-dynamic (HmacSHA256 per-request key derivation)

Why it's "not real security"

Encryption keys live in runtimeConfig.public.cacheAesKey / runtimeConfig.public.apiKey:

// nuxt.config.ts — project constants as real values (ship with the code; a same-named NUXT_PUBLIC_* env can still override at runtime)
runtimeConfig: {
  public: {
    cacheAesKey: 'your-16-byte-key', // 16 / 24 / 32 bytes
    apiKey: 'your-backend-key',      // request-encryption key agreed with the backend
  }
}

Anything under runtimeConfig.public.* is serialized into __NUXT__.config.public and injected into the client HTML. Any user can read it with one line of JS in DevTools:

// Browser console
window.__NUXT__.config.public.cacheAesKey  // key in plain text
window.__NUXT__.config.public.apiKey

Once the key is out, cookies / localStorage / request bodies can all be decrypted — the encryption is effectively useless against a determined attacker. This is an inherent limitation of any pure-frontend encryption, not a framework design flaw: the client must hold the key to decrypt, and any key shipped to the client can be reverse-engineered.

What actually provides security

What you want to preventThe real defense
MITM eavesdropping on trafficHTTPS / TLS (not framework encryption)
Backend rejecting illegal requestsBackend auth: token validation, request signing
DB leak leaving plaintext readableField-level encryption with keys in HSM/KMS, never on the frontend
User tampering with local dataValidate again on backend — frontend encryption only adds seconds of friction

Then what is framework encryption good for

Some limited but real value:

  1. Prevents DevTools Cookies / Local Storage panel from showing sensitive fields at a glance. After "Remember me", the stored password is ciphertext rather than plain JSON — a casual onlooker can't grab it instantly.
  2. Prevents intermediate log/proxy/CDN layers from accidentally recording plaintext when cookies travel with every request.
  3. Stops low-effort scrapers that grep for keywords in raw response bodies.

Design guidance

Treat framework encryption as obfuscation. Never as a security barrier.

  • ✅ Use useCookie / useLocal / useSession for auth state, user preferences, UI caches — obfuscation gives enough marginal benefit.
  • ✅ Use framework request encryption — keeps logs clean and stops low-effort scrapers.
  • ❌ Don't use "we encrypt it" as justification to store more sensitive fields. Passwords must rely on HTTPS + backend validation + user opt-in ("Remember me"), as layered defenses.
  • ❌ Don't design "encrypt sensitive business data on the frontend before putting it into the DB" — that's a backend job; the key shouldn't be on the frontend.

Planned evolution

  • AES-CBC → AES-GCM (shelved — see the closing comment on framework#2): the backend framework must stay compatible with legacy projects and cannot change its ECB encryption, and the Web Crypto API has no native ECB support, so the migration is shelved as a whole; to be re-evaluated when the backend framework ships a major upgrade.
  • Client-side key negotiation (not planned): technically possible to use ECDH to negotiate a session key at login time, but the engineering cost vastly outweighs the benefit (HTTPS already covers 99% of transport security).