Skip to content

fix(skills): reject skill names that are not one path component - #163

Merged
zhengchaol merged 2 commits into
mainfrom
fix/skill-name-path-traversal
Oct 24, 2026
Merged

zhengchaol merged 2 commits into
mainfrom
fix/skill-name-path-traversal

Conversation

@zhengchaol

@zhengchaol zhengchaol commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Skill names from a project's .parallel-cli-skills-manifest.json reached shutil.rmtree(install_dir / name) without validation. That file ships with the repo, so an entry like ../../../x let parallel-cli skills install --project delete directories outside the project. Names from the manifest and from the index must now be a single path component. Unsafe manifest entries are ignored, and unsafe index names fail the install.

The manifest itself was also written through a symlink, so a repo shipping it as a link to another file had install overwrite that file. It is now written to a temp file and os.replaced into place.

Reproduced against the production index before and after the change. The new tests fail on main.

🤖 Generated with Claude Code

Each skill name becomes a directory under the install dir, and install
and uninstall delete that directory with shutil.rmtree. Names read from
a project's .parallel-cli-skills-manifest.json were never validated, and
that file ships with the repository. An entry like "../../../x" let a
repo make `parallel-cli skills install --project` delete a directory
outside the project, and "." wiped the whole install dir, unmanaged
skills included.

Accept only names that are a single path component under both POSIX and
Windows rules. Unsafe manifest entries are ignored, like other malformed
entries. An unsafe name in the remote index fails the install, because
it would steer file writes outside the install dir the same way.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@zhengchaol
zhengchaol marked this pull request as ready for review October 23, 2026 23:52
@zhengchaol
zhengchaol requested a review from a team October 23, 2026 23:52
The install manifest was written with write_text, which follows a
symlink. A repository could ship .parallel-cli-skills-manifest.json as
a link to a file elsewhere, and `skills install --project` would
overwrite that file with JSON. Write a temp file in the install dir and
os.replace it, which swaps the link out and also makes the update
atomic.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@zhengchaol
zhengchaol merged commit 06de051 into main Oct 24, 2026
7 checks passed
@zhengchaol
zhengchaol deleted the fix/skill-name-path-traversal branch October 24, 2026 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant