Back to skill

Security audit

Annotation Format Converter

Security checks for vulnerabilities and agentic risk

Overview

This is a normal local annotation-conversion skill, but one confirmed path-handling bug can let a crafted COCO file overwrite writable .txt files outside the chosen output folder.

Review before installing or running on annotation files from other people. The converter should be hardened to reject absolute paths and parent-directory components in COCO file_name fields, verify outputs remain inside the chosen output folder, and avoid overwriting existing files unless explicitly requested.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/converter.py:71
Finding
Path Traversal Enables Arbitrary TXT File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/converter.py`, lines 71-90 **Vulnerability Type**: Path traversal and arbitrary file overwrite **Risk Level**: High ### Vulnerable Code ```python # Get base name without extension base_name = os.path.splitext(img_name)[0] output_path = os.path.join(output_dir, f"{base_name}.txt") with open(output_path, 'w') as f: for ann in anns: category_id = ann['category_id'] bbox = ann['bbox'] # [x, y, w, h] # Convert to YOLO format (center_x, center_y, w, h) normalized x_center = (bbox[0] + bbox[2] / 2) / width y_center = (bbox[1] + bbox[3] / 2) / height w = bbox[2] / width h = bbox[3] / height # YOLO uses 0-indexed class IDs f.write(f"{category_id - 1} {x_center} {y_center} {w} {h}\n") ``` ### Technical Analysis The value assigned to `img_name` originates from the untrusted COCO `images[].file_name` field. The code removes only the extension and then joins the remaining value directly to the user-selected output directory. No validation removes parent-directory components, rejects absolute paths, or verifies that the resolved destination remains inside `output_dir`. For example, a value such as `../../target.txt` produces a destination ending in `../../target.txt`. An absolute path can also cause `os.path.join()` to discard the intended output directory entirely. The destination is opened using mode `w`, which creates a missing file or truncates an existing file. Exploitation is constrained to paths writable by the operating-system account running the converter and to filenames ending in `.txt`. ### Attack Path 1. An attacker creates or modifies a COCO annotation file. 2. The attacker places a traversal or absolute path in an `images[].file_name` value, such as `../../configuration.txt`. 3. The attacker causes a user or automated conversion process to run COCO-to-YOLO conversion on that file. 4. `os.path.splitext()` preserve ...[truncated 664 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Treat every COCO `file_name` value as untrusted. - Reduce the supplied filename to a leaf name with `Path(img_name).name` when directory preservation is unnecessary. - Explicitly reject absolute paths and values containing parent-directory components. - Resolve both the output root and candidate destination, then verify that the candidate is contained within the output root. - Refuse to overwrite existing files by default, or require an explicit overwrite option. - Add tests covering absolute paths, `../` traversal, nested traversal, and platform-specific path separators. Example hardening approach: ```python output_root = Path(output_dir).resolve() safe_name = Path(img_name).name base_name = Path(safe_name).stem output_path = (output_root / f"{base_name}.txt").resolve() if output_root not in output_path.parents: raise ValueError("Unsafe output path") with output_path.open("x", encoding="utf-8") as f: ... ``` If overwriting is a required feature, replace mode `x` only after obtaining explicit user authorization. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:59
Finding
Unpinned Third-Party Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 59-63 **Vulnerability Type**: Unrestricted dependency resolution **Risk Level**: Medium ### Vulnerable Code ```bash ## Installation ```bash pip install pillow tqdm ``` ``` ### Technical Analysis The documented installation command retrieves mutable, unconstrained versions of `pillow` and `tqdm` from the package index configured for the user's environment. The project does not provide reviewed version pins, artifact hashes, or a lock file. Consequently, the code installed under the same documented command can change over time. If the configured package index, a package release, or dependency resolution is compromised, package installation or import can introduce attacker-controlled code. Python package installation may execute build hooks when a source distribution is selected. The package names shown are legitimate and there is no evidence that the project intentionally references a malicious package. The risk results from the absence of reproducible, integrity-verified dependency controls. ### Attack Path 1. A user follows the installation instructions in `SKILL.md`. 2. `pip` contacts the package index configured in the user's environment. 3. `pip` selects the latest compatible packages and transitive dependencies without checking project-supplied hashes. 4. A compromised index, malicious release, or tampered artifact is selected. 5. Attacker-controlled code executes during package installation, module import, or subsequent image processing. ### Impact Assessment A compromised dependency can execute with the full privileges of the user performing installation or running the converter. This may permit access to that user's files, environment variables, annotation data, and network resources. The exact scope depends on the execution environment and operating-system permissions. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Create a reviewed dependency file containing exact versions. - Generate and retain cryptographic hashes for every approved distribution. - Install dependencies using hash enforcement, for example: ```bash python -m pip install --require-hashes -r requirements.txt ``` - Document the trusted package index and avoid untrusted extra indexes. - Prefer prebuilt, reviewed wheels where appropriate to reduce exposure to arbitrary build hooks. - Use automated dependency vulnerability scanning and controlled update reviews. - Remove `tqdm` from the installation instructions if it is not required, because the converter currently defines its own local progress function. ]]>
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

Static analysis

No suspicious patterns detected.