HttpApiClient: a path parameter of `.` or `..` changes the request path
Maintainers usually reply within 1 day
@effect-bot is already working on this.
Since Oct 22, 2026.
Assessment
This issue has not been assessed yet.
Description
HttpApiClient puts each path parameter into the URL with encodeURIComponent. That function leaves . and .. unchanged, so a parameter whose value is . or .. becomes a dot segment. The URL parser then resolves it, and the request goes to a different path than the endpoint's.
const Api = HttpApi.make("Api").add(
HttpApiGroup.make("users").add(
HttpApiEndpoint.get("get", "/users/:id", { params: { id: Schema.String } }),
HttpApiEndpoint.delete("remove", "/users/:id/sessions", { params: { id: Schema.String } })
)
)
const client = yield* HttpApiClient.make(Api, { baseUrl: "http://127.0.0.1:3000/api/v1" })
yield* client.users.get({ params: { id: ".." } })
yield* client.users.remove({ params: { id: ".." } })
A local node:http server receives these requests, and both FetchHttpClient and NodeHttpClient send the same ones:
id |
get |
remove |
|---|---|---|
"." |
GET /api/v1/users/ |
DELETE /api/v1/users/sessions |
".." |
GET /api/v1/ |
DELETE /api/v1/sessions |
So an ID that comes from user input can send a DELETE to a different resource. I found this while building a Docker Engine client: containers.inspect({ id: "." }) calls the list endpoint /containers/json. A value like ../admin is safe, because encodeURIComponent encodes the /.
Cause
compilePath builds the URL for both HttpApiClient.make and the URL builder (line 793).
Percent-encoding the dots doesn't help. WHATWG URL also treats %2e, .%2e, %2e. and %2e%2e as dot segments, in either case. For example, new URL("http://x/a/%2E%2E/b").pathname is /b. No encoding of . or .. survives URL, so the client can't send one as a path segment.
Proposal
Reject a path parameter whose value is exactly . or .. before sending the request, the same way a missing required parameter is rejected today. Rust's Docker client bollard does the same for its path parameters.
Whether this should be a defect, like the missing-parameter Error, or a typed failure is a maintainer decision.
- Dominant language
- TypeScript
- Stars
- 16.7k
- Forks
- 808
- Avg merge
- 11h 24m
- Merged PRs (30d)
- 848
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Effect-TS/effect
-
Support the `openapi-3.0` target in `Schema.toStandardJSONSchemaV1`Possibly taken @MichaelDeBoey claimed this today. Openwontfix
Difficulty 4/5 3-5 days Newbie friendliness 48/100
Maintainers usually reply within 1 day
-
RpcClient.layerProtocolWorker: what's the equivalent of Piscina's abortable tasks? (terminate a stuck worker on interrupt, control respawn)Possibly taken @effect-bot claimed this 7 days ago. Open
Effect-TS/effect#9332 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 45/100
Effect-TS/effect#8501 · 3 comments ·
Maintainers usually reply within 1 day
-
McpServer stdio: can an MCP client reach the `@effect/rpc/*` control methods? `@effect/rpc/Eof` stops the server silentlyPossibly taken @IMax153 claimed this 28 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 25/100
Maintainers usually reply within 1 day
-
Native TCP transport for @effect/sql-clickhouse-nativeMay be free again A pull request for this issue was closed without being merged. Openenhancement
Difficulty 5/5 Over a week Newbie friendliness 30/100
Effect-TS/effect#8343 · 1 comment ·
Maintainers usually reply within 1 day
All issues in Effect-TS/effect
Similar issues
-
area:agent-view area:tui bug platform:macos
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
anthropics/claude-code#104558 ·
Maintainers usually reply within 1 day
-
updater
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
UniversityOfHelsinkiCS/oodikone#5141 ·
-
maintanance
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
inmanta/web-console#7606 ·
Maintainers usually reply within 1 day
-
bug skills
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
equinor/fusion-framework#5846 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 74/100