Back to skill

Security audit

Batch Renamer

Security checks for vulnerabilities and agentic risk

Overview

This is a file-renaming skill with coherent purpose, but its implementation and install guidance create review-worthy risks around moving or corrupting files outside the intended directory.

Review carefully before installing. Prefer running only the included Python script in a test directory, avoid shared or attacker-writable directories, use preview first, and do not follow the global npm or pip install commands unless the publisher provides verifiable package ownership, versions, and source linkage. Be aware that unsafe patterns or a tampered backup file could move or corrupt files outside the directory you intended to manage.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
batch_renamer.py:120
Finding
Untrusted Backup Data Allows Arbitrary Filesystem Renames## Vulnerability Details **File Location**: `batch_renamer.py:20-22` and `batch_renamer.py:120-131` **Vulnerability Type**: Unvalidated backup paths and missing directory-containment enforcement **Risk Level**: High ### Vulnerable Code ```python def load_backup(self): if self.backup_file.exists(): with open(self.backup_file, 'r', encoding='utf-8') as f: self.backup_data = json.load(f) return self.backup_data ``` ```python # Reverse the mappings to undo the operation reverse_mappings = {v: k for k, v in backup.items()} count = 0 for new_str, old_str in reverse_mappings.items(): new_path = Path(new_str) old_path = Path(old_str) if new_path.exists() and not old_path.exists(): new_path.rename(old_path) print(f"Undo: {new_path.name} -> {old_path.name}") count += 1 ``` ### Technical Analysis The undo implementation treats `.batch-renamer-backup.json` as trusted input. It deserializes arbitrary JSON and converts its keys and values directly into filesystem paths without validating the data structure, confirming that the paths belong to a previous operation, or ensuring that they remain inside the selected directory. Both absolute paths and paths containing traversal components can consequently be used as rename sources or destinations. The operation executes with all filesystem privileges held by the user running the utility. The `exists()` checks do not establish trust or containment. They only require the attacker-selected source to exist and the attacker-selected destination not to exist. ### Attack Path 1. An attacker obtains write access to a directory that a victim is likely to process, such as a shared working directory. 2. The attacker creates `.batch-renamer-backup.json` containing a mapping whose value is the path of an existing victim-accessible file and whose key is an attacker-selected destination. 3. The victim runs: ...[truncated 771 chars]
Remediation
## Remediation Suggestions - Validate that the backup is a JSON object containing only expected string-to-string mappings. - Canonicalize the selected directory and every source and destination with `Path.resolve()`. - Require both paths to be direct children of the selected directory. - Reject absolute paths, traversal components, symbolic-link escapes, and unexpected nested paths. - Store only filenames rather than unrestricted filesystem paths. - Add an integrity mechanism or securely controlled state directory so that an attacker cannot replace the backup unnoticed. - Before undoing, verify that each mapping corresponds to a successfully completed operation. - Abort the entire undo transaction if any mapping fails validation rather than partially processing the file.

T09 · Insecure Skill Coding Practices

Warning
Location
batch_renamer.py:83
Finding
User-Controlled Rename Patterns Can Escape the Selected Directory## Vulnerability Details **File Location**: `batch_renamer.py:83-96` and `batch_renamer.py:110-115` **Vulnerability Type**: Path traversal through an unrestricted destination filename **Risk Level**: Medium ### Vulnerable Code ```python def rename(self, pattern=None, regex=None, preview=False): files = self.get_files() mappings = {} for i, file_path in enumerate(files): old_name = file_path.name if pattern: new_name = self.generate_name(pattern, i, file_path) elif regex: new_name = self.apply_regex(old_name, regex) else: continue new_path = self.directory / new_name mappings[str(file_path)] = str(new_path) ``` ```python # Perform the renames for old_str, new_str in mappings.items(): old_path = Path(old_str) new_path = Path(new_str) if old_path.exists() and not new_path.exists(): old_path.rename(new_path) print(f"Rename: {old_path.name} -> {new_path.name}") ``` ### Technical Analysis The value produced from the user-supplied `--pattern` argument is treated as a filename but is not restricted to a filename. A pattern may contain `..` components, directory separators, or an absolute path. Joining such a value to `self.directory` does not guarantee containment: traversal components can escape the directory, and an absolute path can override the base path. The resulting path is passed directly to `Path.rename()`. The confirmation prompt reports only the number of files and does not clearly expose or validate destinations, so it is not an adequate security boundary. ### Attack Path 1. A user or wrapper invokes the utility with an unsafe pattern, for example: ```bash python3 batch_renamer.py rename ./photos --pattern "../archive/photo_{001}.{ext}" ``` 2. `generate_name()` preserves the traversal component while replacing template variables. 3. `self.dire ...[truncated 771 chars]
Remediation
## Remediation Suggestions - Treat the generated value strictly as a filename. - Reject absolute paths, `..`, path separators, null bytes, and platform-specific alternate separators. - Require `Path(new_name).name == new_name`. - Resolve the destination and verify that its parent is exactly the resolved selected directory. - Avoid relying only on string-prefix checks, which can be bypassed by similarly named directories. - Display all validated source-to-destination mappings before confirmation. - Preflight the complete batch for containment, collisions, and invalid names before renaming any file.

