mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 00:46:45 +00:00
* 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. |
||
|---|---|---|
| .. | ||
| long-term-plans | ||
| plans | ||
| promotion | ||
| research | ||
| screens | ||
| sync-and-op-log | ||
| wiki | ||
| add-new-integration.md | ||
| android-edge-to-edge-keyboard.md | ||
| apple-release-automation.md | ||
| build-and-publish-notes.md | ||
| documentation-guide.md | ||
| ENV_SETUP.md | ||
| github-access-token-instructions.md | ||
| gitlab-access-token-instructions.md | ||
| how-to-rate.md | ||
| howto-refresh-snap-credentials.md | ||
| i18n-script-usage.md | ||
| legacy-webview-analysis.md | ||
| mac-app-store-code-signing-guide.md | ||
| performance-project-tag-report.md | ||
| plainspace-api-extension-plan.md | ||
| plainspace-integration-plan.md | ||
| plugin-development.md | ||
| styling-guide.md | ||
| theming-contract.md | ||
| TRANSLATING.md | ||
| unused-translations-analysis.md | ||
| update-android-app.md | ||
| update-mac-certificates.md | ||