Skip to content

fix(HttpApi): strip space delimiter when decoding bearer/http credentials#2306

Open
sam-goodwin wants to merge 1 commit into
Effect-TS:mainfrom
sam-goodwin:fix/httpapi-bearer-leading-space
Open

fix(HttpApi): strip space delimiter when decoding bearer/http credentials#2306
sam-goodwin wants to merge 1 commit into
Effect-TS:mainfrom
sam-goodwin:fix/httpapi-bearer-leading-space

Conversation

@sam-goodwin
Copy link
Copy Markdown

@sam-goodwin sam-goodwin commented May 29, 2026

Closes #2305

securityDecode slices schemeLength off the Authorization header, but the header is "<scheme> <credential>" — so the single space separating the scheme from the credential stays attached to the decoded value. Every bearer/http credential decodes with a leading space (basic is unaffected — it still uses the basicLen = "Basic ".length constant).

- (request) => Redacted.make((request.headers.authorization ?? "").slice(self.schemeLength)) as any
+ (request) => Redacted.make((request.headers.authorization ?? "").slice(self.schemeLength + 1)) as any
// before:  "Bearer abc123".slice("Bearer".length /* 6 */) === " abc123"
// after:   "Bearer abc123".slice("Bearer".length + 1 /* 7 */) === "abc123"

Regression

Introduced in 361ca30 (#2291, "Add HttpApiSecurity.http for passing custom schemes"), first released in effect@4.0.0-beta.73. That change replaced the hard-coded const bearerLen = `Bearer `.length (7, which included the delimiter space) with schemeLength: options.scheme.length (6) and slice(self.schemeLength), dropping the + 1. Bisection: beta.72 good, beta.73 bad.

Impact

Any HTTP API guarded by HttpApiSecurity.bearer (or a custom HttpApiSecurity.http({ scheme })) rejects valid credentials, because the server-side decoded token is one byte longer than what the client sent.

Test

Added HttpApiSecurity.test.ts exercising securityDecode for both bearer and a custom http scheme. Verified it fails on main (Received: " abc123") and passes with the fix.

…ials

`securityDecode` sliced `schemeLength` off the `Authorization` header, but
the header is `"<scheme> <credential>"`, so the single space separating the
scheme from the credential was left attached (e.g. `Bearer abc123` decoded to
`" abc123"`). Slice `schemeLength + 1` to skip the delimiter.

Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 29, 2026

🦋 Changeset detected

Latest commit: 2c353b1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 27 packages
Name Type
effect Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-node-shared Patch
@effect/platform-node Patch
@effect/vitest Patch
@effect/ai-anthropic Patch
@effect/ai-openai-compat Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/openapi-generator Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Http Bearer token

1 participant