aws-samples / aws-samples/sample-autonomous-cloud-coding-agents
registry: symlinked .mcp.json exfiltrates secret to a different tracked path + arbitrary-file-write (#665 B4 #1)
- 主要言語
- TypeScript
- スター
- 143
- フォーク
- 46
- 平均マージ
- 3日 10時間
- マージ済み PR(30日)
- 24
説明
**Source:** BLOCKING #1 from @scottschreckengaust's review of #665 — https://github.com/aws-samples/sample-autonomous-cloud-coding-agents/pull/665#pullrequestreview-4915535549 (`agent/src/registry/loader.py:190`)
**Parent:** #246 · **Sibling blockers:** the fail-open guard and the skip-worktree data-loss issues (linked below)
## Problem
`apply_mcp_assets` computes `mcp_path = os.path.join(repo_dir, ".mcp.json")` and opens it `"w"`. Python's `open(..., "w")` **follows symlinks**, so if the cloned repo ships `.mcp.json -> config/mcp.json` (both tracked — a normal shared-config layout), the resolved **unredacted** MCP runtime (bearer headers, `url?token=`, `--api-key` args) lands in `config/mcp.json`. The `_protect_mcp_json_from_commit` guard then flags only the *symlink's* index entry (`.mcp.json`), leaving `config/mcp.json` unguarded — so `post_hooks.ensure_committed` (`git add -u`) stages it and `ensure_pushed` pushes the secret into the PR's git history. Reproduced against the real loader at `0b06ff5`.
The same symlink-follow is an **arbitrary-file-write primitive**: `.mcp.json -> .github/workflows/ci.yml` overwrites the workflow (and `add -u` stages it); `.mcp.json -> .git/config` corrupts repo config so every later git call fails. Repo layout is attacker-controlled input — the agent clones untrusted repos / PR branches (`repo.py:299`).
## Fix
Refuse a non-regular target before writing:
```python
if os.path.islink(mcp_path):
raise RegistryAssetLoadError(f"refusing to write resolved MCP config through a symlink: {mcp_path}")
```
(`os.open(..., O_NOFOLLOW)` is the race-free variant.)
> Note: Scott's recommended durable fix — route registry MCP servers through the SDK in-process `mcp_servers` option instead of writing `.mcp.json` at all — closes this together with the sibling blockers. If that path is taken, this issue is subsumed.
## Acceptance
- A symlinked `.mcp.json` (pointing at a second tracked file, or into `.git`/`.github`) causes `apply_mcp_assets` to raise, not write-through
- Regression test: symlink `.mcp.json` at a second tracked file, assert raise + `git add -u && git diff --cached` empty
コントリビューションガイド
調査の方向性
agent/src/registry/loader.py:190 から開始して apply_mcp_assets を追跡し、その後、信頼できない checkout のコンテキストについて repo.py:299 を確認します。別の追跡対象ファイルを指す symlink の .mcp.json を使った回帰テストを追加し、対象を変更せずに操作が例外を発生させることを検証します。関連する registry テストを実行し、git add -u && git diff --cached が引き続き空であることを確認します。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- git, python
- 領域
- backend, security
- issue の種類
- バグ
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 活発さ
- 静か
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 72/100