Skip to content

Commit 7c75568

Browse files
Zexiclaude
authored andcommitted
fix: return 401 from /global/health when credentials are provided but invalid
Unauthenticated probes still get 200 so the SPA can discover the server before the user has entered any credentials. But when an SDK or health-check supplies explicit credentials that do not match, the endpoint now returns 401. This makes the server-list health indicator accurately reflect auth status instead of showing green even when the configured password is wrong. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ff2e1a6 commit 7c75568

1 file changed

Lines changed: 13 additions & 3 deletions

File tree

packages/opencode/src/server/routes/instance/httpapi/middleware/authorization.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,19 @@ export const authorizationLayer = Layer.effect(
153153
return Authorization.of((effect) =>
154154
Effect.gen(function* () {
155155
const request = yield* HttpServerRequest.HttpServerRequest
156-
// Health endpoint must be public so the SPA can render before credentials
157-
// are configured — otherwise the user can never reach the credential UI.
158-
if (new URL(request.url, "http://localhost").pathname === "/global/health") return yield* effect
156+
if (new URL(request.url, "http://localhost").pathname === "/global/health") {
157+
// Allow unauthenticated probes so the SPA can discover the server before
158+
// the user has entered credentials. But if credentials ARE supplied and
159+
// wrong, return 401 — otherwise the health indicator stays green even
160+
// when the configured password is incorrect.
161+
const credential = yield* credentialFromRequest(request)
162+
const hasCredentials = !!credential.username || Redacted.value(credential.password).length > 0
163+
if (!hasCredentials || ServerAuth.authorized(credential, config)) return yield* effect
164+
yield* HttpEffect.appendPreResponseHandler((_request, response) =>
165+
Effect.succeed(HttpServerResponse.setHeader(response, "www-authenticate", WWW_AUTHENTICATE)),
166+
)
167+
return yield* new HttpApiError.Unauthorized({})
168+
}
159169
return yield* credentialFromRequest(request).pipe(
160170
Effect.flatMap((credential) => validateCredential(effect, credential, config)),
161171
)

0 commit comments

Comments
 (0)