Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).

## [0.78.1] - 2026-09-08

`web-content-extraction` skill の `@xmldom/xmldom` 脆弱性を解消(Dependabot alert #26)。

### Security
- **`@xmldom/xmldom` を脆弱性修正版へ更新(Dependabot #26)**: `defuddle@0.19.1` → `mathml-to-latex@1.8.0`(defuddle の optionalDependencies)経由の推移依存を 0.9.10 → 0.9.12 に更新(`mathml-to-latex` の `^0.9.10` 範囲内で lockfile のみ更新、`package.json` は変更なし)。GHSA-6gmq-8vp8-gcm6(Medium — `requireWellFormed` シリアライズ時に不正な `EntityReference.nodeName` を経由した XML フラグメント注入、影響範囲 `>=0.9.0 <=0.9.11`)を解消。本 skill が到達するのは `mathml-to-latex` が MathML の解析に使う `DOMParser` だけで、この advisory の対象である `XMLSerializer` は呼ばれないため実行経路そのものには該当しない。一方、同じ 0.9.12 には `DOMParser.parseFromString` から到達できる parser 側の DoS 修正(GHSA-965w-775f-mr7g: namespace 宣言の二次的メモリ増、GHSA-8344-3jmq-59r6: 重複属性 dedup の O(M²)、RAWTEXT 終了タグ欠落時の出力増幅など。upstream release notes 記載の repository advisory 計 11 件で、GitHub の global advisory DB にはまだ未登録)が含まれており、攻撃者由来の任意 Web ページの MathML を解析する本 skill の経路にはこちらが直接関係する
- `npm audit` を 0 件にし、skill 自身のテスト(node `--test` 47 件)と `npm ci` 整合を確認済み。`@xmldom/xmldom` は `update-deps.mjs` の直接対象ではなく `defuddle` 更新時に推移的にしか追従しないため、キット同梱の lockfile は advisory 対応として手動で更新した
- **既存インストールへの取り込み範囲**: fresh install と、`web-content-update` フックが一度も走っていない(deploy 時の lockfile が snapshot と一致する)インストールは `setup.sh --update` / 自動アップデートで 0.9.12 になる。フックが一度でも走ったインストールでは lockfile の `.packages` が runtime 所有として保持される(`lib/update.sh` の package pair merge)ため、更新後も 0.9.10 のまま残る。その場合は `cd ~/.claude/skills/web-content-extraction && npm update @xmldom/xmldom` で手動更新できる(`mathml-to-latex` の `^0.9.10` 範囲内なので `package.json` は変わらず、以後のアップデートでも保持される)。MDM 管理下は runtime bundle の再配布で更新される
- **MDM runtime bundle の期待 SHA256 ピンを更新**: `package-lock.json` の更新に伴い、`lib/deploy.sh`・`mdm/detect-mdm.sh`・`mdm/install-mdm.sh`・`docs/mdm/README.md`・関連テストの期待 lock ハッシュを `e235f673…` → `ddace3fb…` へ更新(`package.json` は不変のため package ハッシュ `711c13b0…` は変わらない)。**MDM 配布環境は新しいバンドルパス(`711c13b0…-ddace3fb…`)で root-owned runtime bundle を再ビルド・再配布する必要がある**(旧バンドルは検証で拒否される。v0.75.2 と同じ経路)

## [0.78.0] - 2026-09-07

### Added
Expand Down
6 changes: 3 additions & 3 deletions docs/mdm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ installer / detector の file / tree digest は同一の canonical walker を使
| `biome` | profile 解決後の `ENABLE_BIOME_HOOKS=true` | 対象ユーザー所有の `~/.local/lib/claude-code-starter-kit/biome/2.5.4` versioned private tree。architecture 固有の native `biome` と固定 `package.json` だけを含め、`~/.local/bin/biome` が exact `biome` を指すことも別 postcondition で束縛する |
| `node_runtime` | `safety_net` または `web_content_runtime` が必須 | `/Library/Application Support/ClaudeCodeStarterKit/runtime/node-v24.18.0-darwin-{arm64\|x64}` の公式 Node full tree(bundled npm 11.16.0 を含む)。root:wheel、upstream mode、ACL なし、group/other 書込不可とし、`~/.local/bin/node` が exact `bin/node` を指すことも別 postcondition で束縛する |
| `safety_net` | profile 解決後の `ENABLE_SAFETY_NET=true` | 対象ユーザー所有の `~/.local/lib/claude-code-starter-kit/cc-safety-net/1.0.6` versioned private tree。固定 JS / `package.json` と private Node を直接呼ぶ deterministic wrapper を含め、`~/.local/bin/cc-safety-net` が exact wrapper を指すことも別 postcondition で束縛する |
| `web_content_runtime` | profile 解決後の `INSTALL_SKILLS=true` | `/Library/Application Support/ClaudeCodeStarterKit/runtime/web-content-extraction/node-v24.18.0-npm-v11.16.0-darwin-{arm64\|x64}/711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1-e235f6738b9350d2c6fe6c64b4bfd8e458efcd47df6bb52dd30749ed2c7d45c4` の root-owned bundle tree。exact children は `.claude-code-starter-kit-wce-runtime.json`、`package.json`、`package-lock.json`、`node_modules`。bundle 内は全 entry が root:wheel、ACL なしで、symlink / 特殊ファイルを拒否する。directory は `0755`、top-level の3 regular files は `0644`、`node_modules` 内の regular file は `0644` / `0755`。xattr は `com.apple.provenance` だけを許可し、その値も tree digest に封印する。ユーザー側 `~/.claude/skills/web-content-extraction/node_modules` は対象 UID 所有、link count 1、ACL なしで bundle 内 `node_modules` への exact absolute symlink とする |
| `web_content_runtime` | profile 解決後の `INSTALL_SKILLS=true` | `/Library/Application Support/ClaudeCodeStarterKit/runtime/web-content-extraction/node-v24.18.0-npm-v11.16.0-darwin-{arm64\|x64}/711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1-ddace3fb92cc857f7fbcc73159fc68fb0438e1c03c1fe7dfcfd8ea654b994832` の root-owned bundle tree。exact children は `.claude-code-starter-kit-wce-runtime.json`、`package.json`、`package-lock.json`、`node_modules`。bundle 内は全 entry が root:wheel、ACL なしで、symlink / 特殊ファイルを拒否する。directory は `0755`、top-level の3 regular files は `0644`、`node_modules` 内の regular file は `0644` / `0755`。xattr は `com.apple.provenance` だけを許可し、その値も tree digest に封印する。ユーザー側 `~/.claude/skills/web-content-extraction/node_modules` は対象 UID 所有、link count 1、ACL なしで bundle 内 `node_modules` への exact absolute symlink とする |
| `ghostty` | `ENABLE_GHOSTTY_SETUP=true` の明示 opt-in。MDM による事前配布必須 | `/Applications/Ghostty.app` tree。Apple-anchored Developer ID requirement、identifier `com.mitchellh.ghostty`、Team ID `24VZTF6M5V`、`com.apple.quarantine` 不在を検証する。対象ユーザー権限では `/Applications` へ非対話 cask 導入できないため、`auto` / `fail` とも未配布または quarantine 残存なら失敗する |
| `fonts` | `ENABLE_FONTS_SETUP=true` の明示 opt-in | `~/Library/Fonts` の IBM Plex Mono 1.1.0 exact 16 TTF と HackGen NF 2.10.0 exact 4 TTF。filename、file SHA-256、sfnt 構造、family / version / PostScript name を検証して20個の file entry にする。その他の既存 font は保持し、managed inventory には含めない |

Expand All @@ -264,15 +264,15 @@ component digest は、固定 artifact の provenance gate を通過した live
- Biome 2.5.4 の `auto` は `https://registry.npmjs.org/@biomejs/cli-darwin-{arm64|x64}/-/cli-darwin-{arm64|x64}-2.5.4.tgz` を package manager で実行せず直接取得する。arm64 archive / binary / `package.json` SHA-256 は順に `befd5504c242b0174f9f57c9b2f2b14fd106c5f4568bee1b204d1369b890a688` / `1250bb41a0409cf6c3133fc47819237eb61251624297f87158d2bed3ec123c3c` / `54947a4827f0a6960d84eae39de98dba707b6f9222a276beaaa54ab4014dc68c`、x64 は `12e7076f80070aa085653f67fc1cb88f658253c67eb35677fab7c80c5aceb3cb` / `b3dfae5422dbd86272bb8ed40afec66670ea7754531d8fbcbae7e445e5430387` / `f25fac4d876cbd18fe78753dd06fde9a12607a76006546cf6a9549a8f1fb511f`。archive の inventory / member type を制限し、versioned private tree へ atomic に公開する。Homebrew、user PATH、既存 npm global tree は MDM baseline として受理しない。`fail` は通信・変更を行わず、同じ2-file tree と command symlink が事前配布済みの場合だけ受理する。
- Safety Net 1.0.6 の `auto` は `https://registry.npmjs.org/cc-safety-net/-/cc-safety-net-1.0.6.tgz`(SHA-256 `588a23f77637f34b99b6fcff68787b19d2cf692470c284ec633e982008b0a6ab`)を直接取得し、`dist/bin/cc-safety-net.js`(SHA-256 `1ffbfafabf2fe4fc9b6bf64a8088ca3a96c2714cf8fd8afd5b1b326582c982d4`)と `package.json`(SHA-256 `2e57b465553ba97e1e6f7a37655fc52e31cad4ca739140bb7af40d052e3d88c8`)だけを安全に抽出する。root-private Node の absolute path で JS を実行し `NODE_OPTIONS` / `NODE_PATH` を破棄する deterministic wrapper を生成して versioned private tree へ atomic に公開する。`fail` は通信・変更を行わず、この exact tree、wrapper、command symlink が事前配布済みの場合だけ受理する。
- `node_runtime` は architecture ごとの公式 Node v24.18.0 `.tar.xz` を固定する。URL は `https://nodejs.org/dist/v24.18.0/node-v24.18.0-darwin-{arm64|x64}.tar.xz`、arm64 SHA-256 は `4477b9f78efb77744cf5eb57a0e9594dba66466b38b4e93fa9f35cb907a095a6`、x64 は `4a3b6bc81542154430825128d9a279e8b364e8d90581544e506ef7579fd1ab6f`。`auto` はこの固定 HTTPS URLから root-private な同一 filesystem stage へ安全に展開し、tree metadata、exact version / architecture、system library だけへの依存、`bin/node` の Apple Developer ID requirement(identifier `node`、Team ID `HX7739G8FX`、Developer ID intermediate / leaf OID)を検証して atomic に公開する。`fail` は通信や tree 変更を行わず、同じ固定 tree が root trustbase に事前配布済みの場合だけ受理する。対象ユーザーの activation symlink は setup が作成・修復し、postcondition で再検証する。Homebrew / user-local Node は MDM runtime として受理しない。
- Web Content Extraction runtime は Node v24.18.0 / bundled npm 11.16.0、配布対象 commit の `package.json` SHA-256 `711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1`、`package-lock.json` SHA-256 `e235f6738b9350d2c6fe6c64b4bfd8e458efcd47df6bb52dd30749ed2c7d45c4`、現在の architecture を固定する。package / lock は private package、lockfile v3、exact registry tarball、SHA-512 integrity、install script / link なしの契約も満たす必要がある。
- Web Content Extraction runtime は Node v24.18.0 / bundled npm 11.16.0、配布対象 commit の `package.json` SHA-256 `711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1`、`package-lock.json` SHA-256 `ddace3fb92cc857f7fbcc73159fc68fb0438e1c03c1fe7dfcfd8ea654b994832`、現在の architecture を固定する。package / lock は private package、lockfile v3、exact registry tarball、SHA-512 integrity、install script / link なしの契約も満たす必要がある。
- `auto`: root 専用の stage、home、cache、tmp、空の user/global npm config を使う clean environment で、registry を `https://registry.npmjs.org/` に固定する。継承するネットワーク設定は構文検証済みの `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` だけとし、固定 Node / npm で `npm ci --omit=dev --ignore-scripts --no-bin-links --no-audit --no-fund` を実行する。npm 補助物 `node_modules/.package-lock.json` は必須にせず、存在しても許容する。bundle 内 symlink / 特殊ファイルを全面拒否し、exact source files、非空の `node_modules`、root direct dependency ごとの directory と regular `package.json` の存在、canonical schema v1 marker、metadata / xattr / digest を検証して同一 filesystem から atomic publish する。既存 bundle が有効なら再利用し、不正な canonical leaf は quarantine へ隔離して再構築する。修復成功後の quarantine は自動削除せず、フォレンジック確認または手動 cleanup 用に保持する。
- `fail`: 通信、build、root bundle の repair / quarantine を行わず、同じ root-owned bundle を読み取り専用で検査する。初回 preseed は過去の receipt や既存 activation を要求せず、root / MDM trustbase と canonical package / lock / marker / metadata / digest 契約だけで受理する。setup は exact bundle を再検証して対象ユーザーの activation symlink だけを atomic に作成・修復し、root wrapper が postcondition を再検証する。
- activation: ユーザー側には bundle の `node_modules` への exact absolute symlink だけを作る。通常インストールが作成した既存の real `node_modules` directory は、対象ユーザー所有、ACL なし、group/other 書込不可の場合に限り、同じ skill directory 内のランダムな `.node-modules.pre-mdm.XXXXXX` へ inode ごと atomic に退避してから symlink を公開する。安全に置換できる既存 symlink / single-link regular file は、旧 leaf を同じ random name へ一時退避し、新 activation の検証後に token-bound inode だけを除去するため永続 backup を残さない。実 directory は削除せず pre-MDM backup として保持するため、利用者への確認なしで MDM 管理状態へ収束できる。正しい activation がすでに存在する再実行では symlink inode を置き換えず、新しい backup も作らない。この backup namespace は fresh setup、update、remediation、`uninstall.sh` のいずれも自動削除しない。uninstall は kit-managed files と disposable な `node_modules` / `logs` だけを除去し、backup とそれを含む skill directory を保持するため、不要と確認した backup は利用者が明示的に削除する。activation symlink とユーザーディレクトリの通常 xattr、および root runtime の祖先ディレクトリの通常 xattr は信頼根拠にせず、それ自体では拒否しない。hash-versioned bundle は複数ユーザーから共有でき、古い bundle を通常 remediation が自動削除することはない。web updater は両 mode で無効。

marker は compact JSON、下記 key 順、末尾 LF 1 個の exact bytes。次は arm64 の内容で、x64 では `arch` だけを `x64` にする。

```json
{"arch":"arm64","lock_sha256":"e235f6738b9350d2c6fe6c64b4bfd8e458efcd47df6bb52dd30749ed2c7d45c4","node_version":"v24.18.0","npm_version":"11.16.0","package_sha256":"711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1","registry":"https://registry.npmjs.org/","schema_version":1}
{"arch":"arm64","lock_sha256":"ddace3fb92cc857f7fbcc73159fc68fb0438e1c03c1fe7dfcfd8ea654b994832","node_version":"v24.18.0","npm_version":"11.16.0","package_sha256":"711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1","registry":"https://registry.npmjs.org/","schema_version":1}
```

- Ghostty は MDM が事前配布した app が上記 Apple Developer ID requirement を満たし、`com.apple.quarantine` がない場合だけ再利用する。不在、署名不一致、quarantine 残存はいずれも `auto` / `fail` とも fail-closed とし、対象ユーザーから Homebrew cask の導入や再導入は試みない。Developer ID 検証は notarization / Gatekeeper 判定とは別契約なので、配布側でも Gatekeeper policy を確認する。
Expand Down
2 changes: 1 addition & 1 deletion lib/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@ refresh_fresh_wce_snapshot_pair() {
# Covers fresh, fresh-with-existing, and update paths (called once after deploy).
# ---------------------------------------------------------------------------
_WCE_MDM_PACKAGE_SHA256="711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1"
_WCE_MDM_LOCK_SHA256="e235f6738b9350d2c6fe6c64b4bfd8e458efcd47df6bb52dd30749ed2c7d45c4"
_WCE_MDM_LOCK_SHA256="ddace3fb92cc857f7fbcc73159fc68fb0438e1c03c1fe7dfcfd8ea654b994832"

_wce_mdm_trust_base() {
printf '%s' "/Library/Application Support"
Expand Down
6 changes: 3 additions & 3 deletions mdm/detect-mdm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3703,7 +3703,7 @@ _mdm_wce_runtime_root() {
_base="$(_mdm_receipt_trust_base)" || return 1
_arch="$(_mdm_node_runtime_arch)" || return 1
printf '%s' \
"$_base/ClaudeCodeStarterKit/runtime/web-content-extraction/node-v24.18.0-npm-v11.16.0-darwin-$_arch/711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1-e235f6738b9350d2c6fe6c64b4bfd8e458efcd47df6bb52dd30749ed2c7d45c4"
"$_base/ClaudeCodeStarterKit/runtime/web-content-extraction/node-v24.18.0-npm-v11.16.0-darwin-$_arch/711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1-ddace3fb92cc857f7fbcc73159fc68fb0438e1c03c1fe7dfcfd8ea654b994832"
}

_mdm_wce_runtime_marker_is_valid() { # <runtime-root>
Expand All @@ -3718,7 +3718,7 @@ import sys

path, arch = sys.argv[1:]
package_digest = "711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1"
lock_digest = "e235f6738b9350d2c6fe6c64b4bfd8e458efcd47df6bb52dd30749ed2c7d45c4"
lock_digest = "ddace3fb92cc857f7fbcc73159fc68fb0438e1c03c1fe7dfcfd8ea654b994832"
expected = (
f'{{"arch":"{arch}","lock_sha256":"{lock_digest}",'
f'"node_version":"v24.18.0","npm_version":"11.16.0",'
Expand Down Expand Up @@ -3929,7 +3929,7 @@ _mdm_wce_runtime_tree_is_trusted() { # <runtime-root>
[[ "$(_mdm_sha256 "$_root/package.json")" \
== 711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1 \
&& "$(_mdm_sha256 "$_root/package-lock.json")" \
== e235f6738b9350d2c6fe6c64b4bfd8e458efcd47df6bb52dd30749ed2c7d45c4 ]] \
== ddace3fb92cc857f7fbcc73159fc68fb0438e1c03c1fe7dfcfd8ea654b994832 ]] \
|| return 1
_mdm_artifact_digest tree "$_root" "$_uid" "$_gid" >/dev/null
}
Expand Down
2 changes: 1 addition & 1 deletion mdm/install-mdm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14333,7 +14333,7 @@ _MDM_WCE_MARKER_FILE=".claude-code-starter-kit-wce-runtime.json"
_MDM_WCE_RUNTIME_DIGEST=""
_MDM_EXPECTED_WCE_COMPONENT_SHA256=""
_MDM_WCE_PACKAGE_SHA256="711c13b06916af27f643386615cae616114dc359b7c0463147b4fd607e2912c1"
_MDM_WCE_LOCK_SHA256="e235f6738b9350d2c6fe6c64b4bfd8e458efcd47df6bb52dd30749ed2c7d45c4"
_MDM_WCE_LOCK_SHA256="ddace3fb92cc857f7fbcc73159fc68fb0438e1c03c1fe7dfcfd8ea654b994832"

_mdm_wce_runtime_owner_uid() {
if [[ "${_MDM_TEST_MODE:-0}" == 1 \
Expand Down
6 changes: 3 additions & 3 deletions skills/web-content-extraction/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading