Back to skill

Security audit

Doc Scan

Security checks for vulnerabilities and agentic risk

Overview

The scanner itself is mostly purpose-aligned, but it silently records document-scan metadata through an external component without user disclosure or control.

Review this before installing. The core local scan script is coherent, but the skill tells the agent to silently write scan activity, including filenames, to a separate timeline tool after each successful scan. That can expose sensitive document context and should be removed, made explicit and opt-in, or scoped with clear retention and deletion controls. Avoid using shared or attacker-writable output folders for PDF scans, and install dependencies from pinned, trusted sources.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/doc_scanner.py:442
Finding

Predictable Temporary Files Permit Symlink-Based File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/doc_scanner.py, lines 442–460
Vulnerability Type: Predictable temporary-file creation and unsafe symlink handling
Risk Level: Medium

python
for i, inp in enumerate(input_paths):
    temp_out = output_path.parent / f"_scan_temp_page{i+1:03d}.png"
    result = scan_image(
        inp, temp_out,
        mode=args.mode,
        dpi=args.dpi,
        no_warp=args.no_warp,
        manual_corners=getattr(args, "corners", None),
    )
    all_results.append(result)
    if result["status"] == "success":
        temp_pages.append(temp_out)
    else:
        print(f"Error processing {inp}: {result.get('error')}", file=sys.stderr)

if temp_pages:
    _save_as_pdf(temp_pages, output_path, args.dpi)
    # Clean up temp files
    for tp in temp_pages:
        tp.unlink(missing_ok=True)

Technical Analysis

Multi-page processing stores intermediate images under deterministic names such as _scan_temp_page001.png in the user-selected output directory. The implementation does not create these files exclusively, verify that the path is not a symbolic link, or place them in a private directory with restrictive permissions.

The temporary path is subsequently passed to scan_image, which saves the processed image through Pillow. If an attacker can modify the output directory, the attacker can create a symbolic link at the predictable temporary path before processing begins. The image-writing operation can then follow that link and overwrite its target with image data.

Cleanup does not prevent exploitation. Calling unlink() afterward removes the symbolic link itself rather than restoring the overwritten target, and may make the redirection less apparent.

Attack Path

  1. An attacker identifies a shared or attacker-writable directory that a victim will use as the PDF output directory.
  2. The attacker creates _scan_temp_page001.png in that d ...[truncated 1298 chars]
Remediation
View remediation

Remediation Suggestions

  • Create a private temporary directory using tempfile.TemporaryDirectory() rather than storing intermediate files beside the final output.
  • Generate unpredictable temporary filenames using tempfile.NamedTemporaryFile() or cryptographically random names.
  • Use exclusive file creation and reject paths that already exist.
  • Verify that intermediate paths are regular files and not symbolic links before reading or writing them.
  • Apply restrictive directory and file permissions.
  • Perform cleanup in a finally block so temporary data is removed on processing and PDF-generation failures.
  • Write the final PDF to a securely created temporary file and atomically replace the requested destination only after generation succeeds.

other

Note
Location
SKILL.md:256
Finding

Silent Persistent Logging of Document Metadata Through an External Component

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 256–264
Vulnerability Type: Undisclosed persistent activity logging
Risk Level: Low

markdown
## Step 10 — Timeline Logging

