Remote templates: symlinks are silently dropped since 1.4.1, breaking shared code across template variants
@mhenc đang làm issue này rồi.
Từ ngày 14/9/2026.
Đánh giá
Issue này chưa được đánh giá.
Mô tả
What happened
Since 1.4.1, agents-cli scaffold create --agent <remote git URL> silently drops every
symlink in the template source. A template that uses an intra-repo symlink to share a
library across several template variants scaffolds "successfully" into a project that is
missing that library and fails on import.
This is a regression: 1.4.0 copied a symlinked directory as real files.
The guard is copy_files.should_skip() in
google/agents/cli/scaffold/utils/template.py:
# Never follow symlinks from untrusted remote template sources
if path.is_symlink():
logging.warning(
f"Skipping symlink in template source (symlinks are not allowed): {path}"
)
return True
I understand the CWE-59 motivation (a template shipping id_rsa -> ~/.ssh/id_rsa). The
problem is that the check rejects all symlinks, including ones whose target never leaves
the cloned repository, and it does so without failing the command.
Reproduction
A repo laid out like this, pushed to GitHub, with the template at template/:
myrepo/
├── shared/ # single source of truth
│ └── config.py
└── template/
├── agents-cli-manifest.yaml
└── app/
├── agent.py # `from .shared.config import ...`
└── shared -> ../../shared # committed as a symlink (git mode 120000)
agents-cli scaffold create demo \
--agent https://github.com/<org>/myrepo/template@main --prototype
Expected: demo/app/shared/config.py exists (this is what 1.4.0 did).
Actual: demo/app/shared/ does not exist. The command prints
✅ Success! Your agent project is ready. and the project fails at import.
Version bisect
I ran each release's own copy_files over the same template directory:
| Version | app/shared/ in output |
|---|---|
| 1.0.0 / 1.2.0 / 1.3.0 / 1.4.0 | present (symlink dereferenced) |
| 1.4.1 / 1.5.0 | missing |
The Never follow symlinks from untrusted remote string first appears in 1.4.1.
Two things make this hard to notice
- It is a warning, not an error. Scaffolding reports success, and the failure only
shows up later as anImportErrorfar from its cause. local@does not exercise the same path.agents-cli scaffold create --agent local@<path>pre-copies the template with
shutil.copytree(local_path, template_source_path, ignore=...)
(scaffold/commands/create.py), andcopytreedefaults tosymlinks=False, i.e. it
dereferences. So a template author's CI that validates withlocal@— which the docs
present as the way to test a template locally — passes, while every real user of the
published URL gets a broken project. Our CI has been green this whole time.
Why this matters for multi-variant templates
We maintain an internal ADK template with several variants (a default ReAct agent, an A2UI
variant, a multi-agent GKE variant). All of them share one library — DI wiring for model
tiers, Secret Manager, artifact storage, logging/tracing — plus one ruff.toml and one
ty.toml.
The scaffolder only copies the directory --agent points at, so the only way to share
code across variants without duplicating it is an intra-repo symlink from each variant
into the shared directory. That is exactly what 1.4.1 broke. This is the same use case as
#62, which we're otherwise happy with.
The workaround is to vendor N physical copies of the shared library into the repo (one per
variant) and add a sync script plus a CI drift check. That works, but it means the "single
source of truth" only exists by convention, and every shared-code review carries N
mechanical duplicate diffs.
Suggested fixes, in order of preference
-
Allow a symlink whose resolved target stays inside the fetched repository.
Path.resolve()the link and require it to be under the clone root, skipping it
otherwise. That preserves the CWE-59 protection completely — an escaping link is still
refused — while letting a template share code within its own repo.One detail: the containment check needs to be against the cloned repo root, not the
template subdirectory. A shared library naturally sits at the repo root while the
template is a subdirectory, so the link legitimately points "up" out of the template
dir but never out of the repo. -
An opt-in in the template manifest, e.g.
settings.follow_symlinks: true, if you'd
rather the decision be explicit per template. -
At minimum, fail loudly. If symlinks stay banned, please make the command error out
(or print to stderr and list every dropped path in the summary) instead of logging a
warning and reporting success. Silently producing a broken project is the worst
outcome. It would also help to havelocal@skip symlinks the same way remote fetches
do, so a template author's local validation reflects what users will actually get.
Environment
- agents-cli 1.5.0 (and 1.4.1); last working: 1.4.0
- Linux, Python 3.13 / 3.14
- Ngôn ngữ chính
- Python
- Star
- 6k
- Fork
- 686
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của google/agents-cli
-
documentation needs review
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 92/100
google/agents-cli#86 ·
-
needs review
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 42/100
google/agents-cli#92 · 1 bình luận ·
-
When an extension is applied, there is a warning emitted for EVERY commandCó thể đã có người làm @asrujana-44 đã nhận 8 ngày trước. Đang mở
google/agents-cli#91 · 1 bình luận · 1 người được giao ·
-
scaffold: dependency reconciliation is silent — no diff shown, unlike enhance/upgradeCó thể đã có người làm @asrujana-44 đã nhận 2 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
google/agents-cli#85 · 1 bình luận · 1 người được giao ·
-
[Bug] Scaffolded agent card grows a duplicate JSONRPC 0.3 interface on every GET (card_modifier mutates the shared AgentCard)Có thể đã có người làm @asrujana-44 đã nhận 7 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
google/agents-cli#84 · 2 bình luận · 1 người được giao ·
Tất cả issue của google/agents-cli
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
BasedHardware/omi#20271 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 92/100
openai/openai-cookbook#3153 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
cvss-severity:high devguard l3montree-cybersecurity/devguard/devguard pkg:golang/github.com/l3montree-dev/devguard risk:low state:open
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
l3montree-dev/devguard#3146 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
-
bug confirmed issue
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
open-webui/open-webui#31849 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày