Back to skill

Security audit

元质 yotta-code-quality

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate code-review skill, but its installers can overwrite or delete through unsafe destination paths and can persist broadly in agent skill folders.

Install only from a version and source you trust, prefer a pinned package version, avoid running the global installer unless you really want the skill in every supported agent, and choose a skill directory you control with no pre-existing yotta-code-quality symlink. The runtime review behavior is mostly transparent and opt-in for edits/history, but the installer deserves careful handling.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
bin/install.js:128
Finding
JavaScript Installer Follows Pre-Existing Destination Symlinks<![CDATA[ ## Vulnerability Details **File Location**: `bin/install.js:128-155` **Vulnerability Type**: Unsafe destination path and symlink handling **Risk Level**: Medium ### Vulnerable Code ```javascript function copyDir(src, dst, skip) { for (const entry of fs.readdirSync(src, { withFileTypes: true })) { if (skip.has(entry.name)) continue; const from = path.join(src, entry.name); const to = path.join(dst, entry.name); try { if (entry.isDirectory()) { fs.mkdirSync(to, { recursive: true }); copyDir(from, to, skip); } else if (entry.isFile()) { fs.copyFileSync(from, to); } } catch (err) { throw new InstallError('Failed to copy ' + from + ' -> ' + to + ': ' + err.message); } } } function installTo(dest) { if (!dest || typeof dest !== 'string') throw new UsageError('Destination directory is required'); const target = path.resolve(dest, SKILL_NAME); assertSafeTarget(target); try { fs.mkdirSync(target, { recursive: true }); copyDir(PKG_ROOT, target, COPY_SKIP); if (!fs.existsSync(path.join(target, 'SKILL.md'))) { throw new InstallError('Installed directory is missing SKILL.md'); } ``` ### Technical Analysis The installer creates and writes to the target using path-based filesystem operations without checking whether the target directory or any existing destination entry is a symbolic link. `fs.mkdirSync(..., { recursive: true })` accepts an existing directory symlink, while subsequent `fs.copyFileSync` calls can follow destination symlinks. The `assertSafeTarget` function only performs a lexical comparison against the package source directory. It does not canonicalize the destination with `fs.realpathSync`, inspect components with `fs.lstatSync`, or verify that the resolved target remains within the user-selected skills directory. Consequently, an attacker who can prepare entries in the destination directory can redirect installation writes outside the int ...[truncated 1331 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the destination parent using `fs.realpathSync` and verify that the final target remains beneath the intended skills directory. 2. Inspect every existing destination component with `fs.lstatSync` and reject symbolic links. 3. Reject a pre-existing target unless it is a verified directory owned or trusted by the current user. 4. Copy into a newly created temporary sibling directory using exclusive creation, then atomically rename it into place. 5. Avoid overwriting existing files without explicit user confirmation or a verified upgrade mode. 6. Add tests covering: - A symlink at the complete target path. - Symlinked files inside an existing target. - Symlinked intermediate path components. - Attempts to install into or through the package source directory. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
install.sh:63
Finding
Shell Installer Can Copy and Delete Through an Unvalidated Destination Path<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:63-67` **Vulnerability Type**: Unsafe destination path and symlink handling **Risk Level**: Medium ### Vulnerable Code ```bash install_to() { mkdir -p "$1/$SKILL_NAME" cp -r "$SOURCE_DIR/." "$1/$SKILL_NAME/" rm -rf "$1/$SKILL_NAME/.git" echo "installed -> $1/$SKILL_NAME" } ``` ### Technical Analysis The shell installer accepts a destination path and immediately performs recursive copying and deletion beneath it. It does not canonicalize the path, reject symbolic links, ensure that the target is outside the source tree, or verify that the final `.git` path belongs to the newly installed copy. If `<destination>/yotta-code-quality` is a pre-existing symlink to another directory, `cp` can place files in that linked directory. The subsequent path traversal to `<destination>/yotta-code-quality/.git` can reach a `.git` directory under the linked location, after which `rm -rf` deletes it. Quoting prevents shell metacharacter injection, so this is not command injection. The issue is filesystem path trust and unsafe recursive operations. ### Attack Path 1. An attacker gains write access to a skills directory that the victim will use with `--dir`, `--agent`, global installation, or project auto-detection. 2. The attacker creates `yotta-code-quality` as a symlink to a victim-writable repository or another selected directory. 3. The victim executes `bash install.sh` using that destination. 4. `mkdir -p` accepts the pre-existing linked path. 5. `cp -r` copies the project through the symlink and may overwrite files in the linked directory. 6. `rm -rf "$1/$SKILL_NAME/.git"` resolves the path through the linked directory and can delete its `.git` metadata. ### Impact Assessment An attacker can cause file overwrites and deletion of repository metadata outside the intended installation directory, limited to locations writable by the user running the script. Deleting `.git` can destroy uncommitted r ...[truncated 269 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Canonicalize the destination with `realpath` before copying or deleting. 2. Reject the operation if the target or any intermediate component is a symbolic link. 3. Verify that the canonical target is a child of the canonical user-selected skills directory and is not the source directory. 4. Replace in-place recursive copying with installation into a newly created temporary sibling directory followed by an atomic rename. 5. Remove `.git` from the temporary source copy before placement rather than recursively deleting it after installation. 6. Add an explicit upgrade mode and refuse to overwrite a pre-existing installation by default. 7. Add automated tests for linked targets, linked path components, existing `.git` directories, paths with spaces, and source-descendant destinations. ]]>

T08 · Insecure Dependencies

Note
Location
README.md:149
Finding
Recommended Unpinned npx Command Automatically Executes Mutable Registry Content<![CDATA[ ## Vulnerability Details **File Location**: `README.md:149-159` **Additional Locations**: `README.zh-CN.md:162-172`, `CHANGELOG.md:13` **Vulnerability Type**: Unpinned package execution through the npm supply chain **Risk Level**: Low ### Vulnerable Code ```text ### Method 1: npm one-liner (recommended) # Optional China mirror: npm config set registry https://registry.npmmirror.com npx -y @yottameta/yotta-code-quality --agent <agent-name> npx -y @yottameta/yotta-code-quality --dir <your-skills-dir> - If the mirror has not synced the new package (404): add --registry=https://registry.npmjs.org/ ``` ### Technical Analysis The recommended command uses `npx -y` without a package version. This retrieves and executes whichever release currently satisfies the package name, normally the latest registry version, while `-y` suppresses the confirmation prompt. The audited package currently has no third-party runtime dependencies or npm lifecycle scripts, and no malicious code was found in the reviewed artifact. Nevertheless, the documented command does not bind execution to that audited artifact. A future compromised publication, publisher account, registry response, or configured mirror could provide different executable content. This is a supply-chain hardening issue rather than evidence that the current package is malicious. ### Attack Path 1. An attacker compromises the npm publisher account, release pipeline, package namespace, or a configured registry mirror. 2. The attacker publishes or serves a modified latest release containing a malicious `bin/install.js` or other executable package behavior. 3. A user follows the recommended unversioned `npx -y` command. 4. `npx` downloads the mutable release and executes its package binary without an interactive confirmation. 5. The malicious package executes with the installing user's filesystem and process privileges. ### Impact Assessment A compromised fetched package could execute arbitrary JavaScr ...[truncated 417 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the documented command to a reviewed release, for example: ```text npx -y @yottameta/yotta-code-quality@0.4.0 --agent <agent-name> ``` 2. Publish package integrity information and signed provenance for each release. 3. Recommend installation from the official npm registry and clearly explain that third-party mirrors introduce an additional trust boundary. 4. Document how users can inspect package metadata and contents before execution. 5. Consider removing `-y` from security-sensitive installation guidance so users retain an execution confirmation step. 6. Maintain tightly controlled publisher access with multi-factor authentication and protected release automation. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill is presented as a passive code-quality reviewer, but the observed package behavior reportedly includes installation logic, directory discovery, environment-variable-based path resolution, and file copying into agent/user/project locations. That mismatch is dangerous because users may invoke or install what they believe is a review-only skill while it performs filesystem-modifying actions outside the stated scope, reducing informed consent and increasing the chance of unintended persistence or supply-chain abuse.

Vague Triggers

Medium
Confidence
82% confidence
Finding
The trigger phrases include broad everyday review requests such as "any issues" and "ready to merge," which can cause the skill to activate in contexts broader than intended. In an agent ecosystem, overbroad triggering is risky because it can inject this skill's instructions into unrelated conversations, unexpectedly influencing agent behavior or causing access to shared code when the user did not clearly request this specific reviewer.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The template instructs agents to proactively invoke the skill whenever code-quality-related topics arise, which is a broad trigger surface that can cause unintended activation in adjacent conversations. In an agent-instruction file, overly broad auto-triggering is risky because it can override user expectations, expand the skill's influence beyond explicit consent, and lead to instruction collisions or unnecessary access to repository context.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
test/install.test.js:12