feat(extensions): serve local media in Flex viewer canvas + bundled MCP server - #8
Merged
Merged
Conversation
…CP server Ports the .NET FlexPreviewService local-media serving (LINE_FLEX_MCP_ASSET_DIR) to the two Node servers so a Flex message can reference local artwork/video by a relative url in every preview path, not just the .NET MCP tool. - Add shared lib/assets.mjs (resolveAssetPath / assetContentType / isLoopbackHost / resolveMediaRequest), a port of the .NET confinement logic kept in one place so the canvas (extension.mjs) and bundled MCP server (mcp/server.mjs) cannot diverge. - Wire both servers to serve assets under LINE_FLEX_MCP_ASSET_DIR (opt-in, loopback host-guarded, extension allowlist .png/.jpg/.jpeg/.mp4, path traversal/symlink escape refused). renderer.js and web assets unchanged. - Add zero-dependency node:test suite (42 tests): a superset of the .NET FlexPreviewAssetServingTests plus DNS-rebinding and resolveMediaRequest cases. Cleanup uses a single async fs.rm to avoid an rmSync recursive crash on Windows with non-ASCII temp paths. - Add npm test script and a CI job (node --test) so JS-specific regressions are caught; runs on Linux where the symlink-escape test is exercised. - Document local media serving in the extension README (en/ja). 3-role gate: security PASS / code PASS / test-arch PASS (non-blocking CONCERNS), no blocking findings. Record: docs/reviews/2026-09-04-flex-preview-extension-parity-review.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要
Flex プレビューのローカルメディア配信(
LINE_FLEX_MCP_ASSET_DIR配下の画像/動画を相対urlで参照)を、これまで対応していなかった Copilot キャンバス拡張(extension.mjs)と同梱 Node MCP サーバ(mcp/server.mjs) に移植し、.NET Tools(FlexPreviewService)との機能 parity を取りました。これまで両 Node サーバは静的ファイル whitelist +
/api/*のみ配信し、相対urlのメディアは 404 でした(.NET MCP 経由のみ配信可=非対称)。本 PR でこの非対称を解消します。利用シーン: 用意したメディアをフォルダに配置 → Flex JSON からは相対
url(例"assets/hero.png")で参照 → 本番移行時は origin だけ HTTPS の CDN に差し替え(相対パスは不変)。プレビュー専用の利便機能。変更点
lib/assets.mjs(新規) — 封じ込めロジックを共有モジュールに集約。resolveAssetPath/assetContentType/isLoopbackHost/resolveMediaRequestは .NET の同名ロジックの移植。セキュリティ上重要な封じ込めを 1 箇所に置き、2 サーバが同一のresolveMediaRequestを通す(二重持ち回避)。extension.mjs/mcp/server.mjs—LINE_FLEX_MCP_ASSET_DIR配下メディア配信を配線(opt-in・ループバック Host ガード・拡張子 allowlist.png/.jpg/.jpeg/.mp4・パストラバーサル/symlink 越え拒否)。renderer.jsほかweb/は無改修。lib/assets.test.mjs(新規・42 tests) — 依存ゼロのnode:test。.NETFlexPreviewAssetServingTestsの上位集合+ DNS リバインド/resolveMediaRequest直接テスト。ci.yml— 依存ゼロのextension-testジョブ追加(node --test・Linux で symlink 越えテストも実走)。mcp/package.jsonにnpm test。テスト
node --test extensions/line-flex-viewer/lib/assets.test.mjs= 42/42 全緑。mcp/server.mjsを stdio 起動した手動 e2e スモークで実配信確認(画像 200/バイト一致・.gif→404・トラバーサル→404・外部 Host→404)。レビュー
3 役ゲート = security PASS / code PASS / test-arch PASS(非ブロッキング CONCERNS)、BLOCKING なし。封じ込め(トラバーサル・エンコード回避・rooted/UNC・制御文字・DNS リバインド・symlink 越え)は .NET 版と等価と実証。
記録:
docs/reviews/2026-09-04-flex-preview-extension-parity-review.md残(非ブロッキング follow-up・次サイクル)
/api/*・静的配信へのホストガード横展開(既存 follow-up と同一課題)handleRequestを SDK 非依存モジュールへ切り出し)X-Content-Type-Options: nosniffの些細な parity(.NET も未対応)未確認
extension.mjs)の実起動は SDK/ホストが必要で未検証。mcp/server.mjsと同一配線・共有関数のため単体テスト+実 MCP スモークで実質担保。🤖 Generated with Claude Code