Back to skill

Security audit

Handoff Installer

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a genuine repository handoff installer, but its installer has an under-scoped file-handling issue that can copy local file contents into a target repository when AGENTS.md or CLAUDE.md are symlinks.

Install only in repositories you control and trust. Before running install or update, verify that AGENTS.md and CLAUDE.md in the target repository are regular files, not symlinks, and review the resulting diff before committing or pushing. Expect this to add persistent Chinese-language handoff rules that guide future agents, including local task-state commits and a consent-gated session-history recovery workflow.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/install.sh:401
Finding
Repository File Symlinks Can Disclose Local Files During Installation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:57-59` and `scripts/install.sh:401-422` **Vulnerability Type**: Symlink following and unintended local file disclosure **Risk Level**: Medium ### Vulnerable Code ```sh assert_real_dir_ancestors '.agents/skills/handoff' assert_real_dir_ancestors '.agents/tasks/archive' assert_real_dir_ancestors '.claude/skills' ``` ```sh write_agents_block() { _target=$TARGET/AGENTS.md if [ -f "$_target" ] && grep -qF "$BEGIN" "$_target"; then awk -v b="$BEGIN" -v e="$END" '$0==b{skip=1} !skip{print} $0==e{skip=0}' "$_target" > "$WORK/agents-body" elif [ -f "$_target" ]; then cp "$_target" "$WORK/agents-body" printf '\n' >> "$WORK/agents-body" else : > "$WORK/agents-body" fi { sed -n '1,$p' "$WORK/agents-body"; sed -n '1,$p' "$AGENTS_SOURCE"; } > "$WORK/AGENTS.md" mv "$WORK/AGENTS.md" "$_target" } write_import() { _target=$TARGET/CLAUDE.md _line=$(tr -d '\r\n' < "$IMPORT_SOURCE") if [ ! -f "$_target" ]; then printf '%s\n' "$_line" > "$_target" elif [ "$(head -1 "$_target")" != "$_line" ]; then { printf '%s\n' "$_line"; sed -n '1,$p' "$_target"; } > "$WORK/import" mv "$WORK/import" "$_target" fi } ``` ### Technical Analysis The installer explicitly rejects symbolic links along managed paths under `.agents` and `.claude`, but it does not perform an equivalent check for the repository-level `AGENTS.md` and `CLAUDE.md` files. The shell tests and utilities used by these functions follow symbolic links: - `[ -f "$_target" ]` succeeds when the link resolves to a regular file. - `grep`, `awk`, `cp`, `head`, and `sed` read the link target. - The resulting content is written into a temporary regular file. - `mv` then replaces the repository symlink itself with that regular file. Consequently, if an untrusted target repository contains `AGENTS.md` or `CLAUDE.md` as a symbolic link to a local file readable by the user running the installer, the linked file's ...[truncated 1956 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject symbolic links at both repository-level managed files before reading or replacing them: ```sh assert_regular_or_missing() { _path=$1 if [ -L "$_path" ]; then printf 'refusing to install: %s is a symlink\n' "${_path#"$TARGET"/}" >&2 return 1 fi if [ -e "$_path" ] && [ ! -f "$_path" ]; then printf 'refusing to install: %s is not a regular file\n' "${_path#"$TARGET"/}" >&2 return 1 fi } assert_regular_or_missing "$TARGET/AGENTS.md" assert_regular_or_missing "$TARGET/CLAUDE.md" ``` 2. Perform this validation before transaction hashes are calculated and repeat it immediately before each read and final replacement to reduce time-of-check/time-of-use exposure. 3. Where platform support permits, open existing files using a no-follow mechanism such as `O_NOFOLLOW` rather than relying exclusively on a separate shell check. 4. Ensure that replacement operations only target verified regular files or absent paths. Reject directories, devices, FIFOs, sockets, and other special file types. 5. Add regression tests covering: - `AGENTS.md` linked to a readable external file - `CLAUDE.md` linked to a readable external file - Dangling symbolic links - Links changed between validation and replacement - Ordinary regular files, to confirm legitimate updates still work 6. Verify after a rejected installation that no external content was copied into the repository and that the original symlink remains unchanged. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
[ -n "$_stored" ] || return 0
  if [ -f "$TARGET/$LEGACY_LEDGER_TARGET" ] && \
     [ "$(hash_file "$TARGET/$LEGACY_LEDGER_TARGET")" = "$_stored" ]; then
    rm "$TARGET/$LEGACY_LEDGER_TARGET"
    rmdir "$TARGET/tools" 2>/dev/null || :
    printf 'migrated legacy ledger: %s -> %s\n' "$LEGACY_LEDGER_TARGET" "$LEDGER_TARGET"
  fi
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill explicitly instructs use of local shell and declares required binaries, but it does not define an explicit tool scope such as allowed-tools/permissions. That creates an authorization ambiguity where an agent may invoke shell more broadly than intended, which is especially risky because the shell script can modify arbitrary files in a target repository.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
L58 says the packaged runtime policy is used in Chinese as a repository convention. This imposes a specific language on the installed runtime behavior, and the file does not present that language choice as optional or user-selectable for the runtime policy itself.

Skill Enumeration

Medium
Category
Agent Snooping
Content
以上是安装器自身的边界。**被装进去的 handoff 运行时协议另有一条灾后路径**:任务棒丢失时,
它允许借助外部工具读取上一个会话的历史来重建任务棒。该路径要求先取得用户明确同意才能读取,
整理结果也要经用户确认才写入仓库;细节见装入后的 `.agents/skills/handoff/SKILL.md`「抢救」一节。
安装器本身不执行这条路径。
Confidence
86% confidence
Finding
The installer documentation discloses that the installed runtime protocol includes a disaster-recovery path that can use external tools to read prior session history. Even though this installer does not execute that path, it is packaging and deploying a capability that could expose sensitive conversation data if the installed runtime later obtains user consent under unclear or weak controls.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The document's operational instructions are written in Chinese, while there is no indication that the skill is region-specific or that users may opt into another language. This can violate language/locale policy when a skill constrains usage to a specific language without user choice or justification.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This section instructs the agent to create directories, stage files, move `.agents/tasks/current.md` into an archive path, and commit the changes using a chained shell command. Because the runtime skill is meant to govern future repository sessions and does not require an explicit per-action user confirmation at the point of mutation, it can cause repository state changes that the user may not realize are about to happen, including irreversible history changes once committed.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The template instructions and required field guidance are written entirely in Chinese and implicitly require task content to be authored in Chinese. This is a natural-language locale constraint that applies across the template without offering a language choice or explaining a justified region-specific requirement.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The entire skill reference is written in Chinese and does not mention any user language preference, opt-in, or region-specific justification. Under the policy, forcing a specific language without user choice is a natural-language locale violation.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
ROOT=$(cd "$(dirname "$0")/.." && pwd)
VERSION=$(tr -d '\r\n' < "$ROOT/VERSION")
AGENTS_SOURCE=$ROOT/assets/runtime/AGENTS.block.md
SKILL_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/SKILL.md
TEMPLATE_SOURCE=$ROOT/assets/runtime/repo/agents/tasks/TEMPLATE.md
IMPORT_SOURCE=$ROOT/assets/runtime/repo/CLIENT_IMPORT
LEDGER_SOURCE=$ROOT/assets/runtime/repo/agents/skills/handoff/ledger.sh
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
write_skill_link() {
  _target=$TARGET/.claude/skills/handoff
  mkdir -p "$TARGET/.claude/skills"
  if [ -e "$_target" ] || [ -L "$_target" ]; then
    if [ ! -L "$_target" ] || [ "$(readlink "$_target")" != '../../.agents/skills/handoff' ]; then
      printf 'conflicting skill entry: %s\n' "$_target" >&2
Confidence
85% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This shell script modifies the target repository by copying files into .agents, rewriting AGENTS.md and CLAUDE.md, creating a symlink, changing execute permissions, writing lock/transaction files, and potentially deleting tools/ledger.sh during migration. While the file has a brief top-level comment about installing or inspecting the protocol, it does not provide a user-facing warning, confirmation prompt, or explicit disclosure near the mutating paths before making these repository changes.

Scope Creep

Low
Category
Excessive Agency
Content
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Static analysis

No suspicious patterns detected.