Repository navigation
Description
Problem
The CodeMode fetch shim's response-headers wrapper reads a plain object without own-property checks, so a header that is absent can read as present when its (lowercased) name collides with an Object.prototype member.
packages/core/src/codemode/web.ts:23,32-33:
const headers = Object.fromEntries(response.headers)
// ...
get: (name: string) => headers[name.toLowerCase()] ?? null,
has: (name: string) => name.toLowerCase() in headers,Object.fromEntries produces a plain object with Object.prototype in its chain, and neither get ([] lookup) nor has (in operator) distinguishes own from inherited properties. The lookup is lowercased first, so the affected names are the all-lowercase prototype members: constructor and __proto__.
Verified evidence (main f58571a052, laptop probe of the real module)
Probe: ~/git/fleet/probe-2026-10-28-creator-opencode2/probe-codemode-headers.ts (laptop) — imports the real extension from packages/core/src/codemode/web.ts, calls its fetch global against a local Bun.serve server whose response carries only content-type: text/plain and x-real: yes:
headers.get("content-type")→"text/plain",has→true(correct)headers.get("x-real")→"yes",has→true(correct)headers.get("x-absent")→null,has→false(correct)headers.get("constructor")→function Object() { [native code] }(a function, not a string/null),has("constructor")→true— header is absentheaders.get("__proto__")→[object Object](an object),has("__proto__")→true— header is absent
(toString / hasOwnProperty / valueOf are not affected only because the lookup lowercases them to non-member spellings — tostring, hasownproperty, valueof.)
Why it matters
This fetch is the web surface exposed to CodeMode programs (model-written scripts executed via the extension at web.ts:38). A script that branches on headers.has("constructor"), or that reads a header value and treats it as a string (get(...) is typed/expected to return string | null), instead receives the Object constructor function or Object.prototype — a truthy non-string that poisons downstream string operations and presence checks, for a header the server never sent. The real Headers API this shim mirrors returns null / false for every absent name.
Fix direction
Make the wrapper own-property-safe: build the record with a null prototype (Object.assign(Object.create(null), …) / Object.fromEntries into a null-prototype object) or guard both accessors with Object.hasOwn(headers, key). Keep entries() behavior unchanged.
Acceptance criteria
- For a response without those headers,
headers.get("constructor")andheaders.get("__proto__")returnnull, andheaders.has(...)returnsfalsefor both. - Headers actually sent (including, if a server sends one, a header literally named
constructor) still return their real string values fromgetandtruefromhas. -
entries()output is unchanged. - A test exercises the CodeMode web fetch wrapper (or its header record) against a response lacking prototype-named headers and pins the two names above.
Activity
developing-today commentedon Oct 29, 2026
OPENCODE-177
dezren39 commentedon Oct 29, 2026
🤖 Agent note · filed
5 remaining items
dezren39 commentedon Oct 29, 2026
CI re-check by queue worker (lane B): PR #808 is MERGEABLE, but its checks are still QUEUED / IN_PROGRESS ~35 minutes after opening (fleet runner backlog — the same congestion affecting PRs #806/#810). No check has failed on this change; the only completed non-neutral results are CANCELLED pr-standards runs whose replacements are queued.
Task 2969 re-parked 30m. Resume: if CI is green (or fails only on pre-existing unrelated tests), merge PR #808 per the standing directive and complete the task.
dezren39 commentedon Oct 29, 2026
🤖 Agent note · state: parked (PR #808, awaiting CI rerun)
c78fc9b120. First CI run's only failures were the unit: two permission-focus tests fail on linux + windows (pre-existing) #565packages/tuipermission pair (this PR's diff ispackages/corecodemode only; laptop codemode suite 26/26, new web.test.ts discriminating). Failed jobs were rerun (run 40803546681, attempt 2) at 03:10Z; at this shift's check (~04:12Z) the rerun was still queued/in-progress in the CI backlog — build (windows) running, unit (linux) and e2e queued. Typecheck, build (linux), nix-eval, compliance/standards all pass.Merge pull request #808 from developing-today/queue/2969-805-codemode…
dezren39 commentedon Oct 29, 2026
Merged via PR #808 (merge commit
9a8652bcaeddc6015f1d3e34521f71cf59490308); this issue auto-closed by the merge. CI at headd5cd8372: typecheck, build (linux+windows), e2e (linux+windows), nix-eval, and pr-standards green. Unit (linux+windows) failed only on the pre-existing #565 tui permission pair (fixed on main by PR #789; this branch was 27 commits behind main) plus an unrelated Windows debug-paths 30s timeout; the diff is codemode-only (packages/core/src/codemode/web.ts+ newweb.test.ts) and was verified sound before merging under the standing merge directive. Queue task 2969 completed.agent-note:v1 agent=repo-queue-worker-shift-opencode lane=A task=2969 state=complete pr=#808