Back to skill

Security audit

Caveman Input Compression

Security checks for vulnerabilities and agentic risk

Overview

This skill is review-worthy because a file-compression task can send sensitive local files and API keys to configurable model endpoints without enforcing its documented file scope.

Install only if you are comfortable with selected files being processed by external model providers and with the skill using ambient API credentials. Before use, restrict it to a trusted workspace path, avoid broad environment variables like OPENAI_BASE_URL for untrusted endpoints, prefer a local-only provider, and manually verify backups and compressed output before replacing important bootstrap files.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/compress.py:127
Finding

Document Scope Restrictions Are Not Enforced by the Compression Workflow

Content
View full analysis
[--dry-run]", file=sys.stderr) sys.exit(1) filepath = sys.argv[1] dry_run = "--dry-run" in sys.argv # Check feature flags if "AGENTS.md" in filepath and not os.environ.get("CAVEMAN_COMPRESS_AGENTS"): print("⚠️ AGENTS.md compression disabled (set CAVEMAN_COMPRESS_AGENTS=1)") sys.exit(0) if "HEARTBEAT.md" in filepath and not os.environ.get("CAVEMAN_COMPRESS_HEARTBEAT"): print("⚠️ HEARTBEAT.md compression disabled (set CAVEMAN_COMPRESS_HEARTBEAT=1)") sys.exit(0) if "MEMORY.md" in filepath and not os.environ.get("CAVEMAN_COMPRESS_MEMORY"): print("⚠️ MEMORY.md compression disabled (set CAVEMAN_COMPRESS_MEMORY=1)") sys.exit(0) try: content = read_file(filepath) compressed = compress(content, dry_run=dry_run) if not dry_run: if not is_technically_intact(content, compressed): print("[ERROR] Validation failed — compression may have lost content") return write_backup(filepath, content) Path(filepath).write_text(compressed, encoding="utf-8") print(f"✓ Compressed: {filepath}") except Exception as e: print(f"✗ Error: {e}", file=sys.stderr) sys.exit(1) ``` ### Technical Analysis The executable workflow accepts an arbitrary path from `sys.argv[1]` and immediately passes it to `read_file()`. Although `scripts/detect.py` defines `is_safe_to_compress()`, the compression workflow never calls it. The feature checks are substring comparisons for only three filenames. They do not enforce: - Containment under `~/.openclaw/workspace` - A Markdown extension - The documented ...[truncated 1205 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/compress.py:62
Finding

Environment-Controlled Endpoint Can Receive Document Contents and API Credentials

