| CVE | Vulnerability name | Date | Responsible Security Disclosure by | Vulnerabilities |
|---|---|---|---|---|
|
—
|
SignupBleed |
2026-08-16 |
AhmedLukman and xet7![]() Found while reviewing a pull request about the opposite symptom. |
|
WeKan's Admin Panel has a Registration setting. Turning it off is how an administrator says that nobody else may join this instance. It closed the sign-up form. It did not close the REST endpoint behind it:
POST /users/register
The endpoint did have a guard, and the guard looked exactly right:
// server/apiAuthRoutes.js — before
if (Accounts._options.forbidClientAccountCreation) {
sendJsonResult(res, { code: 403 });
return;
}
Nothing in WeKan ever sets that option. Three separate things each nearly set it, and none of them does:
Accounts.config() call in the tree, in server/accounts-common.js, sets loginExpirationInDays and nothing else.forbidClientAccountCreation: disableRegistration in config/accounts.js is passed to AccountsTemplates.configure() — the useraccounts package's own options object, not Meteor's Accounts.disableRegistration is only assigned inside an async Meteor.call('isDisableRegistration', …) callback, which fires after configure() has already run. The file records this a few lines above, for a different reason.So the condition was always false, and the endpoint had never refused anyone. It read as though it worked, which is why it lasted: the option is named exactly for the job it was not doing.
The fix reads the setting from where the setting lives — the same field the sign-up form's own Meteor method reads, so the form and the API can no longer disagree about whether the door is open:
// server/apiAuthRoutes.js — after
const setting = await ReactiveCache.getCurrentSetting();
if (setting?.disableRegistration === true) {
require('/server/lib/securityLog').record({
key: 'authz.register', action: 'blocked', source: 'POST /users/register',
detail: 'refused account creation while registration is disabled',
});
sendJsonResult(res, { code: 403 });
return;
}
The optional chain matters: an instance with no Settings document yet still allows registration, rather than locking itself out on first run. The refusal is recorded because every call that reaches it is an attempt — once the administrator has turned registration off there is no legitimate caller, so the log cannot drown Admin Panel / Problems in ordinary traffic.
tests/restRegisterRespectsSetting.test.cjs pins nine facts, four of them negative, on an endpoint that had no tests at all: that the setting is read where the Meteor method reads it, that the dead option is not consulted again and is still set nowhere — so a later change cannot quietly reintroduce two sources of truth that disagree — that an enabled instance still creates the user and answers with its token, and that a missing Settings document does not refuse everybody.
Pull request #6598 by AhmedLukman changed this guard to read WeKan's setting. It was filed against issue #4774, a 403 Forbidden from this endpoint that nobody had been able to reproduce — and which this line cannot produce, because it never returned 403 at all. Looking into why turned up the opposite fault, and a more serious one. The pull request was closed and the fix written with a security log entry and the tests; the finding is the reporter's.