Back to skill

Security audit

camsnap

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says: it captures a webcam snapshot on request and saves it locally, with no evidence of hidden exfiltration or persistence.

Install only if you are comfortable with a skill that can access the default webcam when invoked and save the captured image in the current workspace. Review output paths carefully, and prefer a private working directory if other local users or processes can modify the destination folder.

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

T09 · Insecure Skill Coding Practices

Note
Location
camsnap.py:20
Finding

Symlink Race Can Bypass the Output Directory Restriction

Content
View full analysis

Vulnerability Details

File Location: camsnap.py, lines 20–40, 59–68, and 84
Vulnerability Type: Time-of-check to time-of-use (TOCTOU) symlink race
Risk Level: Low

Vulnerable Code

python
def _validate_output_path(output_path: str) -> str:
    """Resolve and validate an output path, guarding against traversal."""
    resolved = Path(output_path).resolve()
    # Block path traversal outside cwd tree
    cwd = Path.cwd().resolve()
    try:
        resolved.relative_to(cwd)
    except ValueError:
        raise ValueError(
            f"Output path escapes working directory: {output_path}"
        )
    ext = resolved.suffix.lower()
    if ext and ext not in ALLOWED_EXTENSIONS:
        raise ValueError(
            f"Unsupported image extension '{ext}'. Allowed: {sorted(ALLOWED_EXTENSIONS)}"
        )
    if not ext:
        # Default to .jpg when no extension given
        resolved = resolved.with_suffix(".jpg")
    return str(resolved)
python
if output_path:
    output_path = _validate_output_path(output_path)
else:
    output_dir = _validate_output_path(output_dir)
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    output_path = os.path.join(output_dir, f"snapshot_{timestamp}.jpg")

# Ensure parent directory exists
os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
python
success = cv2.imwrite(output_path, frame)

Technical Analysis

The script resolves the supplied path and verifies that it is beneath the current working directory. However, validation and image creation are separate filesystem operations. The validated pathname is later passed to os.makedirs() and cv2.imwrite(), both of which resolve path components again.

A local attacker who can modify a destination directory within the working directory can replace a validated path component with a symbolic link after _validate_output_path() returns ...[truncated 1754 chars]

Remediation
View remediation

Remediation Suggestions

  • Avoid validating a pathname and then reopening it through ordinary pathname resolution.
  • Open a trusted descriptor for the working directory and perform descriptor-relative traversal and file creation.
  • On supported platforms, use openat-style operations with O_NOFOLLOW for each relevant path component and reject symbolic links.
  • Verify that every intermediate component is a directory owned or controlled by the expected principal.
  • Create the destination file atomically with restrictive permissions and without following a final symbolic link.
  • Because cv2.imwrite() accepts a pathname rather than an existing file descriptor, encode the image in memory with cv2.imencode() and write the resulting bytes through the securely opened descriptor.
  • If descriptor-relative operations are unavailable, use a private output directory that untrusted users cannot modify and revalidate the parent immediately before writing. Revalidation alone reduces but does not eliminate the race.
  • Add tests that replace validated path components with symlinks and confirm that writes outside the working directory are rejected.
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

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This skill can activate the user's webcam and save an image to disk, but the description and usage text do not prominently warn about that privacy-sensitive action. In an agent setting, insufficient disclosure increases the risk of unexpected image capture, undermining informed user consent and potentially collecting sensitive visual information from the user's environment.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.