Skip to content

fix(wallet): ship the security headers config in the build output - #683

Merged
aterga merged 2 commits into
mainfrom
fix/wallet-ship-ic-assets-config
Nov 10, 2026
Merged

aterga merged 2 commits into
mainfrom
fix/wallet-ship-ic-assets-config

Conversation

@aterga

@aterga aterga commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

Summary

The wallet's security headers never reach the canister when it is deployed from a release artifact. app.orbit.global (and playground.orbitwallet.io) currently serve no Content-Security-Policy, X-Frame-Options, X-Content-Type-Options or Referrer-Policy, and none of the cache rules from the wallet's asset config apply. orbit.global and docs.orbit.global, whose .ic-assets.json is committed, serve theirs.

Cause

with-ic-assets generates .ic-assets.json in its writeBundle hook and wrote it to apps/wallet/public/. Vite copies public/ into the output before that hook runs, so the file only reached the output of a later build on the same machine. A clean build, such as the deterministic Docker build behind every release, never contains it. The 0.8.1 release tarball has no .ic-assets.json, so scripts/deploy-app uploads the assets without headers.

Changes

  • with-ic-assets.plugin.ts: write .ic-assets.json into the build output (dir), next to the assets it configures. The publicDir option is dropped; nothing passed it.
  • with-versioned-entrypoint.plugin.ts: don't copy a leftover public/.ic-assets.json (from builds before this change) into dist/v<version>/. A nested config there would override the root one for the versioned UI.
  • with-ic-assets.plugin.spec.ts: new tests. The file is written into the output, sets X-Frame-Options: DENY, nosniff, a CSP with default-src 'none' and frame-ancestors 'none', and allows inline scripts of index.html by hash.

The released index.html and v0.8.1/index.html contain no inline scripts, so the root CSP applies to the versioned UIs unchanged.

Testing

  • New unit tests (run in CI; dependencies could not be installed in the environment this was written in).
  • The deterministic build artifact from this PR's CI should contain .ic-assets.json at its root.
  • After the next wallet release: deploy to playground first and check that the app still works under the CSP (it has not been enforced on deployed builds for a while), and that the headers are present, before production.

Generated by Claude Code

The with-ic-assets plugin generated .ic-assets.json into apps/wallet/public
from the writeBundle hook. Vite copies public/ before that hook runs, so a
clean build never had the file in its output, and the deterministic release
artifact never carried it. Deploys of that artifact therefore uploaded the
wallet without its headers: app.orbit.global serves no Content-Security-Policy,
X-Frame-Options, X-Content-Type-Options or Referrer-Policy, and none of the
cache rules apply.

Write the file into the build output instead, and keep a leftover copy in
public/ out of the versioned UI directory, where it would override the root
config. Add a test for the plugin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VP2vTHJDxWCtmbSkf3682e
Copilot AI balanced review requested due to automatic review settings November 10, 2026 14:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The enforced connect-src policy blocks both WASM chunk store subdomains, causing registry-based disaster recovery to fail before WASM and Candid can be loaded.

1 open issue
What changed in this PR

This PR ensures clean wallet builds include the asset configuration needed to apply security headers and cache rules when deploying release artifacts.

Changes:

  • Write .ic-assets.json directly into the build output and remove the unused publicDir option.
  • Exclude stale asset configuration files when copying public assets into versioned directories.
  • Add unit tests for output placement, security headers, and inline-script hashes.
File Description
apps/​wallet/​build/​plugins/​with-versioned-entrypoint.plugin.ts Prevent stale nested asset configurations from overriding the root configuration.
apps/​wallet/​build/​plugins/​with-ic-assets.plugin.ts Generate the asset configuration directly in the build output.
apps/​wallet/​build/​plugins/​with-ic-assets.plugin.spec.ts Test configuration generation and security policy contents.

Review effort: Balanced

@aterga
aterga marked this pull request as ready for review November 10, 2026 15:02
@aterga
aterga requested a review from a team as a code owner November 10, 2026 15:02
Disaster recovery downloads registry modules from the wasm chunk store's HTTP
interface at https://<store>.icp0.io. The host source https://icp0.io does not
match subdomains, so once the CSP is actually served the download is blocked.
Allow the production and playground chunk stores, and test that every
wasm_chunk_store in canister_ids.json is allowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VP2vTHJDxWCtmbSkf3682e
Copilot AI balanced review requested due to automatic review settings November 10, 2026 15:03
@zeropath-ai

zeropath-ai Bot commented Nov 10, 2026

Copy link
Copy Markdown

✅ No security or compliance issues detected. Reviewed everything up to 13b4396.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► apps/wallet/build/plugins/with-ic-assets.plugin.ts
    Implement Vercel OAuth Flow
Enhancement ► apps/wallet/build/plugins/with-versioned-entrypoint.plugin.ts
    Adjust copy behavior to exclude .ic-assets.json5?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Activating the previously unenforced wallet CSP requires release-artifact and deployed-header checks plus playground browser validation of login, versioned navigation, and disaster-recovery downloads, since unit tests alone cannot establish runtime compatibility.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@aterga
aterga enabled auto-merge (squash) November 10, 2026 15:38
@sea-snake
sea-snake disabled auto-merge November 10, 2026 16:04
@sea-snake sea-snake closed this Nov 10, 2026
@sea-snake sea-snake reopened this Nov 10, 2026
@aterga
aterga enabled auto-merge (squash) November 10, 2026 16:14
@aterga
aterga disabled auto-merge November 10, 2026 16:30
@aterga
aterga merged commit 8826c38 into main Nov 10, 2026
59 checks passed
@aterga
aterga deleted the fix/wallet-ship-ic-assets-config branch November 10, 2026 16:30
aterga pushed a commit that referenced this pull request Nov 10, 2026
The cut was forced with `patch` because nx 19.8.3 does not attribute
squash-merged commits whose message contains GitHub's "---------"
co-author separator, so nx wrote "no code changes". This restores #683
in the CHANGELOG and in the release notes in .release.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VP2vTHJDxWCtmbSkf3682e
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.

4 participants