Back to skill

Security audit

Batch Rename

Security checks for vulnerabilities and agentic risk

Overview

This is a normal batch-renaming tool, but its restore and overwrite handling can move or destroy files beyond what users may reasonably expect.

Review before installing. Use preview mode first, avoid --force unless you have an independent backup, and do not run the restore command in directories supplied by someone else or containing an untrusted .rename_backup.json. Treat rename operations as potentially irreversible until the tool creates and validates its own backup manifest.

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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/rename.py:109
Finding
Existing destination files can be overwritten without the force option## Vulnerability Details **File Location**: `scripts/rename.py`, lines 109-130 **Vulnerability Type**: Unsafe file replacement and incomplete conflict validation **Risk Level**: Medium **Vulnerable Code**: ```python # First, check for conflicts new_names = [r['new_img'] for r in renames] if len(new_names) != len(set(new_names)): print("Error: Duplicate filenames would be created") return # Rename files renamed_images = 0 renamed_annotations = 0 errors = [] for r in renames: old_path = Path(args.directory) / Path(r['old_img']).name new_path = Path(args.directory) / r['new_img'] try: # Handle overwrite if args.force and new_path.exists(): new_path.unlink() old_path.rename(new_path) renamed_images += 1 # Rename annotation if exists if r['old_ann'] and r['new_ann']: if args.force and r['new_ann'].exists(): r['new_ann'].unlink() r['old_ann'].rename(r['new_ann']) renamed_annotations += 1 ``` ### Technical Analysis The preflight check only determines whether multiple source images generate the same destination name. It does not determine whether a generated image or annotation destination already exists on disk. The existence checks are only used to explicitly delete destinations when `--force` is enabled. Without that option, the code still invokes `Path.rename()` against the destination. On platforms where the underlying rename operation replaces existing files, this can silently overwrite destination content despite the absence of explicit overwrite authorization. Conflict validation is also performed only for generated image names. Existing annotation destinations and duplicate generated annotation paths are not comprehensively validated. Because image and annotation changes are applied incrementally, a conflict or error encountered partway through processin ...[truncated 1112 chars]
Remediation
## Remediation Suggestions - Resolve and validate every source and destination before making any filesystem changes. - Reject any existing destination unless `--force` was explicitly supplied. - Apply the same conflict checks to image and annotation destinations. - Detect duplicate generated annotation names in addition to duplicate image names. - Ensure that a destination which is also a source in the same batch is handled safely. - Use a two-phase rename process: first move all sources to unique temporary names within the same filesystem, then move them to their final destinations. - Record a complete transaction manifest before mutation and roll back all completed operations if any step fails. - When force mode is enabled, back up existing destination files rather than unlinking them immediately. - Use resolved-path containment checks to ensure all final destinations remain inside their intended directories.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/rename.py:143
Finding
Restore operation trusts attacker-controlled paths from the backup file## Vulnerability Details **File Location**: `scripts/rename.py`, lines 143-169 **Vulnerability Type**: Arbitrary file relocation through unvalidated backup entries **Risk Level**: High **Vulnerable Code**: ```python def cmd_restore(args): """Restore from backup""" backup_file = Path(args.directory) / ".rename_backup.json" if not backup_file.exists(): print("No backup found") return import json with open(backup_file, 'r') as f: backup = json.load(f) print(f"Found backup with {len(backup)} files") confirm = input("Restore original filenames? (y/n): ") if confirm.lower() != 'y': print("Cancelled") return restored = 0 for item in backup: try: current = Path(item['current']) original = Path(item['original']) if current.exists(): current.rename(original) restored += 1 except Exception as e: print(f"Error: {e}") print(f"✓ Restored {restored} files") backup_file.unlink() ``` ### Technical Analysis The restore command treats the contents of `.rename_backup.json` as trusted filesystem paths. The `current` and `original` fields are passed directly to `Path` and then used in a rename operation without schema validation, path normalization, extension validation, or containment enforcement. Consequently, backup entries can contain absolute paths or relative paths with traversal components. Neither endpoint is required to reside in the directory supplied on the command line. If an attacker can place or modify `.rename_backup.json` in a directory that a victim later restores, the file can instruct the program to move any file accessible to the victim to another writable location. The generic confirmation prompt only reports the number of entries. It does not display the source and destination paths, so it does not ...[truncated 1629 chars]
Remediation
## Remediation Suggestions - Accept only relative filenames in backup records; reject absolute paths and any path containing traversal components. - Resolve the image and annotation roots and verify with `Path.resolve()` that every source and destination remains beneath an explicitly approved root. - Define and validate a strict JSON schema, including required fields, string types, permitted extensions, unique entries, and a bounded entry count. - Generate backup manifests exclusively through the rename operation and write them atomically with restrictive permissions. - Add an integrity mechanism, such as an authenticated checksum tied to locally generated state, if backup files may be exposed to untrusted writers. - Display every resolved source-to-destination mapping before confirmation. - Reject existing destinations by default and require separate explicit authorization for replacement. - Preserve the backup when any restoration operation fails. - Implement transactional restoration and rollback so that a partial restore does not leave the filesystem inconsistent.

other

Note
Location
SKILL.md:11
Finding
Advertised undo support is not implemented by the rename operation## Vulnerability Details **File Location**: `SKILL.md`, line 11; `scripts/rename.py`, lines 142-169 **Vulnerability Type**: Misleading recovery capability and missing transactional backup **Risk Level**: Low **Relevant Documentation**: ```markdown - **Undo Support**: Restore original filenames ``` **Relevant Code**: ```python def cmd_restore(args): """Restore from backup""" backup_file = Path(args.directory) / ".rename_backup.json" if not backup_file.exists(): print("No backup found") return import json with open(backup_file, 'r') as f: backup = json.load(f) ``` ### Technical Analysis The documentation states that the Skill supports undoing rename operations. The restore implementation requires a `.rename_backup.json` file, but the audited rename implementation never creates that file or records image and annotation mappings. Users may therefore authorize a destructive batch operation under the mistaken assumption that the built-in restore command can reverse it. This is particularly significant because rename operations are performed incrementally and errors are collected rather than triggering a transaction rollback. A failed or interrupted operation can leave files partially renamed with no automatically generated recovery manifest. ### Attack Path 1. A user relies on the documented undo capability and performs a batch rename. 2. Existing files are replaced, an annotation rename fails, or execution is interrupted after only some files have been changed. 3. The user invokes the restore command to recover the original names. 4. The command reports `No backup found` because the rename command did not create `.rename_backup.json`. 5. The user must reconstruct the original mappings manually, and overwritten content may be unrecoverable. This issue does not require a malicious actor, although an attacker could exploit the user's confidence in the docume ...[truncated 408 chars]
Remediation
## Remediation Suggestions - Create a complete backup manifest atomically before the first filesystem mutation. - Record original and final mappings for both images and annotations. - Use paths relative to validated dataset roots rather than unrestricted absolute paths. - Flush and safely persist the manifest before applying any rename. - Keep the manifest until restoration succeeds completely or the user explicitly discards it. - Integrate rollback into the rename operation so failures automatically reverse prior changes. - Add automated tests for successful restoration, interrupted operations, collisions, malformed manifests, and annotation failures. - If undo support will not be implemented, remove the claim from `SKILL.md` and clearly warn that rename operations may be irreversible.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • 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 (5)

Self-Modification

High
Category
Rogue Agent
Content
- `--start`: Starting number for sequential renaming
- `--annotations`: Path to annotation files (will be renamed together)
- `--preview`: Preview changes without applying
- `--force`: Overwrite existing files
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Self-Modification

High
Category
Rogue Agent
Content
- `--start`: Starting number for sequential renaming
- `--annotations`: Path to annotation files (will be renamed together)
- `--preview`: Preview changes without applying
- `--force`: Overwrite existing files
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill documents a `--force` option that overwrites existing files but does not clearly warn about irreversible data loss or advise safeguards. In a batch-renaming context, this is dangerous because users may unintentionally destroy images or annotations at scale, especially when filenames collide.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The script exposes a restore workflow that depends on `.rename_backup.json`, but the rename path never creates that backup before modifying files. This can mislead users into believing renames are reversible when they are not, increasing the chance of permanent data loss after bulk file operations or forced overwrites.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
This is the same underlying issue as SDI-4: the script claims it can restore from backup, but no backup is ever generated during rename operations. In a batch-renaming tool, that mismatch is dangerous because users may proceed with destructive changes under a false assumption of recoverability.

Static analysis

No suspicious patterns detected.