Back to skill

Security audit

watermark-remover-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it needs review because a task subdirectory value can escape the configured watch folder and the required external GUI is sourced through unsafe search-based guidance.

Install only if you trust and can verify the external 布衣 GUI application. Use dedicated input and output folders, avoid --move unless you have backups, do not pass user-controlled values to --subdir, and review any directory cleanup before deletion. Prefer a hardened version that rejects absolute paths, '..' components, and any task subdirectory that resolves outside input_dir.

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
watermark_remover.py:135
Finding

Unvalidated Task Subdirectory Allows Writes Outside the Configured Input Directory

Content
View full analysis

Vulnerability Details

File Location: watermark_remover.py, lines 135–137
Vulnerability Type: Path traversal / unrestricted filesystem write
Risk Level: High

Vulnerable Code

python
if task_subdir is None:
    target_root = self.input_dir
    sub = ""
else:
    sub = task_subdir
    target_root = self.input_dir / sub
    target_root.mkdir(parents=True, exist_ok=True)

# First write under a temporary .part name, then rename it.
delivered: list[Path] = []
for src in srcs:
    final_path = target_root / src.name
    tmp_path = final_path.with_suffix(final_path.suffix + ".part")
    try:
        if copy:
            shutil.copy2(src, tmp_path)
        else:
            shutil.move(str(src), str(tmp_path))
        tmp_path.rename(final_path)

Technical Analysis

The task_subdir value can be supplied through the command-line --subdir option and is used directly in a filesystem path without validation. Python path joining does not guarantee that the result remains below self.input_dir.

A value containing parent-directory components, such as ../../target, can traverse outside the configured input directory. An absolute path can replace the intended base path entirely on supported platforms. The script then creates the attacker-selected directory and copies or moves source images into it.

Because no canonical containment check is performed, the intended security boundary around the GUI watch directory is not enforced. The final filename is limited to the source filename, but the destination directory is attacker-controlled.

