Back to skill

Security audit

Image Cropper

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent image-cropping tool, but its COCO mode can read image files outside the chosen image directory when given a crafted annotation file.

Review this skill before installing. Use it only on trusted annotation files or run it in a sandbox with access limited to the intended image dataset, especially for COCO input. Avoid reusing an output directory containing files you need to preserve, and prefer pinning Pillow in your environment.

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

Warning
Location
scripts/cropper.py:188
Finding
COCO Annotation Filename Path Traversal Allows Unauthorized Local Image Access## Vulnerability Details **File Location**: `scripts/cropper.py`, lines 188-224 **Vulnerability Type**: Path traversal caused by an untrusted COCO `file_name` **Risk Level**: Medium ### Vulnerable Code ```python for img_id, img_info in images.items(): img_name = img_info.get('file_name', f'{img_id}.jpg') img_path = images_dir / img_name if not img_path.exists(): continue width = img_info.get('width', 0) height = img_info.get('height', 0) if width == 0 or height == 0: with Image.open(img_path) as img: width, height = img.size # Parse annotations annotations = parse_coco_annotation(coco_data, img_id) if not annotations: continue if args.objects: for i, bbox in enumerate(annotations): class_id, x1, y1, x2, y2 = bbox if args.min_size: if (x2 - x1) < args.min_size or (y2 - y1) < args.min_size: continue cropped = crop_image(str(img_path), bbox, args.padding, width, height) base_name = Path(img_name).stem output_name = f"{base_name}_{i}.{args.format}" output_path = output_dir / output_name cropped.save(output_path, quality=args.quality) total_cropped += 1 else: cropped = crop_image(str(img_path), annotations[0], args.padding, width, height) base_name = Path(img_name).stem output_path = output_dir / f"{base_name}_crop.{args.format}" cropped.save(output_path, quality=args.quality) total_cropped += 1 ``` ### Technical Analysis The COCO `file_name` property is read from an externally supplied JSON annotation and appended directly to `images_dir`. The application does not reject absolute paths, normalize traversal components, resolve symbolic links, or verify ...[truncated 1972 chars]
Remediation
## Remediation Suggestions Resolve and validate every annotation-derived path before accessing it: ```python images_root = Path(args.images).resolve() raw_name = img_info.get("file_name", f"{img_id}.jpg") relative_name = Path(raw_name) if relative_name.is_absolute(): raise ValueError(f"Absolute image path is not allowed: {raw_name}") img_path = (images_root / relative_name).resolve() try: img_path.relative_to(images_root) except ValueError: raise ValueError(f"Image path escapes the image directory: {raw_name}") if not img_path.is_file(): continue ``` The containment check must occur after resolution so that both `..` traversal and symbolic-link escapes are rejected. Consider additionally allowing only expected filename suffixes, rejecting unexpected nested paths if dataset semantics do not require them, and logging rejected records without exposing sensitive absolute paths. Add regression tests covering absolute paths, `../` traversal, nested traversal, and symlinks that point outside the image root.

T08 · Insecure Dependencies

Note
Location
SKILL.md:39
Finding
Unpinned Pillow Dependency Creates a Non-Reproducible Supply-Chain Risk## Vulnerability Details **File Location**: `SKILL.md`, lines 39-43 **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Low ### Vulnerable Code ```markdown ## Installation ```bash pip install pillow ``` ``` ### Technical Analysis The documented installation command retrieves whichever Pillow release satisfies pip's default resolution at installation time. No reviewed version, lock file, package hash, or package-index restriction is specified. Consequently, separate installations can receive different code even though the audited project remains unchanged. This is a supply-chain hardening weakness rather than evidence that the current Pillow package is malicious. Exploitation depends on hostile or compromised package-index content, a compromised future dependency release, or manipulation of the package source used by pip. ### Attack Path 1. A user follows the documented installation command. 2. Pip queries its configured package index and resolves the current release of Pillow. 3. If the selected release or package source has been compromised, unreviewed code is installed into the environment. 4. Malicious package behavior may run during installation, import, or subsequent image processing with the privileges of the user running pip or the cropper. ### Impact Assessment The immediate project contains no demonstrated malicious dependency payload. However, mutable dependency resolution prevents reproducible installation and allows dependency code to change after this Skill has been reviewed. If the dependency source were compromised, code could run with the installing user's privileges. The resulting scope could include files, environment variables, network access, and other resources available to that account. The actual impact is contingent upon a separate supply-chain compromise and is therefore rated Low for this project.
Remediation
## Remediation Suggestions Pin Pillow to a reviewed version in a dependency file and verify downloaded artifacts with hashes. For example: ```text Pillow==REVIEWED_VERSION --hash=sha256:REVIEWED_DISTRIBUTION_HASH ``` Install it using: ```bash python -m pip install --require-hashes -r requirements.txt ``` Record hashes for every supported platform artifact or deploy from a controlled internal package mirror. Automate dependency updates through a review process that runs tests and vulnerability scanning before changing the pinned version. The documentation should reference the locked dependency file instead of instructing users to install an unconstrained latest release.
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 (1)

Missing User Warnings

Low
Confidence
78% confidence
Finding
This code creates and uses a user-supplied output directory for saving cropped images, which is a file-writing operation covered by the warning requirement for code files. While the script's purpose implies cropping, there is no explicit confirmation prompt or user-facing warning that running it will create files and may overwrite existing names in the target directory.

Static analysis

No suspicious patterns detected.