Skip to content

fix(join): stop rotating a returning member's webmail password - #104

Merged
ralyodio merged 1 commit into
mainfrom
fix/join-no-password-rotate
Aug 1, 2026
Merged

fix(join): stop rotating a returning member's webmail password#104
ralyodio merged 1 commit into
mainfrom
fix/join-no-password-rotate

Conversation

@ralyodio

@ralyodio ralyodio commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

The bug

handleJoin calls setWebmailPassword unconditionally (cmd/agentbbs/main.go:795), so every visit to join@ mints a fresh Roundcube password — including for members who registered and verified long ago.

Tracing an existing, verified member through handleJoin:

line what happens
751 UserByFingerprintfound, existing account
756 if !foundskipped, no re-registration
780 if !u.EmailVerifiedskipped, already verified
795 setWebmailPassword(u) — runs anyway

join@ is the address people remember, so returning members type it out of habit. That silently invalidates their webmail login: the replacement password scrolls past once in the join output, the old one is already dead, and nothing in the session says a credential changed.

The failure surfaces later as "my password stopped working", with nothing connecting it back to having typed join@. It also reads like a compromised mailbox — an alarming conclusion to hand someone over what was a no-op visit.

This was found by diagnosing exactly that: a member locked out of webmail who assumed the server had been breached.

The fix

Mint a webmail password only while actually onboarding — a new key registering, or an account completing email verification in this session:

onboarding := !found          // new key
...
onboarding = true             // or just verified in this session
...
var webmailPW string
if onboarding {
    webmailPW = a.setWebmailPassword(u)
}

A returning member now gets "You're already a member — nothing changed", is told the password is unchanged, and is pointed at ssh passwd@ — which already sets one password across git, mail and chat, and is key-gated, so it doubles as the forgot-password path.

Rotating a live credential should never be a side effect of saying hello.

Also

The old else if a.webmailURL != "" branch appended a bare • webmail <url> line. Replaced with the full url/login block so the address and where to get credentials are always visible, and the two no-password cases are now distinguished:

  • unchanged — forgot it? ssh passwd@ — returning member, password untouched
  • not set yet — set one: ssh passwd@ — onboarding, but Mailu was unreachable and minting failed

Previously both collapsed into the same bare URL line.

Verification

Inspection only — I could not build this. There's no Go toolchain on the box I'm working from (repo needs Go 1.26), so compilation is left to CI, which runs go build/go test on pull_request. Please confirm CI is green before merging.

Reviewed by hand: onboarding, webmailPW and lead are all used (no unused-variable errors); the expression-less switch is exhaustive and falls through to the original no-op when webmailURL is empty.

No test added — handleJoin has no existing test coverage and requires an ssh.Session; the branch logic isn't reachable without extracting it first. Worth a follow-up.

🤖 Generated with Claude Code

handleJoin called setWebmailPassword unconditionally, so every visit to
join@ minted a fresh Roundcube password -- including for members who
registered and verified long ago.

join@ is the address people remember, so returning members type it out
of habit. Doing so silently invalidated their webmail login: the
replacement password scrolled past once in the join output, the old one
was already dead, and nothing in the session said a credential had
changed. The failure surfaces later, as "my password stopped working",
with no way to connect it back to having typed join@ -- and it reads
like a compromised account, which is an alarming thing to hand someone
over a no-op visit.

Mint the password only while actually onboarding: a new key registering,
or an account that completes email verification in this session. A
returning member is told the password is unchanged and pointed at
passwd@, which already sets one password across git, mail and chat and
is key-gated, so it doubles as the forgot-password path.

Also replace the bare webmail URL line shown when no password is minted
with the full url/login block, so the address and where to get
credentials are always visible, and distinguish "unchanged" (returning)
from "not set yet" (onboarding, but Mailu was unreachable).

Verified by inspection only: this box has no Go toolchain (repo needs
1.26), so the build is left to CI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio marked this pull request as ready for review August 1, 2026 08:44
@ralyodio
ralyodio merged commit 41174ee into main Aug 1, 2026
5 checks passed
@ralyodio
ralyodio deleted the fix/join-no-password-rotate branch August 1, 2026 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant