Repository navigation
fix(authz): keep management credential issuance authenticated when login is disabled - #17064
Merged
diegosouzapw merged 3 commits intoOct 18, 2026
Merged
Conversation
…ller when login is disabled With requireLogin=false an anonymous caller could create or grant a manage/admin-scoped API key, regenerate or reveal one, and mint CLI access tokens at any scope, and a manage-scoped key could mint an admin token. All of those credentials pass the always-protected tier. Inference-only keys and the session / local-CLI paths are pinned as unchanged. Co-authored-by: gsmarcil <116014240+gsmarcil@users.noreply.github.com>
…gin is disabled With requireLogin=false the management tier is open, but a manage/admin-scoped API key and a CLI access token both pass the always-protected tier. Creating a key with a management scope, granting that scope, regenerating or revealing such a key, and minting CLI access tokens at any scope now need the same credential as with login on (requireCredentialForManagementScopedKey() and alwaysRequireAuth on /api/cli/tokens). Inference-only keys and the session / local-CLI paths are unchanged. AUTHZ_GUIDE and REMOTE-MODE no longer say login disabled lets anyone mint. Co-authored-by: gsmarcil <116014240+gsmarcil@users.noreply.github.com>
…/keys The scope gate pushed the handler past the max-lines ratchet; the flag spread was most of its cyclomatic weight. createPermissionOverrides() builds the same payload under the same conditions, and a route-level test pins the flags (and the no-flag defaults) end to end.
Contributor
CI Coverage Report
Coverage artifact was not available for this run. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
With
requireLogin=false, the management tier lets anonymous callers through, but thealways-protected tier (credential exports, log export, shutdown, …) still demands a credential.
Several management routes handed exactly such a credential to an anonymous caller:
POST /api/keyswith amanage/adminscope201, key returned401PATCH /api/keys/{id}grantingmanage/admin200, scope granted401POST /api/keys/{id}/regenerateon a management key200, new secret returned401GET /api/keys/{id}/revealon a management key (reveal enabled)200, secret returned401POST /api/cli/tokens(read/write/admin)200,oma_live_…returned401POST /api/cli/tokensadminwith a manage-scoped key200403(same ceiling as with login on)Each of those calls now needs the same credential it needs with login on. A new helper,
requireCredentialForManagementScopedKey()insrc/lib/api/requireManagementAuth.ts, gates thefour key paths only when the key carries
manage/admin(thehasManageScopeset themanagement auth itself uses).
POST /api/cli/tokensuses the existingalwaysRequireAuthoption onboth
requireManagementAuthandresolveOperatorCredential.Unchanged: inference-only keys are still created, edited, regenerated and revealed anonymously
in open mode; the dashboard session and the local CLI keep doing all of the above; with login on,
nothing changes.
Residual (no code change): keys or tokens minted anonymously before this fix carry no issuer
marker, so they stay valid — operators running with login disabled can review and revoke them in
the API Manager and under Settings → Access Tokens.
Refactor needed by the complexity ratchet: in
POST /api/keysthe create-time permissionflags moved into
createPermissionOverrides()— the same payload under the same conditions. Thegate pushed the handler past the max-lines limit, and the flag spread was most of its cyclomatic
weight; the handler now sits below both limits (4 violations in the touched files vs 5 on the base).
A route-level test pins the flags end to end and passes against the base route as well.
Tests
tests/unit/open-mode-management-credential-mint.test.ts— 16 cases; 9 RED on the base(the six rows above, by scope), 7 regression guards for the unchanged paths (inference-only keys,
session and local CLI, create-time permission flags).
tests/unit/cli-tokens-scope-escalation.test.ts: the case "with login disabled the instance isopen and admin can be minted" pinned the old behaviour (it passed on the base, 10/10). It now
asserts the new contract — anonymous
401with nothing persisted, the dashboard session stillmints
admin— and checks that open mode is actually in effect.requireManagementAuth,/api/keys*,/api/cli/tokens, access tokens or the operator credential (101 files) — see the validationsection.
Docs
docs/architecture/AUTHZ_GUIDE.mdanddocs/guides/REMOTE-MODE.mdstated that login disabledlets anyone mint an
adminCLI token (and issue a sync token); both now describe the verifiedbehaviour. The i18n mirrors need a refresh once the translation backend is back —
REMOTE-MODE.mdwas already out of date in.i18n-state.jsonon the base(
remote-token-privilege-localesis part of the inherited red set).Validation
RUN_CONTRACT_INT=1).check:openapi-security-tiersPASS;check:doc-links,check:fabricated-docsandcheck:docs-symbolsPASS.tests/helpers/managementSession.ts,outside the diff).
upstream-error-call-log-16558,mutation-test-coverage, …), identical on unrelated PRs.