super-productivity/docs
Johannes Millan c6480d1cae
fix(sync): harden SuperSync E2EE against metadata tampering (GHSA-8pxh-mgc7-gp3g) (#8904)
* fix(sync): defense-in-depth vs entityId retarget on encrypted ops

SuperSync E2EE (AES-256-GCM) covers only op.payload; metadata fields
(entityId, opType, actionType, vectorClock, isPayloadEncrypted, ...)
travel as plaintext and are not bound by the auth tag. A malicious/
compromised sync server or MITM could retag an encrypted LWW-update op
with a different entityId, redirecting the authenticated changes onto an
attacker-chosen entity — convertOpToAction() previously trusted the
tampered entityId over the authenticated payload.id (coercing even a
missing payload.id) and only warned.

At the decrypt boundary (where encryption origin is known) verify that
an in-scope LWW op's authenticated payload carries a string id equal to
op.entityId; otherwise fail closed via a new OperationIntegrityError,
distinct from DecryptError so it does not trigger the enter-password
dialog. The gate mirrors convertOpToAction's predicate (alias resolution
+ singleton exclusion) so the two boundaries cannot drift.

Scoped defense-in-depth for GHSA-8pxh-mgc7-gp3g, NOT full integrity.
Still open (durable AAD-envelope fix): plaintext-injection downgrade via
isPayloadEncrypted=false (needs a download-side mandatory-encryption
guard), opType promotion, entityType swap, vectorClock replay. Correct
the overstated integrity claim in the encryption architecture doc.

* fix(sync): reject plaintext ops when SuperSync encryption is mandatory

The isPayloadEncrypted flag is unauthenticated plaintext metadata, so a
compromised SuperSync server or MITM could set it to false and inject a
fully attacker-authored plaintext op — it would skip decryption AND the
payload/metadata integrity check and be applied verbatim (arbitrary op
forgery). This is a strictly more powerful bypass than the ciphertext
entityId retarget closed previously.

assertOpsEncryptedWhenExpected rejects any inbound plaintext op (download
+ piggyback paths) when encryption is enabled. It gates on config INTENT
(isEncryptionMandatory && isEncryptionEnabled()), not key presence, so it
also fails closed in the dropped-credential state (a !!encryptKey gate
would fail open there). Safe with no legacy-data loss: enabling
encryption deletes the server copy and re-uploads everything encrypted,
so no legitimate plaintext op remains; a never-encrypted account
(isEncryptionEnabled()===false) still accepts plaintext. The SuperSync
op-level twin of the file-based GHSA-vrc7 download guard and the
GHSA-9544 upload guard.

Also give OperationIntegrityError a dedicated sync-wrapper branch: fail
closed with a calm translated message instead of the raw GHSA/technical
string.

Follows up the review of GHSA-8pxh-mgc7-gp3g.
2026-07-10 19:06:27 +02:00
..
long-term-plans docs(sync): note local-file rev-check/write is non-atomic (#8898) (#8902) 2026-07-10 17:31:24 +02:00
plans feat(plugins): add Todoist import plugin with Import/Export launcher (#8882) 2026-07-10 13:30:03 +02:00
promotion build: better organize stuff 2025-06-27 09:03:16 +02:00
research feat(task-repeat): RFC 5545 RRULE recurring schedules — EPIC · Phase 1/13 (Closes #4020) (#7948) 2026-06-09 11:25:35 +02:00
screens docs/wiki content v0.8 (#7068) 2026-04-01 12:40:28 +02:00
sync-and-op-log fix(sync): harden SuperSync E2EE against metadata tampering (GHSA-8pxh-mgc7-gp3g) (#8904) 2026-07-10 19:06:27 +02:00
wiki fix(tasks): remove postal-mime dep and harden eml import (#8901) 2026-07-10 17:05:50 +02:00
add-new-integration.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
android-edge-to-edge-keyboard.md fix(android): keyboard + status-bar follow-ups for edge-to-edge (#8508) (#8548) 2026-06-23 11:57:49 +02:00
apple-release-automation.md ci: auto-submit iOS and macOS App Store builds for review (#7857) 2026-06-01 11:42:16 +02:00
build-and-publish-notes.md fix(ci): prevent duplicate unsigned exe files in GitHub Releases 2026-03-19 18:58:52 +01:00
documentation-guide.md Housekeeping for various docs, templates, and actions (#7451) 2026-05-02 13:58:25 +02:00
ENV_SETUP.md build: final approach 2025-07-14 20:52:51 +02:00
github-access-token-instructions.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
gitlab-access-token-instructions.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
how-to-rate.md feat(rate-dialog): action-aware prompt with feedback split 2026-05-04 17:27:11 +02:00
howto-refresh-snap-credentials.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
i18n-script-usage.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
legacy-webview-analysis.md 16.2.1 2025-11-01 13:22:58 +01:00
mac-app-store-code-signing-guide.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
performance-project-tag-report.md docs: add performance report 2025-11-13 18:23:50 +01:00
plainspace-api-extension-plan.md feat(plainspace): create tasks directly in a Plainspace-backed project (#8676) 2026-07-01 19:36:52 +02:00
plainspace-integration-plan.md refactor(sync): remove unused error classes, dialog, and constructor-time logging (phase 1, #8325) (#8510) 2026-06-20 13:36:56 +02:00
plugin-development.md fix(electron): remove exec IPC to close GHSA-256q (#8669) 2026-07-01 17:55:35 +02:00
styling-guide.md docs: update styling breakpoint table (#8846) 2026-07-07 16:50:49 +02:00
theming-contract.md feat(theme): add Plainspace built-in theme 2026-06-15 14:06:21 +02:00
TRANSLATING.md Fix frequency translations (#8000) 2026-06-05 10:53:26 +02:00
unused-translations-analysis.md chore(i18n): remove additional 86 orphan translation keys 2026-01-09 14:59:05 +01:00
update-android-app.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
update-mac-certificates.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00