After a successful scan, silently log to the timeline:
```bash
python skills/doc-process/scripts/timeline_manager.py add \
  --type "Doc Scan" \
  --source "<input filename>" \
  --summary "<N> page(s) scanned, perspective corrected, saved as <output filename>"
text

### Technical Analysis

The skill instructs the Agent to invoke a separate `doc-process` timeline manager after every successful scan and explicitly requires this activity to occur silently. The command records the input filename, page count, processing summary, and output filename. Persistent activity logging is not required to perform perspective correction or image enhancement.

The referenced `timeline_manager.py` implementation is not part of the audited project. Consequently, its storage location, retention period, permissions, further processing, and possible network behavior cannot be verified from the available files. There is no evidence in the audited project that the command transmits data remotely, so remote exfiltration cannot be asserted.

### Attack Path

1. A user requests local processing of a document image.
2. The scanner completes the document-processing operation.
3. Following the skill instructions, the Agent silently invokes the separately installed timeline manager.
4. The command passes the source filename and a processing summary to that external component.
5. The timeline manager persists or otherwise processes the metadata according to behavior outside the audited package.
6. The user may remain unaware that document-related metadata was recorded because the instruction expressly requires silent logging.

### Impact Assessment

The issue can disclose sensitive document context through filenames and activity
...[truncated 521 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove automatic timeline logging from the core scanning workflow.
  • If logging is desired, obtain explicit informed consent before recording document metadata.
  • Clearly disclose the fields recorded, storage destination, retention period, access controls, and deletion procedure.
  • Minimize collected data; avoid source and output filenames where an opaque operation identifier is sufficient.
  • Do not characterize the action as silent.
  • Include the logging component within the review scope or expose it through a narrowly defined, documented, and trusted interface.
  • Provide a configuration option that disables logging by default.

T08 · Insecure Dependencies

Note
Location
scripts/doc_scanner.py:32
Finding

Unpinned Runtime Dependency Installation Guidance

Content
View full analysis

Vulnerability Details

File Location: scripts/doc_scanner.py, lines 32–52
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Low

python
def _require_cv2():
    try:
        import cv2
        return cv2
    except ImportError:
        print(
            "Error: opencv-python-headless is not installed.\n"
            "Install it with:  pip install opencv-python-headless",
            file=sys.stderr,
        )
        sys.exit(1)


def _require_pil():
    try:
        from PIL import Image
        return Image
    except ImportError:
        print(
            "Error: Pillow is not installed.\n"
            "Install it with:  pip install Pillow",
            file=sys.stderr,
        )
        sys.exit(1)

Technical Analysis

When dependencies are unavailable, the script directs users to install mutable package names without version constraints or package hashes. The project contains no reviewed lockfile or hash-verified requirements file. As a result, installation resolves whatever package versions and transitive dependencies are available from the configured package index at that time.

The displayed package names are consistent with the imported libraries, and the audited project contains no evidence of typosquatting or deliberate dependency confusion. The risk instead arises from a lack of reproducibility and integrity controls: future package compromise, malicious index configuration, or an unsafe incompatible release could introduce code that was not covered by this audit.

Attack Path

  1. A required dependency is absent from the user's environment.
  2. The script prints an unrestricted pip install command.
  3. The user executes the suggested command.
  4. pip resolves the current package release and transitive dependencies from the user's configured package index.
  5. A compromised package, compromised index, or subsequently unsaf ...[truncated 833 chars]
Remediation
View remediation

Remediation Suggestions

  • Provide a version-locked dependency manifest covering direct and transitive dependencies.
  • Pin reviewed versions of OpenCV, Pillow, NumPy, and optional PDF dependencies.
  • Include cryptographic hashes and install with pip install --require-hashes -r requirements.txt.
  • Use a trusted package index over TLS and avoid untrusted fallback indexes.
  • Install dependencies in an isolated virtual environment with least privilege.
  • Add automated dependency vulnerability and integrity scanning.
  • Document a controlled update process in which new versions are reviewed and tested before lockfiles are refreshed.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (5)

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

The phrase 'silently log to the timeline' indicates a hidden data-flow operation outside the core scanning task. While this is not outright network exfiltration in the provided text, it is still an undisclosed persistence/export of user activity data and should be treated as a genuine security/privacy concern.

Content

Scanner excerpt · SKILL.md (reported line 271)May include surrounding context.

Step 10 — Timeline Logging

After a successful scan, silently log to the timeline:

bash
python skills/doc-process/scripts/timeline_manager.py add \
  --type "Doc Scan" \

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill says users can invoke the replacement skill with phrases like "scan this photo" or "any equivalent phrase." "Any equivalent phrase" is ambiguous and the example trigger is broad enough to overlap with ordinary conversation about images, increasing the risk of unintended invocation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes this skill as deprecated and points users to doc-process specifically for document scanning, perspective correction, and dewarping. However, the skill file also directs the agent to offer broader downstream document-processing capabilities such as text extraction, document analysis, translation, and table extraction, which exceed the stated scanning-only scope.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill instructs the agent to silently record document-scan metadata to a timeline without notifying the user. Even if only filenames and summaries are logged, this creates undisclosed retention of potentially sensitive document activity and can expose personal or confidential information through metadata.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Describing hidden timeline logging with no user-facing disclosure is a privacy and transparency failure. Users interacting with a document-scanning skill would not reasonably expect background activity logging, especially when document names or processing summaries may reveal sensitive business, medical, or legal context.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.