[Security] Protect local data at rest — owner-only file permissions, DB integrity checks, secret-free logs #146

Open
opened 2026-07-03 10:27:30 +00:00 by jabber.developer2 · 0 comments
Collaborator

At-rest protection and integrity for local storage: owner-only file perms on the history DB and OTR keystores, SQLite integrity check at open, verify-before-persist for OMEMO media, and secret redaction in logs.

Part of #144. Decision legend: M must-do, C could-do, W won't-do (this cycle); investigate = verify the problem is real / scope it before implementing.

Subtasks & findings

T03 — Log secret redaction (plaintext bodies + creds out of logs)

Owner: Dev2 (DB) · Decision: M / C · Effort: ~0.5–1d · Investigate: investigate all log sinks (LOG-06)

Shared redaction helper across DB logger + stderr bridge.

  • REQ-DAR-03 (high · c) — Decrypted plaintext bodies (and SASL/registration creds) written to profanity.log under default dblog=on (merges REQ-LOG-03/CIS-8.5)
    • Evidence: database_sqlite.c:694,717,748,760; connection.c:1088-1107
    • Fix: Drop message->plain from log args (:694/717/760), log row id not INSERT (:748); add redaction helper in _xmpp_file_logger for SASL/jabber:iq:register; add CI grep (redaction helper shared with REQ-LOG-06)
    • Maps to: NIST PR.PS-04/PR.DS-01; ISO A.8.10/A.8.12/A.8.15; CIS 8.5
  • REQ-LOG-06 (medium · m (investigate)) — stderr→log bridge applies no secret redaction
    • Evidence: log.c:289,297
    • Fix: Run the same secret-marker redaction over s->str before log_msg at both sites (reuses REQ-DAR-03 redaction helper)
    • Maps to: NIST PR.PS-04/DE.CM-06; ISO A.8.15/A.8.16

T07 — At-rest file permissions (0600 on DB + OTR keystores)

Owner: Dev2 (DB) · Decision: C · Effort: ~0.5d

chmod after sqlite3_open / privkey / fingerprint writes.

  • REQ-AUTH-01 (high · c) — OTR keys.txt/fingerprints.txt and SQLite history DB left world/group-readable (no chmod 0600)
    • Evidence: database_sqlite.c:144; otr.c:113,372,386
    • Fix: g_chmod(file, S_IRUSR|S_IWUSR) after sqlite3_open, otrl_privkey_generate and both write_fingerprints; manual perms check
    • Maps to: NIST PR.DS-01/PR.AA-01/PR.AA-05; ISO A.8.3/A.8.10/A.5.15/A.5.17

T08 — DB integrity + OMEMO media at-rest

Owner: Dev2 (DB) · Decision: M · Effort: ~1.5–2d · Investigate: investigate both (RES-02, CRY-06)

quick_check at open; verify GCM tag before persisting media.

  • REQ-RES-02 (medium · m (investigate)) — PRAGMA integrity_check only on /history verify, never at DB open
    • Evidence: database_sqlite.c _sqlite_init (128-157)
    • Fix: Run PRAGMA quick_check after sqlite3_open:144 and degrade gracefully on non-'ok'; corrupted-DB test
    • Maps to: NIST RC.RP-01/PR.IR-03; ISO A.8.27/A.8.13
  • REQ-CRY-06 (medium · m (investigate)) — OMEMO media plaintext persisted to user path before GCM tag verified
    • Evidence: omemo/crypto.c:445 (checktag :462); aesgcm_download.c:66,112-140
    • Fix: Decrypt to temp, verify tag, atomic rename on success; on failure remove() output and skip cmd_template branch; tampered-tag test
    • Maps to: NIST PR.DS-08/PR.DS-02; ISO A.8.24

Checklist

T03 — Log secret redaction (plaintext bodies + creds out of logs)

  • REQ-DAR-03 · high · C — Decrypted plaintext bodies (and SASL/registration creds) written to profanity.log under default dblog=on (merges REQ-LOG-03/CIS-8.5)
  • REQ-LOG-06 · medium · M · investigate — stderr→log bridge applies no secret redaction

T07 — At-rest file permissions (0600 on DB + OTR keystores)

  • REQ-AUTH-01 · high · C — OTR keys.txt/fingerprints.txt and SQLite history DB left world/group-readable (no chmod 0600)

T08 — DB integrity + OMEMO media at-rest

  • REQ-RES-02 · medium · M · investigate — PRAGMA integrity_check only on /history verify, never at DB open
  • REQ-CRY-06 · medium · M · investigate — OMEMO media plaintext persisted to user path before GCM tag verified

Notes

  • Investigate first (verify/scope before implementing): REQ-LOG-06, REQ-RES-02, REQ-CRY-06.
