jcoffey-dev is traveling from Thursday 1 October through Sunday 4 October. Issues and pull requests are welcome, and will get an answer after that. Thanks for your patience.
Write-up and test for the fix released in 2026.9.29.1 (#123), now rolled to production.
What was wrong: accounts holding oAuthClientOverride, which administrators hold, skipped OAuth client and redirect URI checks. That applied on the sign-in page, at the code exchange and in the device flow, and is upstream's behavior. Client registration (C-5) therefore protected every account except administrators. A link naming a made-up client and an attacker's redirect URI would give an administrator's code, and then a token, to the attacker. The same went for a device code a made-up client asked for and an administrator approved.
The fix (already on main via #123): the permission counts only in bootstrap and recovery mode, where the recovery administrator signs in before any client is registered. Otherwise administrators sign in through a registered client and one of its redirect URIs, like everyone else.
This PR: the C-5 contract text, and tests/e2e/client_override.py: 8 checks, 3 of which failed against a build without the fix, all passing with it. Covers bootstrap, normal mode, the device flow, and recovery. The system integration suite, including OIDC, passes.
Production: checked before release: every node sets INBUXA_ADMIN_URL and INBUXA_WEBMAIL_URL, so both front ends' clients are registered with the redirect URIs they use, and neither relied on the override. After the roll, all nodes run 2026.9.29.1 with no errors, and webmail, admin, JMAP and OAuth metadata answer normally.
Write-up and test for the fix released in **2026.9.29.1** (#123), now rolled to production.
**What was wrong:** accounts holding `oAuthClientOverride`, which administrators hold, skipped OAuth client and redirect URI checks. That applied on the sign-in page, at the code exchange and in the device flow, and is upstream's behavior. Client registration (C-5) therefore protected every account except administrators. A link naming a made-up client and an attacker's redirect URI would give an administrator's code, and then a token, to the attacker. The same went for a device code a made-up client asked for and an administrator approved.
**The fix (already on main via #123):** the permission counts only in bootstrap and recovery mode, where the recovery administrator signs in before any client is registered. Otherwise administrators sign in through a registered client and one of its redirect URIs, like everyone else.
**This PR:** the C-5 contract text, and `tests/e2e/client_override.py`: 8 checks, 3 of which failed against a build without the fix, all passing with it. Covers bootstrap, normal mode, the device flow, and recovery. The system integration suite, including OIDC, passes.
**Production:** checked before release: every node sets `INBUXA_ADMIN_URL` and `INBUXA_WEBMAIL_URL`, so both front ends' clients are registered with the redirect URIs they use, and neither relied on the override. After the roll, all nodes run 2026.9.29.1 with no errors, and webmail, admin, JMAP and OAuth metadata answer normally.
Documents under C-5 why oAuthClientOverride counts only in bootstrap
and recovery mode, and adds tests/e2e/client_override.py: the
recovery administrator keeps the override in both modes; after setup,
an administrator gets no code for an unregistered client or a
redirect URI its client didn't register, and a device code approved
for an unregistered client can't be exchanged. The script fails
against a build without the change (3 of 8) and passes with it.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Write-up and test for the fix released in 2026.9.29.1 (#123), now rolled to production.
What was wrong: accounts holding
oAuthClientOverride, which administrators hold, skipped OAuth client and redirect URI checks. That applied on the sign-in page, at the code exchange and in the device flow, and is upstream's behavior. Client registration (C-5) therefore protected every account except administrators. A link naming a made-up client and an attacker's redirect URI would give an administrator's code, and then a token, to the attacker. The same went for a device code a made-up client asked for and an administrator approved.The fix (already on main via #123): the permission counts only in bootstrap and recovery mode, where the recovery administrator signs in before any client is registered. Otherwise administrators sign in through a registered client and one of its redirect URIs, like everyone else.
This PR: the C-5 contract text, and
tests/e2e/client_override.py: 8 checks, 3 of which failed against a build without the fix, all passing with it. Covers bootstrap, normal mode, the device flow, and recovery. The system integration suite, including OIDC, passes.Production: checked before release: every node sets
INBUXA_ADMIN_URLandINBUXA_WEBMAIL_URL, so both front ends' clients are registered with the redirect URIs they use, and neither relied on the override. After the roll, all nodes run 2026.9.29.1 with no errors, and webmail, admin, JMAP and OAuth metadata answer normally.