Content
View full analysis
str | None: """Fallback: OpenAI-compatible endpoint via curl.""" endpoint = f"{base_url.rstrip('/')}/v1/chat/completions" payload = { "model": model, "messages": [ { "role": "system", "content": "Compress text into caveman-speak (~45% shorter). Keep technical accuracy, code blocks, URLs, file paths exact. Drop articles, filler, hedging. Output only compressed text.", }, {"role": "user", "content": content[:10000]}, # Limit context ], "max_tokens": 8000, } try: result = subprocess.run( [ "curl", "-s", "-X", "POST", endpoint, "-H", f"Authorization: Bearer {api_key}", "-H", "Content-Type: application/json", "-d", json.dumps(payload), ], capture_output=True, text=True, timeout=60, ) ``` ```python # Try MiniMax minimax_url = os.environ.get("MINIMAX_BASE_URL") or os.environ.get("OPENAI_BASE_URL") or "http://127.0.0.1:8402" minimax_key = os.environ.get("MINIMAX_API_KEY") or os.environ.get("OPENAI_API_KEY") if minimax_url and minimax_key: model = os.environ.get("COMPRESSION_MODEL", "MiniMax-M2.7") compressed = compress_via_openai_compat( minimax_url, minimax_key, model, content ) ``` ### Technical Analysis `MINIMAX_BASE_URL` and the generic `OPENAI_BASE_URL` can completely control the HTTP destination. The code does not en ...[truncated 1544 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/compress.py:70
Finding

Bearer Tokens Are Exposed in Curl Process Arguments

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/compress.py:149
Finding

Broken Validation Integration Prevents Safe Completion and Provides Insufficient Integrity Checks

Content
View full analysis
bool: """Verify technical substance preserved. Returns True if intact, False otherwise.""" checks = [ ("code blocks", has_code_blocks(original) == has_code_blocks(compressed)), ("URLs", has_urls(original) == has_urls(compressed)), ("inline code", has_inline_code(original) == has_inline_code(compressed)), ("file paths", has_file_paths(original) == has_file_paths(compressed)), ] failed = [name for name, passed in checks if not passed] if failed: print(f"⚠️ Validation failed: {', '.join(failed)}", file=sys.stderr) return False return True ``` ### Technical Analysis `compress.py` calls `is_technically_intact()` without importing it. Normal non-dry-run execution therefore raises `NameError` after the source content has already been sent to a model. The expected backup and overwrite sequence does not complete. Additionally, `validate.py` references `sys.stderr` without importing `sys`, so a failed validation check raises another `NameError`. Even if both missing imports are corrected, the validator compares only whether each broad syntax category is present. It does not compare the actual values or counts of URLs, paths, inline-code spans, or fenced code blocks. A response that retains one item in each category while altering or removing other technic ...[truncated 1273 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/cli.py:11
Finding

Package CLI Sends the File Path String Instead of Processing the Target File

Content
View full analysis
[--dry-run]", file=sys.stderr) sys.exit(1) filepath = sys.argv[1] dry_run = "--dry-run" in sys.argv # Import and run sys.path.insert(0, str(Path(__file__).parent)) from compress import compress try: compress(filepath, dry_run=dry_run) ``` ### Technical Analysis The imported `compress()` function expects document content, but this entry point supplies the path string itself. The CLI therefore asks a model to compress text such as `/home/user/file.md`; it does not read, validate, back up, or overwrite the target file. This creates inconsistent behavior between entry points and can produce a success indication from `compress()` even though the documented file operation never occurred. ### Attack Path 1. A user invokes the package CLI with a target file path. 2. The CLI passes the literal path string to the model fallback chain. 3. A provider returns a response, and `compress()` may print a success message. 4. The target file remains unchanged and no backup is created. 5. Automation or the user may incorrectly treat the operation as successfully completed. ### Impact Assessment No additional system privileges are obtained. The primary impact is integrity and operational reliability: callers receive misleading success behavior, documented safeguards are bypassed, and the intended file is not processed. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/compress.py:21
Finding

Backup Filename Generation Conflicts with Backup Detection and Documentation

Content
View full analysis
bool: """Check if path is a backup file (.original.md).""" return Path(path).name.endswith(".original.md") ``` ### Technical Analysis For an input such as `SOUL.md`, `Path(path).with_suffix(".md.original")` creates `SOUL.md.original`. However, the detector identifies only names ending in `.original.md`, and the documentation also describes `.original.md` backups. The backup writer's exclusive creation protects its own generated path from replacement, but the detector does not recognize files created by that writer. This inconsistency weakens the intended policy that backup files should never be selected for compression. ### Attack Path 1. The writer creates `SOUL.md.original`. 2. Backup detection tests only for the `.original.md` suffix. 3. The generated backup is not classified as a backup. 4. If detection is later integrated without fixing the naming mismatch, the generated backup can pass the backup-specific exclusion check, subject to the separate Markdown-extension behavior. 5. Operators and automation looking for the documented filename may also fail to locate the actual backup. ### Impact Assessment No elevated privileges are obtained. The impact is limited to backup handling, recoverability, ...[truncated 151 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill explicitly states an API fallback chain using external model providers and subprocess/curl, but the core description frames the action as local file compression with backup creation. If sensitive workspace bootstrap files are sent to external AI services without prominent disclosure and consent controls, confidential system prompts, memory, or identity files could be exfiltrated.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill explicitly states an API fallback chain using external model providers and subprocess/curl, but the core description frames the action as local file compression with backup creation. If sensitive workspace bootstrap files are sent to external AI services without prominent disclosure and consent controls, confidential system prompts, memory, or identity files could be exfiltrated.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill explicitly states an API fallback chain using external model providers and subprocess/curl, but the core description frames the action as local file compression with backup creation. If sensitive workspace bootstrap files are sent to external AI services without prominent disclosure and consent controls, confidential system prompts, memory, or identity files could be exfiltrated.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill is described as compressing local workspace/bootstrap files, but it sends file contents to Claude CLI, a configurable OpenAI-compatible endpoint, and potentially the remote DeepSeek API. These files may contain agent instructions, memory, secrets, internal URLs, or operational context, so this creates a material confidentiality and supply-chain risk through undisclosed external data transfer.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill advertises file, environment, and shell-capable behavior but does not declare any explicit tool scope or permission boundaries. In an agent environment, this weakens least-privilege controls and can allow the skill to read, write, or invoke external commands more broadly than reviewers or orchestrators expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases 'compress memory file' and 'caveman compress' are broad enough to overlap with ordinary conversation or unrelated requests. In a skill that can overwrite important workspace files and potentially transmit their contents externally, accidental invocation materially increases the chance of unintended modification or data disclosure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script consumes API credentials from environment variables and uses them to contact model services, capabilities that exceed what a user would reasonably infer from a simple file-compression utility. In the context of workspace bootstrap and memory files, this increases the blast radius because sensitive local data may be transmitted using ambient credentials without clear scoping or user awareness.

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/compress.py (reported line 44)May include surrounding context.

python
Output only compressed text, no intro/outro."""

    try:
        result = subprocess.run(
            ["claude", "--print", prompt],
            capture_output=True,
            text=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/compress.py (reported line 76)May include surrounding context.

python
}

    try:
        result = subprocess.run(
            [
                "curl",
                "-s",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

At execution time, the tool reads sensitive files such as AGENTS.md, HEARTBEAT.md, and MEMORY.md, then may send their contents to external or user-configured endpoints without an explicit warning or confirmation. In this skill context, that is especially dangerous because these files often contain persistent agent memory, internal instructions, and potentially secrets, making silent disclosure more severe than in an ordinary text-processing utility.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The module docstring states that the validator is specifically for 'caveman-compressed output', and the main logic rejects outputs that do not match that stylistic heuristic. This is a natural-language policy concern because it imposes a particular language/output style without indicating any user opt-in or justified locale/policy constraint.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
99% confidence
Finding

The manifest says the skill creates '.original.md' backups, while the code uses Path(path).with_suffix('.md.original'), producing a different naming scheme. The docstring on the backup function repeats the claimed '.original.md' behavior, so the inline intent documentation also conflicts with actual behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module docstring says this file provides 'Structural validators for caveman-compressed output,' which implies format/integrity checks. However, the main flow also enforces a content-style requirement via article-ratio analysis in is_caveman_compressed and exits with failure if that heuristic is not met, which goes beyond purely structural validation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.