From 72da79cf18564d07d6f6bac80b819e41a1b95aa7 Mon Sep 17 00:00:00 2001 From: Brent Rockwood Date: Mon, 18 May 2026 23:42:52 -0400 Subject: [PATCH 1/5] fix: upgrade happy-dom and pin transitive deps to fix known CVEs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses three advisories identified by npm audit: - @happy-dom/global-registrator: ^15.11.0 → ^20.9.0 GHSA-37j7-fg3j-429f (critical) — VM context escape → RCE GHSA-6q6h-j7hj-3r64 (high) — unsanitized export names executed as code GHSA-w4gp-fjgq-3q4g (high) — fetch credentials leak - rollup (transitive, via overrides): 3.29.5 → 3.30.0 GHSA-mw96-cpmx-2vgc (high) — arbitrary file write via path traversal - postcss (transitive, via overrides): 8.5.6 → 8.5.14 GHSA-qx2v-qp2m-jg93 (moderate) — XSS via unescaped in output happy-dom v20 requires a document URL when using relative-URL fetch calls, so GlobalRegistrator.register() is updated to pass url: 'http://localhost/' as recommended by the library. Test pass/fail counts are unchanged (38/293 failures are all pre-existing and caused by the absent WASM build artifact). Co-Authored-By: Claude Sonnet 4.6 --- bun.lock | 34 ++++++++++++++++++++-------------- happydom.ts | 2 +- package.json | 6 +++++- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/bun.lock b/bun.lock index 557c739b..9303df7d 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,7 @@ "name": "@cmux/ghostty-terminal", "devDependencies": { "@biomejs/biome": "^1.9.4", - "@happy-dom/global-registrator": "^15.11.0", + "@happy-dom/global-registrator": "^20.9.0", "@types/bun": "^1.3.2", "@xterm/headless": "^5.5.0", "@xterm/xterm": "^5.5.0", @@ -18,6 +18,10 @@ }, }, }, + "overrides": { + "postcss": "^8.5.10", + "rollup": "^3.30.0", + }, "packages": { "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], @@ -89,7 +93,7 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], - "@happy-dom/global-registrator": ["@happy-dom/global-registrator@15.11.7", "", { "dependencies": { "happy-dom": "^15.11.7" } }, "sha512-mfOoUlIw8VBiJYPrl5RZfMzkXC/z7gbSpi2ecycrj/gRWLq2CMV+Q+0G+JPjeOmuNFgg0skEIzkVFzVYFP6URw=="], + "@happy-dom/global-registrator": ["@happy-dom/global-registrator@20.9.0", "", { "dependencies": { "@types/node": ">=20.0.0", "happy-dom": "^20.9.0" } }, "sha512-lBW6/m5BIFl3pMuWPNN0lIOYw9LMCmPfix53ExS3FBi4E+NELEljQ3xH6aAV9IYiQRfn9YIIgzzMrD0vIcD7tw=="], "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], @@ -123,10 +127,14 @@ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - "@types/node": ["@types/node@20.19.25", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ=="], + "@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="], "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="], + "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], + + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + "@volar/language-core": ["@volar/language-core@2.4.23", "", { "dependencies": { "@volar/source-map": "2.4.23" } }, "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ=="], "@volar/source-map": ["@volar/source-map@2.4.23", "", {}, "sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q=="], @@ -177,7 +185,7 @@ "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], - "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], "esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], @@ -195,7 +203,7 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - "happy-dom": ["happy-dom@15.11.7", "", { "dependencies": { "entities": "^4.5.0", "webidl-conversions": "^7.0.0", "whatwg-mimetype": "^3.0.0" } }, "sha512-KyrFvnl+J9US63TEzwoiJOQzZBJY7KgBushJA8X61DMbNsH+2ONkDuLDnCnwUiPTF42tLoEmrPyoqbenVA5zrg=="], + "happy-dom": ["happy-dom@20.9.0", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.18.3" } }, "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ=="], "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], @@ -247,7 +255,7 @@ "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + "postcss": ["postcss@8.5.14", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg=="], "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], @@ -259,7 +267,7 @@ "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], - "rollup": ["rollup@3.29.5", "", { "optionalDependencies": { "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w=="], + "rollup": ["rollup@3.30.0", "", { "optionalDependencies": { "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kQvGasUgN+AlWGliFn2POSajRQEsULVYFGTvOZmK06d7vCD+YhZztt70kGk3qaeAXeWYL5eO7zx+rAubBc55eA=="], "semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], @@ -281,7 +289,7 @@ "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], - "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], @@ -293,26 +301,24 @@ "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], - "webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="], - "whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], + "ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="], + "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], "@microsoft/api-extractor/typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], "@rushstack/node-core-library/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="], + "@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "@vue/language-core/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "ajv-formats/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="], - "bun-types/@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="], - "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], - "bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], } } diff --git a/happydom.ts b/happydom.ts index c2b92eee..7b8dd848 100644 --- a/happydom.ts +++ b/happydom.ts @@ -12,7 +12,7 @@ import { GlobalRegistrator } from '@happy-dom/global-registrator'; // Register Happy DOM globals (window, document, etc.) -GlobalRegistrator.register(); +GlobalRegistrator.register({ url: 'http://localhost/' }); // Mock Canvas 2D Context // Happy DOM doesn't provide canvas rendering APIs, so we mock them for testing. diff --git a/package.json b/package.json index 0b93caba..6357f3e6 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,10 @@ "publishConfig": { "access": "public" }, + "overrides": { + "rollup": "^3.30.0", + "postcss": "^8.5.10" + }, "scripts": { "dev": "vite --port 8000", "demo": "node demo/bin/demo.js", @@ -63,7 +67,7 @@ }, "devDependencies": { "@biomejs/biome": "^1.9.4", - "@happy-dom/global-registrator": "^15.11.0", + "@happy-dom/global-registrator": "^20.9.0", "@types/bun": "^1.3.2", "@xterm/headless": "^5.5.0", "@xterm/xterm": "^5.5.0", From 18e98d95a16c057ce546870249f5d5e3fee68588 Mon Sep 17 00:00:00 2001 From: Brent Rockwood Date: Mon, 18 May 2026 23:58:43 -0400 Subject: [PATCH 2/5] chore: pin dependency versions exactly and add devcontainer Security hardening on top of the CVE fixes: - Remove ^ ranges from @happy-dom/global-registrator, rollup override, and postcss override so lockfile regeneration cannot silently pull in a newer (potentially compromised) version. - Add .devcontainer/devcontainer.json for DevPod / VS Code Dev Containers. The container image is pinned by SHA256 content digest (not just tag). postCreateCommand enables Nix flakes, initializes the git submodule, and pre-populates the Nix store from flake.lock so `nix develop` is instant. All downloads inside the container are hash-verified by Nix against flake.lock, including the pinned Zig 0.15.2 toolchain. Co-Authored-By: Claude Sonnet 4.6 --- .devcontainer/devcontainer.json | 37 +++++++++++++++++++++++++++++++++ bun.lock | 8 +++---- package.json | 6 +++--- 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..e267e476 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,37 @@ +{ + "name": "ghostty-web", + + // Pinned by content digest, not just tag — verify with: + // docker pull nixpkgs/nix:latest + // docker inspect nixpkgs/nix:latest --format '{{index .RepoDigests 0}}' + "image": "nixpkgs/nix@sha256:79397901292ed23c3502177552e4d261c2d711720185e2b3a5beb715f35f595b", + + "postCreateCommand": [ + "sh", "-c", + // 1. Enable flakes globally in the container + "mkdir -p /etc/nix && echo 'experimental-features = nix-command flakes' > /etc/nix/nix.conf && " + // 2. Pull in the Ghostty source (submodule). All objects are verified + // against the commit hash recorded in .gitmodules / git index. + + "git submodule update --init --recursive && " + // 3. Pre-populate the Nix store so `nix develop` is instant afterwards. + // All downloads are hash-verified against flake.lock. + + "nix develop --command echo 'Nix store pre-populated — run nix develop to enter the shell'" + ], + + "customizations": { + "vscode": { + "extensions": [ + "ziglang.vscode-zig", + "biomejs.biome" + ] + } + }, + + // Mount SSH agent so git operations inside the container work + "mounts": [ + "source=${localEnv:SSH_AUTH_SOCK},target=/ssh-agent,type=bind,consistency=cached" + ], + "remoteEnv": { + "SSH_AUTH_SOCK": "/ssh-agent" + } +} diff --git a/bun.lock b/bun.lock index 9303df7d..8d2389cf 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,7 @@ "name": "@cmux/ghostty-terminal", "devDependencies": { "@biomejs/biome": "^1.9.4", - "@happy-dom/global-registrator": "^20.9.0", + "@happy-dom/global-registrator": "20.9.0", "@types/bun": "^1.3.2", "@xterm/headless": "^5.5.0", "@xterm/xterm": "^5.5.0", @@ -19,8 +19,8 @@ }, }, "overrides": { - "postcss": "^8.5.10", - "rollup": "^3.30.0", + "postcss": "8.5.10", + "rollup": "3.30.0", }, "packages": { "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], @@ -255,7 +255,7 @@ "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], - "postcss": ["postcss@8.5.14", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg=="], + "postcss": ["postcss@8.5.10", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ=="], "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], diff --git a/package.json b/package.json index 6357f3e6..52637aa7 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,8 @@ "access": "public" }, "overrides": { - "rollup": "^3.30.0", - "postcss": "^8.5.10" + "rollup": "3.30.0", + "postcss": "8.5.10" }, "scripts": { "dev": "vite --port 8000", @@ -67,7 +67,7 @@ }, "devDependencies": { "@biomejs/biome": "^1.9.4", - "@happy-dom/global-registrator": "^20.9.0", + "@happy-dom/global-registrator": "20.9.0", "@types/bun": "^1.3.2", "@xterm/headless": "^5.5.0", "@xterm/xterm": "^5.5.0", From c3c7f10bd5ba95c6fd383b32898e2b46f21306a9 Mon Sep 17 00:00:00 2001 From: Brent Rockwood Date: Tue, 19 May 2026 00:05:42 -0400 Subject: [PATCH 3/5] fix(devcontainer): remove SSH mount, strip JSON comments The SSH_AUTH_SOCK bind mount failed on macOS where the socket path is inside a sandboxed temp directory Docker can't reach. Removing it keeps the devcontainer portable. The // comments also caused a JSON parse error in DevPod; devcontainer.json is strict JSON, not JSONC. Co-Authored-By: Claude Sonnet 4.6 --- .devcontainer/devcontainer.json | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e267e476..70a19b29 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,23 +1,7 @@ { "name": "ghostty-web", - - // Pinned by content digest, not just tag — verify with: - // docker pull nixpkgs/nix:latest - // docker inspect nixpkgs/nix:latest --format '{{index .RepoDigests 0}}' "image": "nixpkgs/nix@sha256:79397901292ed23c3502177552e4d261c2d711720185e2b3a5beb715f35f595b", - - "postCreateCommand": [ - "sh", "-c", - // 1. Enable flakes globally in the container - "mkdir -p /etc/nix && echo 'experimental-features = nix-command flakes' > /etc/nix/nix.conf && " - // 2. Pull in the Ghostty source (submodule). All objects are verified - // against the commit hash recorded in .gitmodules / git index. - + "git submodule update --init --recursive && " - // 3. Pre-populate the Nix store so `nix develop` is instant afterwards. - // All downloads are hash-verified against flake.lock. - + "nix develop --command echo 'Nix store pre-populated — run nix develop to enter the shell'" - ], - + "postCreateCommand": "mkdir -p /etc/nix && echo 'experimental-features = nix-command flakes' > /etc/nix/nix.conf && git submodule update --init --recursive && nix develop --command echo 'Nix store ready'", "customizations": { "vscode": { "extensions": [ @@ -25,13 +9,5 @@ "biomejs.biome" ] } - }, - - // Mount SSH agent so git operations inside the container work - "mounts": [ - "source=${localEnv:SSH_AUTH_SOCK},target=/ssh-agent,type=bind,consistency=cached" - ], - "remoteEnv": { - "SSH_AUTH_SOCK": "/ssh-agent" } } From 5d37dadfdbd63ec38d0c0a60e583d0ac0e01e832 Mon Sep 17 00:00:00 2001 From: Brent Rockwood Date: Tue, 19 May 2026 03:17:31 -0400 Subject: [PATCH 4/5] chore: remove devcontainer (kept out of scope for this PR) Co-Authored-By: Claude Sonnet 4.6 --- .devcontainer/devcontainer.json | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 70a19b29..00000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "ghostty-web", - "image": "nixpkgs/nix@sha256:79397901292ed23c3502177552e4d261c2d711720185e2b3a5beb715f35f595b", - "postCreateCommand": "mkdir -p /etc/nix && echo 'experimental-features = nix-command flakes' > /etc/nix/nix.conf && git submodule update --init --recursive && nix develop --command echo 'Nix store ready'", - "customizations": { - "vscode": { - "extensions": [ - "ziglang.vscode-zig", - "biomejs.biome" - ] - } - } -} From 61d60382dee80c335eb7588991b4caf6420ffa98 Mon Sep 17 00:00:00 2001 From: Brent Rockwood Date: Tue, 19 May 2026 04:02:26 -0400 Subject: [PATCH 5/5] chore: ignore .devcontainer/ in gitignore Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 722d3337..6207ec46 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ dist/ # WASM build output (built locally and in CI) ghostty-vt.wasm + +# Local dev container config (not part of the project) +.devcontainer/