Back to skill

Security audit

Has Anonymizer

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to perform local anonymization as advertised, but its privacy-sensitive workflow depends on mutable, unverified downloads and open-ended Python dependencies.

Install only if you are comfortable trusting the current upstream Python packages and model repositories, or pin and verify the dependencies and model checksums yourself. Treat mapping files and restored outputs as sensitive because they can reveal the original private data.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
scripts/has_image.py:2
Finding

Unpinned Runtime Dependencies and Unverified Mutable Model Artifact

Content
View full analysis
=3.10" # dependencies = [ # "requests>=2.31.0", # ] # /// ``` `scripts/has-text.sh:9`: ```bash exec uv run "$SCRIPT_DIR/has_text_entry.py" "$@" ``` `scripts/has_image.py:2-8`: ```python # /// script # requires-python = ">=3.10" # dependencies = [ # "ultralytics>=8.3.0", # "opencv-python-headless>=4.8.0", # "pillow>=10.0.0", # ] # /// ``` `scripts/has-image.sh:9`: ```bash exec uv run "$SCRIPT_DIR/has_image.py" "$@" ``` `SKILL.md:52-56`: ```json { "id": "download-image-model", "kind": "download", "url": "https://huggingface.co/xuanwulab/HaS_Image_0209_FP32/resolve/main/sensitive_seg_best.pt", "targetDir": "models", "label": "Download HaS image model FP32 (119 MB)" } ``` `scripts/has_image.py:190-200`: ```python from ultralytics import YOLO path = model_path or os.environ.get("HAS_IMAGE_MODEL", _DEFAULT_MODEL_PATH) if not os.path.isfile(path): _die( "model_not_found", f"Model file not found: {path}\n" f"Download it via: openclaw install has-anonymizer " f"(or manually from HuggingFace)" ) _verbose(f"Loading image model from {path}...") _MODEL = YOLO(path) ``` ### Technical Analysis The text and image launchers invoke `uv run` against inline dependency declarations that use open-ended minimum-version constraints. No reviewed lockfile, exact version pin, or package hash is present in the audited project. As a result, dependency resolution can select releases published after the Skill was reviewed. The image model download URL uses Hugging Face's mutable `resolve/main` reference rather than an immu ...[truncated 2629 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

If the skill mainly computes mappings or expects pre-existing tags instead of performing true anonymization/restoration, users could rely on a non-protective workflow for sensitive material. Because the skill is explicitly marketed for privacy-preserving sharing, any incomplete or misleading implementation meaningfully raises the risk of data leakage.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the skill mainly computes mappings or expects pre-existing tags instead of performing true anonymization/restoration, users could rely on a non-protective workflow for sensitive material. Because the skill is explicitly marketed for privacy-preserving sharing, any incomplete or misleading implementation meaningfully raises the risk of data leakage.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the skill mainly computes mappings or expects pre-existing tags instead of performing true anonymization/restoration, users could rely on a non-protective workflow for sensitive material. Because the skill is explicitly marketed for privacy-preserving sharing, any incomplete or misleading implementation meaningfully raises the risk of data leakage.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The seek/restoration prompt sends the full anonymized-to-original mapping together with the tagged text to a model, which reconstructs all previously hidden sensitive values in one request. In the skill context, this is especially dangerous because the tool is marketed for privacy protection before sharing with LLMs; if restoration is performed through a model interface, the most sensitive data is re-exposed and the privacy boundary can collapse.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares substantial capabilities—environment access, file read/write, network downloads, and shell execution—yet provides no explicit permission or allowed-tools scope. That weakens least-privilege controls and increases the chance an agent may invoke the skill with broader access than intended, especially because the skill handles sensitive text, mappings, and images.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
### Public/private distinction

Type wording matters. For example, `"personal location"` is usually safer than `"location"` if you want to preserve public places but hide private addresses. Public/private person-name distinctions remain less stable and should not be trusted without verification.

### Multilingual support

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · references/eval/eval.py (reported line 45)May include surrounding context.

python
def run_cmd(command: list[str], *, cwd: Path) -> CmdResult:
    """Run a command, parse stdout as JSON, return structured result."""
    proc = subprocess.run(
        command, cwd=cwd, text=True, capture_output=True, check=False
    )
    stdout = proc.stdout.strip()

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The JSON case explicitly sets the language to "zh-CN", which forces a specific locale in the skill data without any indication of user opt-in or alternative language handling. Under the policy, locale constraints should either offer a choice or be clearly documented and justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This JSON file contains language-specific cases for zh-CN, en, ja, ko, fr, de, es, and pt, but there is no accompanying natural-language indication that locale selection is optional or constrained to a justified region-specific use case. Under the stated policy, forcing or embedding fixed language/locale behavior without user opt-in can be a policy concern across all file types.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/has_image.py (reported line 173)May include surrounding context.

python
# ---------------------------------------------------------------------------

_MODEL = None
_MODEL_LOCK = __import__("threading").Lock()
_DEFAULT_MODEL_PATH = os.path.expanduser(
    "~/.openclaw/tools/has-anonymizer/models/sensitive_seg_best.pt"
)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The _model_pair path sends both the original text and the anonymized text to the model service to reconstruct mappings. That materially increases exposure because the service receives the sensitive source content plus the transformed output, which can aid re-identification and undermine the privacy guarantees expected from an anonymization tool, especially since the skill context involves PII-heavy documents, logs, emails, and images.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code sends raw input text to a model service via client.chat(...) during NER/Hide processing, but this file provides no user-facing disclosure or consent check at the transmission point. Because this skill is specifically marketed for anonymizing sensitive content before wider sharing, users may reasonably expect stronger transparency about what data leaves the immediate processing context, making undisclosed transmission a real privacy risk if the backing service is remote, logged, or misconfigured.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The scan path sends raw chunk text to client.chat(messages), which means sensitive document contents are transmitted to an external model service during a feature explicitly described as privacy scanning. In a privacy/anonymization skill, this is especially dangerous because users may reasonably expect local handling or at least a clear disclosure before highly sensitive text is sent off-device or to a remote server.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

When deterministic restoration is insufficient, this code prepares model prompts containing the anonymized text and the tag-to-original-value mapping, then sends them through client.chat(...) to a server. In the context of an anonymization tool, that mapping is effectively the secret needed to reconstruct sensitive plaintext, so transmitting both the text and mapping can fully de-anonymize user data and defeats the privacy boundary if the server is remote, logged, or multi-tenant.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

Batch restore writes fully restored plaintext back to disk, which may include names, IDs, passport numbers, or other sensitive entities that were previously anonymized. Without an explicit warning or safer defaults, users may unintentionally create persistent plaintext artifacts in output directories, backups, sync folders, or shared filesystems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

Single-file restore can persist de-anonymized plaintext to disk via write_text_output, again turning transient restoration into durable sensitive data storage. In a privacy-focused tool, silent plaintext output increases the risk of accidental disclosure through local compromise, indexing, cloud sync, or operational mishandling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This Python file constructs chat API messages containing the user's complete original text and, in other functions, mappings from anonymized entities back to original entities. Although sending such content to a model endpoint is a data-transmission operation, the code provides no confirmation, logging, comment warning, or other user-facing disclosure about that behavior.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/has_text/server_runtime.py (reported line 144)May include surrounding context.

python
if shutil.which("lsof") is None:
        return None

    result = subprocess.run(
        ["lsof", "-tiTCP:%d" % port, "-sTCP:LISTEN"],
        check=False,
        capture_output=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/has_text/server_runtime.py (reported line 160)May include surrounding context.

python
def _read_process_command(pid: int) -> Optional[str]:
    result = subprocess.run(
        ["ps", "-p", str(pid), "-o", "command="],
        check=False,
        capture_output=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/has_text/server_runtime.py (reported line 260)May include surrounding context.

python
port = _parse_port(server_url)
    log_path = f"/tmp/llama-server-{port}.log"
    with open(log_path, "ab") as log_handle:
        process = subprocess.Popen(
            [
                "llama-server",
                "--host",

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

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

md
### Open-set types

Repeated `--type` flags are open-set. They are not limited to a fixed catalog. Natural language type names such as `"person name"`, `"address"`, `"phone number"`, or `"numeric values (transaction amounts)"` are valid.

### Public/private distinction

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The markdown states that for all non-Chinese text, users should use English type names, which imposes a specific language choice across French, German, Spanish, and other supported languages. This is a natural-language locale policy constraint without offering a user choice or documenting why English is required.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

This JSON test corpus explicitly fixes language values such as "zh-CN", "en", "ja", "fr", and "es" for different cases. If this skill is used operationally rather than purely for offline evaluation, that could enforce a locale without user opt-in, which falls under the language/locale policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code creates parent directories and writes masked image files to disk, including in batch mode, but the implementation provides no runtime confirmation, print/log disclosure by default, or explicit warning comment/docstring near the write path. Although writing output is part of the skill's purpose, users are not clearly warned in-code that running the hide command will create new files and directories automatically.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.