At-rest protection and integrity for local storage: owner-only file perms on the history DB and OTR keystores, SQLite integrity check at open, verify-before-persist for OMEMO media, and secret redaction in logs. Part of #144. Decision legend: **M** must-do, **C** could-do, **W** won't-do (this cycle); *investigate* = verify the problem is real / scope it before implementing. ## Subtasks & findings ### T03 — Log secret redaction (plaintext bodies + creds out of logs) _Owner:_ Dev2 (DB) · _Decision:_ M / C · _Effort:_ ~0.5–1d · _Investigate:_ investigate all log sinks (LOG-06) Shared redaction helper across DB logger + stderr bridge. - **REQ-DAR-03** (high · _c_) — Decrypted plaintext bodies (and SASL/registration creds) written to profanity.log under default dblog=on (merges REQ-LOG-03/CIS-8.5) - Evidence: `database_sqlite.c:694,717,748,760; connection.c:1088-1107` - Fix: Drop message->plain from log args (:694/717/760), log row id not INSERT (:748); add redaction helper in _xmpp_file_logger for SASL/jabber:iq:register; add CI grep (redaction helper shared with REQ-LOG-06) - Maps to: NIST PR.PS-04/PR.DS-01; ISO A.8.10/A.8.12/A.8.15; CIS 8.5 - **REQ-LOG-06** (medium · _m (investigate)_) — stderr→log bridge applies no secret redaction - Evidence: `log.c:289,297` - Fix: Run the same secret-marker redaction over s->str before log_msg at both sites (reuses REQ-DAR-03 redaction helper) - Maps to: NIST PR.PS-04/DE.CM-06; ISO A.8.15/A.8.16 ### T07 — At-rest file permissions (0600 on DB + OTR keystores) _Owner:_ Dev2 (DB) · _Decision:_ C · _Effort:_ ~0.5d chmod after sqlite3_open / privkey / fingerprint writes. - **REQ-AUTH-01** (high · _c_) — OTR keys.txt/fingerprints.txt and SQLite history DB left world/group-readable (no chmod 0600) - Evidence: `database_sqlite.c:144; otr.c:113,372,386` - Fix: g_chmod(file, S_IRUSR|S_IWUSR) after sqlite3_open, otrl_privkey_generate and both write_fingerprints; manual perms check - Maps to: NIST PR.DS-01/PR.AA-01/PR.AA-05; ISO A.8.3/A.8.10/A.5.15/A.5.17 ### T08 — DB integrity + OMEMO media at-rest _Owner:_ Dev2 (DB) · _Decision:_ M · _Effort:_ ~1.5–2d · _Investigate:_ investigate both (RES-02, CRY-06) quick_check at open; verify GCM tag before persisting media. - **REQ-RES-02** (medium · _m (investigate)_) — PRAGMA integrity_check only on /history verify, never at DB open - Evidence: `database_sqlite.c _sqlite_init (128-157)` - Fix: Run PRAGMA quick_check after sqlite3_open:144 and degrade gracefully on non-'ok'; corrupted-DB test - Maps to: NIST RC.RP-01/PR.IR-03; ISO A.8.27/A.8.13 - **REQ-CRY-06** (medium · _m (investigate)_) — OMEMO media plaintext persisted to user path before GCM tag verified - Evidence: `omemo/crypto.c:445 (checktag :462); aesgcm_download.c:66,112-140` - Fix: Decrypt to temp, verify tag, atomic rename on success; on failure remove() output and skip cmd_template branch; tampered-tag test - Maps to: NIST PR.DS-08/PR.DS-02; ISO A.8.24 ## Checklist **T03 — Log secret redaction (plaintext bodies + creds out of logs)** - [ ] **REQ-DAR-03** · high · C — Decrypted plaintext bodies (and SASL/registration creds) written to profanity.log under default dblog=on (merges REQ-LOG-03/CIS-8.5) - [ ] **REQ-LOG-06** · medium · M · investigate — stderr→log bridge applies no secret redaction **T07 — At-rest file permissions (0600 on DB + OTR keystores)** - [ ] **REQ-AUTH-01** · high · C — OTR keys.txt/fingerprints.txt and SQLite history DB left world/group-readable (no chmod 0600) **T08 — DB integrity + OMEMO media at-rest** - [ ] **REQ-RES-02** · medium · M · investigate — PRAGMA integrity_check only on /history verify, never at DB open - [ ] **REQ-CRY-06** · medium · M · investigate — OMEMO media plaintext persisted to user path before GCM tag verified ## Notes - **Investigate first** (verify/scope before implementing): REQ-LOG-06, REQ-RES-02, REQ-CRY-06.
jabber.developer added the
Kind/Security
Priority
Medium
3
labels 2026-07-03 10:32:13 +00:00
jabber.developer added this to the Plans (2025-2026) project 2026-07-03 10:32:19 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: devs/cproof#146
No description provided.