dfinity / dfinity/icp-cli-templates

Dev-server `ic_env` cookies collide between projects, because cookies ignore port

Open
#38 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
CSS
Stars
2
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Needs confirmation before acting — this follows from the template plus cookie scoping rules, I have not reproduced it. Filing it because if it holds, it bites more often than the duplicate-cookie case it was found alongside (dfinity/icp-js-core#1384).

The claim

All three frontend templates set the environment via a Set-Cookie response header on the Vite dev server:

hello-world/react-frontend/vite.config.ts:52 (identically in vue-frontend and svelte-frontend):

const server = {
  headers: {
    "Set-Cookie": `ic_env=${encodeURIComponent(
      `PUBLIC_CANISTER_ID:${CANISTER_NAME}=${canisterId}&ic_root_key=${rootKey}`
    )}; SameSite=Lax;`,
  },
  ...

Cookies provide no isolation by port (RFC 6265 §1: "cookies for a given host are shared across all the ports on that host"). So a dev server on localhost:5173 and another on localhost:5174 write to the same jar. With no Domain these are host-only cookies on localhost, and with no Path the default-path for a request to / is /.

Same name, same host, same path means the second write doesn't sit alongside the first — it replaces it. Two scaffolded projects running dev servers concurrently would therefore clobber each other, and whichever started last wins for both. The first project's tab reads the second project's PUBLIC_CANISTER_ID:backend and root key, so its calls go to a canister from an unrelated project.

Why no attribute change fixes it

  • Path=/ doesn't help — both are already at /, and that's what you want anyway.
  • Partitioned doesn't help — the partition key is the top-level site, and both are localhost.
  • Port cannot be expressed in any cookie attribute at all.

The transport is the problem, not its attributes. Deployed frontends are unaffected: those are served at http://<canister-id>.localhost:8000/, distinct hosts, correctly isolated. This is specific to the dev-server simulation of the asset canister's cookie.

Suggested direction

Have the dev server inject the environment through Vite's define (or import.meta.env) instead of a cookie. That's per-server by construction, so it's port-scoped for free, and it removes an ambient mutable value from local development. The trade-off is that the dev path stops being byte-identical to the deployed path, where the cookie is genuinely the right mechanism because the asset canister has no build step to inject into. @icp-sdk/core/agent/canister-env would still be the reader in production; only the dev-server simulation changes.

If keeping the cookie is preferred, the template could at least namespace it per project (ic_env_<project>) via the existing cookieName option on getCanisterEnv, which converts a silent wrong-canister into a clean "not found".

Repro sketch (unverified)

  1. Scaffold two projects from hello-world, deploy both to a local network.
  2. npm run dev in each — Vite picks 5173 and 5174.
  3. Open both in the same browser.
  4. Check document.cookie on each; expect a single ic_env carrying the later project's canister id.
  5. Expect the first project's calls to target the wrong backend.

Worth running before deciding anything. If the collision doesn't reproduce, close this.

Context

Found while scoping dfinity/icp-js-core#1384 (getCanisterEnv taking the first of several ic_env cookies). That one is being fixed in dfinity/icp-js-core#1386, but the fix does not cover this: here there is only ever one cookie, so nothing conflicts — the single value is simply the wrong project's.

The same pattern appears in ~35 vite.config.js files in dfinity/examples and one in dfinity/icp-cli/examples/, so whatever is decided here should propagate there.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the two-project scenario from the issue, using the Vite configuration at hello-world/react-frontend/vite.config.ts and its matching Vue and Svelte files. Check document.cookie and the first project's backend calls, then inspect the ~35 vite.config.js files noted in the issue. Done means the collision is confirmed or rejected and the chosen dev-server change is consistently applied.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript, vite
Domain
frontend, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.