Skip to content

Name the address the code was sent to - #215

Merged
nursoda merged 3 commits into
mainfrom
feature/name-the-masked-address
Sep 4, 2026
Merged

Name the address the code was sent to#215
nursoda merged 3 commits into
mainfrom
feature/name-the-masked-address

Conversation

@nursoda

@nursoda nursoda commented Aug 26, 2026

Copy link
Copy Markdown
Member

The login challenge said that a code had been sent, but not where to. A user who
receives nothing could not tell whether the account carries the right address at
all — the one question the screen has to answer before anyone reaches for their
mailbox. It now names the address in the same masked form the personal settings
use: a*@*.org.

The address sits inside the two existing sentences rather than on a line of its
own. A separate line would state the same fact twice, and as a bare fragment it
gives a translator no subject and no verb to make the address agree with; several
languages need it inside the sentence to inflect it at all.

Showing the address made a second thing urgent. EMailAddressMasker used to
return anything it could not parse unchanged — harmless while only the
settings read it, a disclosure once a login screen prints it. An address whose local part is quoted —
"jo hn"@example.org, which the standard allows — may hold a space or a second
@ and is delivered normally, and an address written
through occ passes no validation at all. Such a value is now hidden whole. The
placeholder for it names no address, so both screens that show one — the login
challenge and the enrolment step — turn it into the empty string and use the
wording that names no address instead.

Translations lag behind, on purpose

Three strings are new: the two sentences that name the address, and the
enrolment screen's variant without one (Codes will be sent to your primary email address., with a full stop where the existing one has a colon). Until Transifex has
them, a non-English instance renders them in English while every other string
stays translated — including the fallback sentences, which are unchanged and keep
their existing translations. This is the normal case, not an edge case, so expect
it to be visible.

The l10n bot runs almost daily, but it only sees strings that reached main.
Merging a few days before a release rather than on the day of it is what closes
this
; there is nothing to fix in the code.

Not to be merged alone

Once the page names the address, a code that stays valid across an address change
would make that line name the wrong mailbox. security/drop-the-code-when-the-address-changes
is what closes that. Merge it first, or both together.

Checked

  • 96 smoke checks green against Nextcloud 33.0.7 and 34.0.2 (tests/smoke/smoke.sh)
  • unit, psalm, psalm taint, php-cs-fixer, eslint, stylelint and the Vitest suite green
  • browser pass on a German instance through all four screen states: address named,
    reload, an address the mask cannot take apart, and no address at all
  • the two new smoke assertions forced red by handing the template the raw address —
    exactly those two turned, and nothing else

🤖 Generated with Claude Code, verified, tweaked and approved by @nursoda.

@nursoda
nursoda requested a review from seyfahni as a code owner August 26, 2026 18:20
@nursoda nursoda added security Related to a security vulnerability php Pull requests that update php code javascript Pull requests that update javascript code labels Aug 26, 2026
@nursoda nursoda self-assigned this Aug 26, 2026
@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

nursoda and others added 3 commits September 5, 2026 00:57
The login screen said that a code had been sent, but not where to. A user who
receives nothing then cannot tell whether the account carries the right
address at all. It now shows the same masked form the personal settings use.

The address goes inside the two existing sentences rather than on a line of
its own. A line of its own would state the same fact twice, and as a bare
fragment it gives a translator no subject and no verb to make the address
agree with; several languages need it inside the sentence to inflect it at
all. Each sentence therefore has a second variant that names the address, so
what a translator sees is always a whole sentence.

The smoke test pins both halves of the result: the masked form is on the
page, and the user's full address is not. Without the second, a refactor that
handed the template the raw address would pass CI in silence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Olav Seyfarth <olav@seyfarth.de>
The masker returned anything it could not parse unchanged, which was harmless
while only the settings used it and is not now that the login screen shows the
result. A quoted local part may hold a space or a second '@' and is delivered
normally, and an address written through occ passes no validation at all, so
either could have been readable in full on the screen that promises a mask.

Such a value is now hidden whole, as IEMailAddressMasker::HIDDEN. That mask
names no address, so putting it on the screen would leave the user with
"sent to *@*" — nothing, in exactly the case where naming the address was
meant to reassure them.

Both screens that show the address therefore ask for the mask through one
method, which turns HIDDEN into the empty string: the login challenge and the
enrolment step during login. The empty string is what already told them there
is nothing to name, so a single guard on each screen covers both "no address
at all" and "an address we cannot name", and the two cannot drift apart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Olav Seyfarth <olav@seyfarth.de>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Olav Seyfarth <olav@seyfarth.de>
@nursoda
nursoda force-pushed the feature/name-the-masked-address branch from 0cb8309 to 5a391be Compare September 4, 2026 22:58
@nursoda
nursoda merged commit 11466f9 into main Sep 4, 2026
41 checks passed
@nursoda
nursoda deleted the feature/name-the-masked-address branch September 4, 2026 23:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

javascript Pull requests that update javascript code php Pull requests that update php code security Related to a security vulnerability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants