Public: anyone can read this; the crew can change it.
The pill's tell carries the page without its #fragment #2316
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/2311-the-pill-s-tell-carries-the-page-without → main 1 commit fork 1 thread · 1 unresolved
2 files
changed +17
−0
src/actions/tell_context.ts +3
| @@ -30,6 +30,9 @@ export function parseContext(v: unknown): TellContext | undefined | null { | ||
| 30 | 30 | : null; |
| 31 | 31 | if (url === null || (url.protocol !== "http:" && url.protocol !== "https:")) |
| 32 | 32 | return null; |
| 33 | // A fragment holds client-only state (tokens, invite keys); the issue | |
| 34 | // body may be public, so it never travels. | |
| 35 | url.hash = ""; | |
| 33 | 36 | out.page = url.href; |
| 34 | 37 | } |
| 35 | 38 | if (o["run"] !== undefined) { |
test/tell-context.test.ts added +14
| @@ -0,0 +1,14 @@ | ||
| 1 | import { expect, test } from "bun:test"; | |
| 2 | import { contextNote, parseContext } from "../src/actions/tell_context.ts"; | |
| 3 | ||
| 4 | test("a page told with a #fragment is told without it", () => { | |
| 5 | const c = parseContext({ page: "https://app.example.test/a?b=1#access_token=secret" }); | |
| 6 | expect(c).toEqual({ page: "https://app.example.test/a?b=1" }); | |
| 7 | expect(contextNote(c ?? undefined)).not.toContain("secret"); | |
| 8 | }); | |
| 9 | ||
| 10 | test("a page without a fragment is kept as it was", () => { | |
| 11 | expect(parseContext({ page: "https://app.example.test/a" })).toEqual({ | |
| 12 | page: "https://app.example.test/a", | |
| 13 | }); | |
| 14 | }); |
new above
offline
Good place for it. Next step: also clear url.search, or the same leak reappears through the query string.