Back to skill

Security audit

batch-renamer

Security checks for vulnerabilities and agentic risk

Overview

This batch-renaming skill is mostly coherent, but its rename script can move or overwrite files outside the intended directory when given crafted rename patterns.

Review carefully before installing. Use only on backed-up directories, inspect the dry-run output, avoid rename patterns containing slashes, backslashes, absolute paths, or .. components, and avoid the global unpinned npx install path unless you trust the current remote package and repository version.

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

Error
Location
scripts/batch_renamer.py:13
Finding
Path Traversal and Arbitrary File Overwrite Through Crafted Rename Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/batch_renamer.py`, lines 13–24 and 51–53 **Vulnerability Type**: Insufficient destination-path validation **Risk Level**: High ### Vulnerable Code ```python if a.replace: old, new_s = a.replace.split("|", 1) if "|" in a.replace else (a.replace, "") new = new.replace(old, new_s) if a.prefix: new = a.prefix + new if a.suffix: r, e = os.path.splitext(new) new = r + a.suffix + e if new != name: plan.append((f, os.path.join(os.path.dirname(f), new))) ``` The generated paths are subsequently used without validation: ```python if a.apply and plan: for x, y in plan: os.rename(x, y) ``` ### Technical Analysis The `--prefix`, `--suffix`, and `--replace` arguments influence the destination path directly. The generated value is passed to `os.path.join()` without rejecting: - Absolute paths - `..` parent-directory components - Forward or backward path separators - Destinations outside the directory supplied through `--dir` - Existing destination files If `new` is absolute, `os.path.join(os.path.dirname(f), new)` discards the intended source directory. A relative value containing `../` can similarly escape that directory after filesystem path resolution. The script then passes the untrusted destination directly to `os.rename`. On operating systems where `os.rename` replaces an existing destination, this can overwrite a file without confirmation. On other systems, the operation can fail after earlier files have already been renamed. ### Attack Path 1. The attacker supplies or convinces an operator or agent to use a crafted prefix, suffix, or replacement rule. 2. The crafted name contains an absolute path or parent-directory traversal components. 3. For example, a prefix such as `../escaped/` causes a source file named `report.txt` to receive a destination resembling: `selected-directory/../escaped/report.txt`. 4. The operator runs the command with `--apply`. 5. Th ...[truncated 1077 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Treat every generated destination as an untrusted filesystem path. 1. Require the generated name to be a filename rather than a path: - Reject `/` and `\`. - Reject `.` and `..`. - Reject absolute paths using `os.path.isabs`. - Consider rejecting platform-specific drive and UNC path syntax. 2. Canonicalize and enforce directory containment: ```python source_dir = os.path.realpath(os.path.dirname(f)) destination = os.path.realpath(os.path.join(source_dir, new)) if os.path.dirname(destination) != source_dir: raise ValueError("Destination must remain inside the source directory") ``` 3. Refuse to overwrite existing paths: ```python if os.path.lexists(destination): raise FileExistsError("Destination already exists: %s" % destination) ``` 4. Perform validation for the entire plan before changing any file. 5. Detect duplicate destination paths using normalized, case-aware filesystem semantics. 6. Display validation failures in both human-readable and JSON output and return a nonzero exit code. 7. Where appropriate, use a non-overwriting rename primitive or explicitly create destination reservations to reduce race-condition exposure between validation and execution. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/batch_renamer.py:51
Finding
Non-Atomic Rename Execution Allows Collisions, Data Loss, and Partial Batch State<![CDATA[ ## Vulnerability Details **File Location**: `scripts/batch_renamer.py`, lines 51–53 **Vulnerability Type**: Unsafe non-transactional filesystem mutation **Risk Level**: Medium ### Vulnerable Code ```python if a.apply and plan: for x, y in plan: os.rename(x, y) ``` ### Technical Analysis The script executes rename operations sequentially without first validating the complete plan. It does not detect: - Multiple sources resolving to the same destination - A destination that is another source in the batch - Existing destination files - Rename cycles - Platform-specific case-insensitive filename collisions - Failures that occur after part of the plan has been applied There is no rollback mechanism. If a later operation fails, earlier operations remain in effect, even though the batch did not complete. Replacement rules are not necessarily one-to-one. For example, removing the letter `a` from both `a.txt` and `aa.txt` can map both source names to `.txt`. On systems with replacement semantics, the later operation can overwrite the result of the earlier operation. On systems that reject replacement, execution can terminate after previous mutations have already occurred. A source-target collision can also destroy an unmodified file. If `a.txt` is renamed to `b.txt` while an existing `b.txt` is not itself part of the rename plan, `os.rename` may replace `b.txt`. ### Attack Path 1. A directory contains files whose names collapse to the same output under the selected replacement rule, or one planned destination already exists. 2. The operator previews the plan and invokes the script with `--apply`. 3. The script begins applying operations without global collision validation. 4. Earlier operations succeed. 5. A later rename overwrites an earlier result or existing file, or fails because of a collision or filesystem error. 6. The directory is left with missing files, overwritten contents, or only a partially applied rename plan. The attack ...[truncated 682 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Implement a two-phase rename process. 1. Before modifying files, validate the entire plan: - Normalize every source and destination. - Verify that every destination is unique. - Detect case-insensitive collisions where applicable. - Reject existing destinations unless they are safely participating in the same validated rename graph. - Detect source-target chains and cycles. - Confirm that every source still exists and has not changed since planning. 2. Use collision-resistant temporary names in the same directory: - Rename each source to a unique temporary filename. - Only after all temporary renames succeed, rename temporary files to final destinations. - Ensure temporary names cannot conflict with existing paths. 3. Maintain an operation journal and roll back completed operations if any later step fails. 4. Report failures with a nonzero exit code instead of allowing an unhandled exception to expose only a partial result. 5. Consider adding an explicit overwrite option that defaults to disabled. Even when enabled, require collision reporting and confirmation. 6. Add tests covering duplicate destinations, source-target chains, cycles, existing targets, case-only renames, permission failures, and rollback behavior. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:81
Finding
Unpinned Third-Party CLI and Repository Reference in Global Installation Instructions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, line 81 **Vulnerability Type**: Unpinned supply-chain execution **Risk Level**: Medium ### Vulnerable Code ```bash npx skills add zhaoxinghua09-cell/agent-skills -g ``` ### Technical Analysis The documented one-command installation procedure invokes `npx` with the unpinned package name `skills`. Depending on the local environment and package availability, `npx` may download and execute the current package release rather than an audited fixed version. The referenced repository is also identified by a mutable repository name rather than a verified commit or signed release. Consequently, the effective code installed by this command can change after this project artifact has been audited. The `-g` option requests global skill installation, increasing the persistence and scope of a compromised package or repository version. The bundled Python script itself has no third-party runtime dependencies; this finding applies specifically to the documented installation channel. ### Attack Path 1. A user follows the one-command installation instruction in `SKILL.md`. 2. `npx` resolves the `skills` CLI from the local cache, local environment, or external package registry. 3. Because no exact CLI version or integrity hash is specified, a changed or compromised package version may be executed. 4. The CLI retrieves the repository through a mutable reference. 5. A compromised CLI release or changed repository revision installs altered skill content globally. 6. The altered content can subsequently be loaded or executed by agents using the global skill directory. Successful exploitation depends on compromise or malicious modification of the external package or repository. The instruction nevertheless provides no version or integrity boundary preventing such a changed payload from being used. ### Impact Assessment Code executed through `npx` receives the permissions of the invoking user. A compromised inst ...[truncated 439 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the CLI to an audited exact version: ```bash npx --yes skills@EXACT_VERSION ... ``` 2. Pin the repository content to a specific reviewed commit or signed release rather than a mutable branch. 3. Publish and verify cryptographic checksums or signatures for distributed skill artifacts. 4. Prefer project-local installation over global installation unless global scope is explicitly required. 5. Document the expected package publisher, registry, exact version, repository commit, and artifact checksum. 6. Recommend reviewing downloaded content before enabling it in an agent environment. 7. Where supported, use lockfiles, package-manager integrity metadata, and installation modes that do not execute arbitrary lifecycle scripts. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill describes and promotes file read/write behavior through a local Python renaming script, but it does not declare any explicit tool scope such as permissions or allowed-tools. In an agent environment, missing scope metadata weakens least-privilege controls and can allow broader filesystem actions than a reviewer or host expects.

Rp1

Medium
Category
MCP Rug Pull
Confidence
80% confidence
Finding
The installation instructions use `npx skills` without pinning a specific package version, which can fetch whatever version is current at execution time. This creates a supply-chain risk: a compromised or incompatible future release could run during installation and affect the user's environment.

Vague Triggers

Low
Confidence
89% confidence
Finding
The phrase "One command for daily file/text chores" is very broad and does not clearly define what requests should trigger this skill versus ordinary editing help. The README does not provide specific trigger phrases, scope boundaries, or negative examples to prevent unintended invocation.

Intent-Code Divergence

Low
Confidence
89% confidence
Finding
The usage section for this skill says write operations are dry-run by default and adds that "text-replace/dup-finder 还会先备份". In this batch-renamer skill file, that statement refers to other tools and describes behavior outside this skill's actual implementation scope, creating misleading documentation about what this skill itself does.

Static analysis

No suspicious patterns detected.