T09 · Insecure Skill Coding Practices

Warning
Location
batch_renamer.py:25
Finding
Fixed Backup File Can Be Overwritten Through a Symbolic Link## Vulnerability Details **File Location**: `batch_renamer.py:16` and `batch_renamer.py:25-27` **Vulnerability Type**: Symbolic-link following during security-sensitive file creation **Risk Level**: Medium ### Vulnerable Code ```python self.backup_file = self.directory / ".batch-renamer-backup.json" ``` ```python def save_backup(self, mappings): with open(self.backup_file, 'w', encoding='utf-8') as f: json.dump(mappings, f, indent=2, ensure_ascii=False) ``` ### Technical Analysis The backup is written to a predictable filename in the user-selected directory. Standard `open(..., 'w')` follows symbolic links and truncates the linked target before writing the JSON data. When the selected directory is writable by an attacker, the attacker can pre-create `.batch-renamer-backup.json` as a symbolic link to another file writable by the victim. The implementation neither checks whether the backup path is a symbolic link nor uses no-follow file-creation semantics. ### Attack Path 1. An attacker has write access to a shared directory that the victim will process. 2. The attacker creates: ```bash ln -s /path/to/victim-writable-target /shared/.batch-renamer-backup.json ``` 3. The victim runs a non-preview rename operation against `/shared` and confirms it. 4. `save_backup()` opens the fixed path in write mode. 5. The operating system follows the symbolic link and truncates the target. 6. The utility writes JSON mapping data into the target file. ### Impact Assessment The attacker can corrupt or replace the contents of an arbitrary file writable by the invoking user. This can destroy configuration or application data and cause denial of service. The operation cannot directly overwrite files for which the invoking user lacks permission.
Remediation
## Remediation Suggestions - Refuse to use a backup path that is a symbolic link. - Open the file with operating-system no-follow semantics where supported. - Create temporary backup data securely in a trusted state directory, set restrictive permissions, flush it, and atomically replace the final regular file. - Verify the file type, ownership, and permissions before reading or replacing an existing backup. - Avoid storing security-sensitive state in an attacker-writable target directory. - Handle race conditions by performing checks and file creation through a single secure descriptor-based operation rather than separate check-and-open calls.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:39
Finding
Installation Documentation Directs Users to Unverified Registry Packages## Vulnerability Details **File Location**: `SKILL.md:39-42` and `README.md:20-25` **Vulnerability Type**: Unverified third-party package installation and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code `SKILL.md` presents the following command as the installation procedure: ```bash npm install -g batch-renamer ``` `README.md` lists registry installation as planned: ```bash npm install -g batch-renamer # or pip install batch-renamer ``` ### Technical Analysis The reviewed project contains a standalone Python script and does not include an npm manifest, Python packaging metadata, lock file, hashes, or other evidence tying the named registry packages to the audited source. Installing a registry package can execute package-controlled installation hooks or later execute code unrelated to this repository. The inconsistency between `SKILL.md`, which presents global npm installation as available, and `README.md`, which describes command-line package installation as planned, increases the likelihood that users will install an unaudited same-name package. This audit does not establish that either registry package is malicious. The confirmed issue is that the documentation directs users toward third-party code whose identity and contents cannot be verified from the reviewed artifact. ### Attack Path 1. A user follows the installation command in `SKILL.md` or `README.md`. 2. The package manager resolves `batch-renamer` from its public registry rather than from this project. 3. The registry package and its transitive dependencies are downloaded without a version pin or integrity information supplied by this project. 4. Package installation hooks, imported modules, or installed executables run code that was not part of the audited artifact. 5. If the registry name is controlled or later compromised by an attacker, attacker-supplied code executes with the installing user's privileges. ### Impact As ...[truncated 443 chars]
Remediation
## Remediation Suggestions - Remove npm and pip installation commands until official packages are published and verifiably linked to this source. - Document direct execution of the reviewed Python script as the supported installation method. - If packages are published, provide canonical registry links, publisher identity, exact versions, checksums or hashes, and reproducible-build information. - Pin dependencies and publish lock files where applicable. - Ensure package metadata links back to the same source repository and release commit. - Avoid global installation unless it is necessary, and clearly explain the additional trust implications. - Keep `SKILL.md` and `README.md` installation status consistent.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (4)

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The skill documentation is written in Chinese throughout and does not indicate that other languages are available or that the user can choose a preferred language. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The manifest description and primary documentation are written in Chinese, and the skill presents itself entirely in that language without indicating that users can opt into another language or that the skill is intentionally region-specific. This is a natural-language locale policy concern under the rule for forced language or locale behavior.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This code presents its title, prompts, status messages, and CLI help text in Chinese, including the confirmation prompt and command descriptions. That creates a natural-language locale restriction without user opt-in or any documented justification that the tool is intended only for Chinese-speaking users.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The manifest description is entirely in Chinese and does not indicate that other languages are supported or that the user can choose a preferred language. This can violate a language/locale policy when skills are expected to be language-neutral or user-selectable.

Static analysis

No suspicious patterns detected.