Attack Path

  1. An attacker causes the Agent or user to process an image while supplying a crafted task subdirectory, for example:
    bash
    python watermark_remover.py process image.png --subdir ../../unintended-directory
    
  2. target_root becomes a path outside the configured input_dir.
  3. `mkdir(parents=True, exist_ok=Tru ...[truncated 1202 chars]
Remediation
View remediation

Remediation Suggestions

Treat task_subdir as a single directory identifier rather than an arbitrary path.

  1. Reject absolute paths.
  2. Reject . and .. path components.
  3. Reject directory separators and platform-specific drive or UNC path syntax if nested task paths are unnecessary.
  4. Resolve the destination and verify that it remains beneath the resolved input directory before creating directories or writing files.
  5. Consider generating task directory names internally and disallowing user-defined paths entirely.
  6. Add tests covering parent traversal, absolute POSIX paths, Windows drive paths, UNC paths, and symbolic-link escapes.

Example hardening:

python
def safe_task_root(input_dir: Path, task_subdir: str) -> Path:
    candidate_name = Path(task_subdir)

    if (
        candidate_name.is_absolute()
        or len(candidate_name.parts) != 1
        or task_subdir in {"", ".", ".."}
        or candidate_name.name != task_subdir
    ):
        raise ValueError("Invalid task subdirectory name")

    base = input_dir.resolve()
    candidate = (base / candidate_name).resolve()

    try:
        candidate.relative_to(base)
    except ValueError as exc:
        raise ValueError("Task directory escapes input_dir") from exc

    return candidate

If directories inside input_dir may contain attacker-controlled symbolic links, perform filesystem operations using mechanisms that prevent symbolic-link traversal, or ensure the selected directory is newly created and verified before use.

T08 · Insecure Dependencies

Warning
Location
README.md:4
Finding

Required Proprietary Dependency Is Recommended Through an Unauthenticated Search Process

Content
View full analysis

Vulnerability Details

File Location: README.md, line 4; also present in SKILL.md, line 24
Vulnerability Type: Unsafe third-party software acquisition / supply-chain exposure
Risk Level: Medium

Vulnerable Documentation

The installation guidance states, in English translation:

text
If the software is not available, search for the Buyi batch image watermark-removal software to obtain it.

The skill documentation similarly instructs users without the required membership or application to search for the software.

Technical Analysis

The project depends operationally on an external proprietary GUI application, but it does not identify an authenticated official distribution endpoint, verified publisher identity, cryptographic checksum, or code-signing verification procedure.

Directing users to obtain executable software through a generic search exposes them to malicious advertisements, search-result poisoning, counterfeit download sites, repackaged installers, and similarly named executables. The Python project has no third-party package dependencies, but the GUI executable is a required runtime component and therefore remains part of the effective supply chain.

Attack Path

  1. A user follows the project’s instruction to search for the required GUI application.
  2. A malicious advertisement or search result presents a counterfeit or modified installer using the expected product name.
  3. The user downloads and executes the unverified software.
  4. The malicious program runs with the user’s local privileges and receives access to the configured input and output directories.
  5. It can read submitted images, alter output files, exfiltrate local data, or perform any other action permitted to the compromised user account.

Impact Assessment

Successful exploitation can result in arbitrary code execution under the installing user’s account. The counterfeit application may access all files av ...[truncated 416 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace generic search instructions with the verified publisher’s canonical HTTPS download URL.
  2. State the expected publisher and product identity.
  3. Document how to verify the executable’s platform code-signing certificate and expected signer.
  4. Publish version-specific cryptographic hashes through an authenticated project channel.
  5. Warn users not to install copies from advertisements, mirrors, file-sharing sites, or unverified search results.
  6. Pin or document a known-compatible application version.
  7. If the publisher and distribution provenance cannot be verified, remove the recommendation and clearly state that the external component has not been security-reviewed.
  8. Where practical, isolate the GUI application using a dedicated low-privilege account or sandbox and grant access only to dedicated input and output directories.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README exposes a destructive --move mode that deletes the original input file after handing it to the workflow, but the warning is brief and embedded in a command list rather than presented as a prominent pre-use safety notice. In an agent-driven context, users may copy commands or authorize actions without appreciating that source images can be irreversibly removed, creating avoidable data-loss risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The README recommends deleting task subdirectories after processing to keep the environment clean, but it does not clearly warn that automated cleanup can remove user-supplied images or intermediate artifacts that may still be needed. Because this skill is designed for batch processing and possible shared use, an agent following this guidance could delete the wrong directory or erase evidence needed for verification or rollback.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill directs use of a local script that reads configuration, environment variables, and user-supplied file paths, yet the manifest declares no explicit tool scope or permissions boundaries. That makes the skill easier to invoke with broader-than-necessary filesystem and environment access, increasing the chance of unintended file access, file overwrite, or misuse of local configuration during automation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger language is broad enough to auto-activate on generic 'watermark removal' or uploaded-image requests without strong confirmation that the user intends to use this specific local GUI automation workflow. In context, this can cause the agent to move or copy local files into monitored directories and initiate processing in external software unexpectedly, which is a meaningful safety and privacy risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The usage section states that the skill should be used whenever the user mentions watermark removal and the skill is configured, but it does not clearly constrain when automation is appropriate versus when the agent should ask for confirmation. Because this skill performs local filesystem actions and hands files to a third-party GUI, ambiguous activation can lead to unintended processing of sensitive images or accidental batch operations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The JSON comment strings are written entirely in Chinese and present the configuration requirements as mandatory instructions, with no indication that another language is supported or that the locale restriction is intentional. This matches the policy category for language/locale constraints expressed in natural-language content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code performs a file write via --json-out and directly writes JSON content to the specified path. Although the CLI option name implies output creation, there is no nearby confirmation or explicit warning that an existing file may be overwritten, which is a safety-relevant local file modification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.