Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

Commit ab3f7f2

Browse files
committed
fix(security): UserService::createApiToken — reject invalid expiresIn
`parseExpiration()` returns `null` for any string that doesn't match the `^(\d+)([dhm])$` regex (e.g. "5x", "abc", "90 days"). The caller wrote that null straight into the persisted token row, where a null `expires` means a *non-expiring* token. Net effect: a typo in the expiration mints a permanent API key instead of producing an error. Throw `\InvalidArgumentException` from the controller surface when the input is supplied but unparseable. Existing "no expiration provided" path (`$expiresIn === null` or empty) still produces a non-expiring token — that's an explicit operator choice, not a malformed-input side effect. Refs: #1419 review (off-diff blocker — top-level comment 4378205122)
1 parent 17facc5 commit ab3f7f2

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

lib/Service/UserService.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,9 +1231,18 @@ public function createApiToken(IUser $user, string $name, ?string $expiresIn=nul
12311231
$tokenId = $this->secureRandom->generate(16);
12321232

12331233
// Calculate expiration.
1234+
// SECURITY: a non-matching `expiresIn` (e.g. "5x", "abc") used to
1235+
// fall through to `$expires = null` → non-expiring token. That is
1236+
// a perpetual API key minted from malformed input. Reject the
1237+
// request instead so the caller sees the typo.
12341238
$expires = null;
12351239
if ($expiresIn !== null && $expiresIn !== '') {
12361240
$expires = $this->parseExpiration(expiresIn: $expiresIn);
1241+
if ($expires === null) {
1242+
throw new \InvalidArgumentException(
1243+
'Invalid expiresIn value "'.$expiresIn.'" — expected a number followed by d (days), h (hours), or m (minutes), e.g. "90d".'
1244+
);
1245+
}
12371246
}
12381247

12391248
$now = date('c');

0 commit comments

Comments
 (0)