Back to skill

Security audit

Annotation Visualizer

Security checks for vulnerabilities and agentic risk

Overview

This skill is a normal annotation visualizer, but its COCO mode can use paths from an annotation file to read or overwrite files outside the chosen dataset folders.

Install only if you will run it on trusted datasets or first harden the COCO filename handling. Avoid processing COCO JSON from untrusted sources because it can cause reads or overwrites outside the output directory. Pin Pillow in a reviewed requirements file for more reproducible installs.

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/visualize.py:256
Finding
COCO Filename Path Traversal Enables Arbitrary Image File Access and Overwrite## Vulnerability Details **File Location**: `scripts/visualize.py`, lines 256-258 and 285 **Vulnerability Type**: Unvalidated path traversal and absolute-path injection **Risk Level**: High ### Vulnerable Code ```python img_info = images.get(img_id, {}) img_name = img_info.get('file_name', f'{img_id}.jpg') img_path = images_dir / img_name if not img_path.exists(): continue ``` ```python output_path = output_dir / img_name visualize_image( str(img_path), annotations, str(output_path), thickness=args.thickness, fill=args.fill, show_label=args.show_label, font_size=args.font_size ) ``` The destination is subsequently created and written in `visualize_image`: ```python os.makedirs(os.path.dirname(output_path) if os.path.dirname(output_path) else '.', exist_ok=True) img.save(output_path) ``` ### Technical Analysis The COCO `file_name` property is taken directly from an attacker-controlled JSON annotation and used to construct both input and output paths. The code does not reject absolute paths, `..` path components, or resolved paths outside the configured image and output directories. With `pathlib`, joining a base path to an absolute second operand discards the base path. Relative traversal components can similarly escape the intended directory after path resolution. Consequently, `img_path` can refer to any image file readable by the invoking user, while `output_path` can refer to a location outside the designated output directory. The output function also creates missing parent directories and saves the rendered image without checking whether the destination remains within the approved output directory. ### Attack Path 1. An attacker prepares a COCO JSON document containing an image entry whose `file_name` is an absolute path or includes traversal components, such as `/home/user/important.png` or `../../important.png`. 2. The victim invokes the documented command: ```ba ...[truncated 1359 chars]
Remediation
## Remediation Suggestions Treat every COCO `file_name` value as untrusted input: 1. Reject absolute filenames. 2. Resolve the candidate input and output paths before accessing them. 3. Verify with `Path.relative_to()` or `Path.is_relative_to()` that each resolved path remains under its authorized base directory. 4. Reject filenames containing parent-directory traversal components. 5. Use a sanitized basename or an internally generated filename for output rather than reproducing the input path. 6. Refuse to overwrite existing output files unless explicitly authorized. 7. Avoid automatically creating directories derived from untrusted filenames. Example hardening pattern: ```python images_root = Path(args.images).resolve() output_root = Path(args.output).resolve() supplied_name = Path(img_name) if supplied_name.is_absolute() or ".." in supplied_name.parts: raise ValueError(f"Unsafe COCO filename: {img_name}") input_path = (images_root / supplied_name).resolve() if not input_path.is_relative_to(images_root): raise ValueError(f"Input path escapes images directory: {img_name}") safe_output_name = supplied_name.name output_path = (output_root / safe_output_name).resolve() if not output_path.is_relative_to(output_root): raise ValueError(f"Output path escapes output directory: {img_name}") ``` Where support for older Python versions is required, replace `is_relative_to()` with a guarded `relative_to()` call.

T08 · Insecure Dependencies

Note
Location
SKILL.md:49
Finding
Unpinned Pillow Dependency Creates Supply-Chain and Reproducibility Risk## Vulnerability Details **File Location**: `SKILL.md`, lines 49-53 **Vulnerability Type**: Unpinned third-party runtime dependency **Risk Level**: Low ### Vulnerable Code ```bash ## Installation ```bash pip install pillow ``` ``` ### Technical Analysis The installation instructions request the latest package version available under the `pillow` package name without a reviewed version constraint or cryptographic integrity hash. The package name is legitimate and no dependency-confusion or typosquatting package was identified, but the mutable installation instruction prevents reproducible dependency resolution. Users following these instructions at different times may receive different releases. A compromised package-index account, compromised distribution artifact, or malicious future release could therefore affect installations without any change to this repository. ### Attack Path This issue requires a third-party supply-chain compromise: 1. An attacker compromises the relevant package publication channel or causes a malicious release to be served under the expected dependency name. 2. A user follows the project documentation and runs: ```bash pip install pillow ``` 3. Package resolution selects the current unpinned release. 4. Malicious installation or runtime code executes with the permissions of the user or build environment running `pip` or the visualizer. ### Impact Assessment The direct project code does not retrieve or execute a remote payload by itself; exploitation depends on compromise of the external dependency supply chain. If that occurs, malicious package code could execute with the installing user's privileges and potentially access files, credentials, environment variables, or build artifacts available to that account. In the absence of a supply-chain compromise, the more likely effects are incompatible updates, non-reproducible environments, and unexpected behavior caused b ...[truncated 21 chars]
Remediation
## Remediation Suggestions 1. Pin Pillow to a reviewed version in a dependency file rather than instructing users to install an unconstrained latest release. 2. Generate and verify cryptographic hashes for approved distribution artifacts. 3. Use a lock file or hash-enforced requirements file for reproducible installations. 4. Routinely scan the pinned dependency for disclosed vulnerabilities and update it through a reviewed process. 5. Configure installation to use a trusted package index over authenticated TLS. Example installation file: ```text Pillow==REVIEWED_VERSION \ --hash=sha256:REVIEWED_DISTRIBUTION_HASH ``` Example installation command: ```bash python -m pip install --require-hashes -r requirements.txt ```
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.