Skip to content

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

Merged
tim-smart merged 2 commits into
Effect-TS:mainfrom
sam-goodwin:fix/httpapi-bearer-leading-space
Jun 1, 2026
Merged

fix(HttpApi): strip space delimiter when decoding bearer/http credentials#2306
tim-smart merged 2 commits into
Effect-TS:mainfrom
sam-goodwin:fix/httpapi-bearer-leading-space

Conversation

@sam-goodwin
Copy link
Copy Markdown
Contributor

@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: 4963a1f

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

IMax153
IMax153 previously approved these changes Jun 1, 2026
@IMax153
Copy link
Copy Markdown
Member

IMax153 commented Jun 1, 2026

@sam-goodwin - looks like there's a type error in CI.

Effect.provideService(HttpServerRequest.ParsedSearchParams, {})
)

describe("HttpApiSecurity", () => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also have a test that validates that credentials from a different scheme than the one specified are rejected.

See the tests in Julius' PR #2315

@tim-smart tim-smart enabled auto-merge (squash) June 1, 2026 21:07
@tim-smart tim-smart merged commit 4255c9b into Effect-TS:main Jun 1, 2026
14 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

Bundle Size Analysis

File Name Current Size Previous Size Difference
basic.ts 6.72 KB 6.72 KB 0.00 KB (0.00%)
batching.ts 9.23 KB 9.23 KB 0.00 KB (0.00%)
brand.ts 6.20 KB 6.20 KB 0.00 KB (0.00%)
cache.ts 9.70 KB 9.70 KB 0.00 KB (0.00%)
config.ts 18.40 KB 18.40 KB 0.00 KB (0.00%)
differ.ts 16.85 KB 16.85 KB 0.00 KB (0.00%)
http-client.ts 20.20 KB 20.20 KB 0.00 KB (0.00%)
logger.ts 10.18 KB 10.18 KB 0.00 KB (0.00%)
metric.ts 8.56 KB 8.56 KB 0.00 KB (0.00%)
optic.ts 7.37 KB 7.37 KB 0.00 KB (0.00%)
pubsub.ts 13.80 KB 13.80 KB 0.00 KB (0.00%)
queue.ts 11.08 KB 11.08 KB 0.00 KB (0.00%)
schedule.ts 10.08 KB 10.08 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 26.24 KB 26.24 KB 0.00 KB (0.00%)
schema-string-transformation.ts 12.59 KB 12.59 KB 0.00 KB (0.00%)
schema-string.ts 10.34 KB 10.34 KB 0.00 KB (0.00%)
schema-template-literal.ts 13.94 KB 13.94 KB 0.00 KB (0.00%)
schema-toArbitraryLazy.ts 18.51 KB 18.51 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 21.13 KB 21.13 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 17.67 KB 17.67 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 17.61 KB 17.61 KB 0.00 KB (0.00%)
schema-toFormatter.ts 17.44 KB 17.44 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 19.96 KB 19.96 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 18.00 KB 18.00 KB 0.00 KB (0.00%)
schema.ts 17.05 KB 17.05 KB 0.00 KB (0.00%)
stm.ts 11.95 KB 11.95 KB 0.00 KB (0.00%)
stream.ts 9.25 KB 9.25 KB 0.00 KB (0.00%)

@sam-goodwin
Copy link
Copy Markdown
Contributor Author

Thanks @tim-smart for driving it home.

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 has extra space

3 participants