chore(security): redact SMTP credentials from compose.dev.yml.1 template (LC-211) #253

Merged
nrupard merged 1 commit from chore/lc-211b-redact-smtp-creds-template into main 2026-05-28 21:18:32 +02:00
Owner

Summary

compose.dev.yml.1 is the committed TEMPLATE that operators copy to compose.dev.yml (kept out of git via skip-worktree). It was carrying live values verbatim: a real relay host (mail.a8n.run), a real account (nate@a8n.run), and a real password. Read access to the repo = ability to submit mail as that account.

Replaced the six LETS_CHAT_SMTP_* lines plus LETS_CHAT_BASE_URL with the commented-out empty-string convention from compose.dev-web.yml:30-41. Expanded the leading comment to document the copy-and-fill workflow plus the valid TLS modes (tls / starttls / none; port 465 implicit TLS uses tls).

Supersedes #252 (LC-211 typo-only fix): the invalid LETS_CHAT_SMTP_TLS: "implicit" value is gone (line is now a commented-out empty-string placeholder), so the parse_tls_mode warn-and-disable branch at server/src/mail.rs:43 no longer fires from this template. Close #252 in favor of this PR.

Rotation status

  • Operator rotates nate@a8n.run password at Stalwart on hc-01 (the leaked string "aksre znav bqmq siye ivr" becomes invalid the moment the rotation is saved).
  • Operator stores the new password locally in compose.dev.yml (skip-worktree'd) or a SOPS-encrypted secrets file.

History posture

The leaked password remains in git history at commits 30efeb8, 66801a8, and 877cd3a. Exposure window ~1 day (LC-100 i18n merge 2026-05-27 to now). History rewrite (git filter-repo + force-push to main) is deliberately NOT done here per the repo's "never force-push main" rule. Once the Stalwart rotation lands the historical string is a dead credential.

Test plan

  • grep --recursive --extended-regexp 'aksre|znav|bqmq|siye|nate@a8n\.run' --exclude-dir=.git --exclude-dir=target . returns nothing.
  • grep --recursive --line-number --extended-regexp 'LETS_CHAT_SMTP_TLS.*"(implicit|ssl|smtps)"' --exclude-dir=.git --exclude-dir=target . returns nothing (LC-211 AC).
  • Operator copies compose.dev.yml.1 -> compose.dev.yml, uncomments the SMTP block, fills the rotated password, redeploys, and the container log reads SMTP mailer configured.
## Summary `compose.dev.yml.1` is the committed TEMPLATE that operators copy to `compose.dev.yml` (kept out of git via skip-worktree). It was carrying live values verbatim: a real relay host (`mail.a8n.run`), a real account (`nate@a8n.run`), and a real password. Read access to the repo = ability to submit mail as that account. Replaced the six `LETS_CHAT_SMTP_*` lines plus `LETS_CHAT_BASE_URL` with the commented-out empty-string convention from `compose.dev-web.yml:30-41`. Expanded the leading comment to document the copy-and-fill workflow plus the valid TLS modes (`tls` / `starttls` / `none`; port 465 implicit TLS uses `tls`). **Supersedes #252** (LC-211 typo-only fix): the invalid `LETS_CHAT_SMTP_TLS: "implicit"` value is gone (line is now a commented-out empty-string placeholder), so the `parse_tls_mode` warn-and-disable branch at `server/src/mail.rs:43` no longer fires from this template. Close #252 in favor of this PR. ## Rotation status - [ ] Operator rotates `nate@a8n.run` password at Stalwart on `hc-01` (the leaked string `"aksre znav bqmq siye ivr"` becomes invalid the moment the rotation is saved). - [ ] Operator stores the new password locally in `compose.dev.yml` (skip-worktree'd) or a SOPS-encrypted secrets file. ## History posture The leaked password remains in git history at commits `30efeb8`, `66801a8`, and `877cd3a`. Exposure window ~1 day (LC-100 i18n merge 2026-05-27 to now). History rewrite (`git filter-repo` + force-push to main) is deliberately NOT done here per the repo's "never force-push main" rule. Once the Stalwart rotation lands the historical string is a dead credential. ## Test plan - [x] `grep --recursive --extended-regexp 'aksre|znav|bqmq|siye|nate@a8n\.run' --exclude-dir=.git --exclude-dir=target .` returns nothing. - [x] `grep --recursive --line-number --extended-regexp 'LETS_CHAT_SMTP_TLS.*"(implicit|ssl|smtps)"' --exclude-dir=.git --exclude-dir=target .` returns nothing (LC-211 AC). - [ ] Operator copies `compose.dev.yml.1` -> `compose.dev.yml`, uncomments the SMTP block, fills the rotated password, redeploys, and the container log reads `SMTP mailer configured`.
nrupard force-pushed chore/lc-211b-redact-smtp-creds-template from e1628dab7d
Some checks failed
check-secrets / Kingfisher (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / Nosey parker (pull_request) Successful in 3s
check-secrets / Kingfisher (pull_request) Successful in 4s
check-secrets / TruffleHog (pull_request) Successful in 5s
Check / clippy + fmt + tests (pull_request) Failing after 27s
to 875b743394
All checks were successful
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / Kingfisher (pull_request) Successful in 6s
check-secrets / Kingfisher (push) Successful in 8s
check-secrets / Nosey parker (pull_request) Successful in 7s
check-secrets / TruffleHog (pull_request) Successful in 9s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 2m17s
2026-05-28 21:17:55 +02:00
Compare
nrupard deleted branch chore/lc-211b-redact-smtp-creds-template 2026-05-28 21:18:32 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!253
No description provided.