Security fixes before deploy; restore CNB exchange rates #3
Loading…
Reference in a new issue
No description provided.
Delete branch "security-fixes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Findings from a pre-deploy security review.
useServerSyncencrypted every mutation in a batch with one XChaCha20 nonce. noble/ciphers 2 throws on that, so full syncs and multi-mutation batches (recurring transactions) never reached the server. Old lofik on noble/ciphers 0.5.3 reused the nonce silently, so batched messages on the old sync server are weakly encrypted. Now one nonce per mutation.Bob's coffeebroke the query. Values are now quoted with''escaping.x-frame-options: DENYandx-content-type-options: nosniff.keyless_legacy_url), so CNB rates had stopped loading. A new/cnb?date=dd.mm.yyyyroute fetches the fixed CNB URL server-side, so the third-party proxy is gone.max_page_count). A failed insert is logged and not acked, so the client keeps its pending updates.maxHttpBufferSizeraised from 1 MB (about 2,000 transactions) to 10 MB.bun, with/app/dataowned by it. In Dokploy, use a volume mount, not a bind mount.Checked:
astro checkclean, build OK. Production server with two browser profiles: apostrophe titles save, full sync wrote 3 rows with 3 distinct nonces and reached the second device./cnbreturns CNB rates from curl and from the page; a malformed date gets 400. Not tested:docker build(no Docker here), and the 1 GB cap being hit.🤖 Generated with Claude Code
Recommendation: nits
This PR fixes a nonce-reuse bug in the sync encryption (now one nonce+cipher instance per mutation instead of per batch), adds SQL string escaping via a shared
q()helper, and addsx-frame-options/x-content-type-optionsheaders to the production server. I verified the per-message nonce fix lines up with the server/schema, which already stores and expects one nonce per message, and thatq()is applied consistently everywhere a user-controlled value was previously interpolated raw into SQL.@ -76,1 +72,4 @@for (const mutation of mutations) {const nonce = randomBytes(24);const chacha = xchacha20poly1305(sha256(privKey), nonce);nit: sha256(privKey) is now recomputed on every loop iteration even though privKey doesn't change per mutation; only the nonce needs to be fresh. Minor, avoidable work in a hot path for large batches.
Fixed in
1ff95a7989.Re the nit on
useLofikMutation.ts(key hashing in the loop): fixed in1ff95a7. The key is hashed once per batch and only the nonce is per mutation.Fix nonce reuse in sync, escape SQL values, add frame and nosniff headersto Security fixes before deploy; restore CNB exchange ratesRecommendation: looks-good
This PR self-hosts a CNB exchange-rate proxy (replacing corsproxy.io), caps the sync SQLite DB at 1 GB with a max_page_count pragma plus try/catch around the insert transaction, raises socket.io's max message size for full syncs, and switches the Docker container to run as the non-root
bunuser. It also fixes the previously-flagged nit of recomputing sha256(privKey) on every mutation in a batch.