Back to skill

Security audit

Proof Engine

Security checks for vulnerabilities and agentic risk

Overview

This skill is a broad business proof automation tool, but it needs review because it can send sensitive business results to Telegram and write outside its declared skill area.

Install only if you are comfortable giving this skill access to financial, testimonial, revenue, brand, content, and agent-memory-adjacent workspace data. Treat Telegram notifications as external sharing: verify exactly what will be sent, use a limited bot token and chat, and disable or avoid notification commands if the proof data is sensitive. Review or restrict cross-skill writes and avoid using --output with arbitrary paths.

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

T09 · Insecure Skill Coding Practices

Warning
Location
proof_manager.py:458
Finding
Arbitrary File Overwrite Through User-Controlled VSL Output Path## Vulnerability Details **File Location**: `proof_manager.py`, lines 458-460; related argument declaration at line 938 **Vulnerability Type**: Arbitrary file overwrite / unrestricted path handling **Risk Level**: Medium ### Vulnerable Code ```python # If VSL output requested if platform == "vsl" and args.output: with open(args.output, "w") as f: f.write(story) print(f" ✅ VSL script: {args.output}") ``` The output path is supplied through this unrestricted command-line argument: ```python p_story.add_argument("--output", help="Output file (for VSL)") ``` ### Technical Analysis The `--output` argument controls the complete path passed to `open()` in write mode. The application does not canonicalize the path, restrict it to an approved output directory, reject symbolic links, or verify that the destination is a regular file. Opening a destination with mode `"w"` creates the file if it does not exist and truncates it if it does. Consequently, a caller capable of invoking the CLI can overwrite any file writable by the process. Relative traversal sequences such as `../../...`, absolute paths, and links pointing outside the intended VSL output directory are all accepted. This behavior exceeds the documented purpose of generating VSL scripts and can also exceed the write locations declared by the Skill metadata. ### Attack Path 1. Ensure the proof vault contains at least one item whose `impact_score` meets the story-generation threshold. 2. Identify a file writable by the Skill process. 3. Invoke the story command with the VSL platform and the target file as the output path, for example: ```bash python3 proof_manager.py story \ --platform vsl \ --filter-impact 5 \ --output /workspace/path/to/writable-target ``` 4. `cmd_story()` generates a story and calls `open(args.output, "w")`. 5. The target is truncated and replaced with generated Markdown content. ...[truncated 850 chars]
Remediation
## Remediation Suggestions 1. Restrict VSL output to an explicitly approved directory, such as `/workspace/voice/scripts/`. 2. Resolve both the approved directory and requested destination with `pathlib.Path.resolve()`, then verify that the destination remains beneath the approved directory: ```python from pathlib import Path VSL_DIR = Path("/workspace/voice/scripts").resolve() requested = Path(args.output) destination = requested.resolve() if VSL_DIR not in destination.parents: raise ValueError("Output path must be inside the approved VSL directory") ``` 3. Reject existing symbolic links and verify that existing destinations are regular files. 4. Prefer accepting only a filename from the caller and construct the complete path internally. 5. Use atomic writes through a securely created temporary file in the destination directory, followed by `os.replace()`. 6. Consider refusing to replace an existing file unless the caller supplies a separate, explicit overwrite option. 7. Align the runtime filesystem permissions with the write paths declared in `SKILL.md`.

T05 · Unauthorized Access and Privilege Escalation

Note
Location
proof_manager.py:250
Finding
Unnecessary Recursive Enumeration of the Agent Memory Directory## Vulnerability Details **File Location**: `proof_manager.py`, lines 250-267; related permission declaration in `SKILL.md`, lines 17-28 **Vulnerability Type**: Excessive filesystem access / violation of least privilege **Risk Level**: Low ### Vulnerable Code ```python # Read from AUDIT.md files audit_files = [] # Full workspace scan — all declared skill directories SCAN_DIRS = [ "/workspace/proof", "/workspace/brand", "/workspace/CASHFLOW", "/workspace/voice", "/workspace/memory", "/workspace/revenue", "/workspace/content", "/workspace/.learnings", ] for scan_dir in SCAN_DIRS: if os.path.exists(scan_dir): for root, _, files in os.walk(scan_dir): for f in files: if f == "AUDIT.md": audit_files.append(os.path.join(root, f)) ``` The Skill metadata also requests read access to the memory directory: ```yaml required_paths: read: - /workspace/proof/ - /workspace/brand/ - /workspace/CASHFLOW/ - /workspace/voice/ - /workspace/memory/ - /workspace/revenue/ - /workspace/content/ - /workspace/.learnings/ ``` ### Technical Analysis The agent-capture operation recursively walks `/workspace/memory` solely to locate files named `AUDIT.md` and count them. Proof management does not establish a functional need for unrestricted recursive visibility into the Agent's memory area. Although the current implementation does not open, copy, or transmit the contents of discovered memory files, recursive enumeration reveals directory names, file names, and the locations of matching audit records. Requesting access to this sensitive area also creates an unnecessarily broad capability that could amplify the consequences of future defects or malicious modifications. This violates the principle of least privilege: the Skill should receive only the narrow filesystem access requir ...[truncated 1218 chars]
Remediation
## Remediation Suggestions 1. Remove `/workspace/memory/` from `metadata.openclaw.required_paths.read` unless a documented, essential use case requires it. 2. Remove `/workspace/memory` from `SCAN_DIRS`. 3. Replace broad recursive walks with an allowlist of known audit file paths. 4. If discovery is required, restrict traversal depth and scan only directories directly associated with agent audit output. 5. Run the Skill in a filesystem sandbox that exposes only approved source and destination directories. 6. Document the purpose of every requested path and periodically review permissions for least-privilege compliance.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (32)

Tainted flow: 'req' from os.environ.get (line 98, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
data=payload.encode(),
            headers={"Content-Type": "application/json"}
        )
        with urllib.request.urlopen(req, timeout=10):
            pass
        print("  ✅ Telegram sent")
    except Exception as e:
Confidence
93% confidence
Finding
The skill can send proof summaries and business metrics to Telegram using credentials from environment variables, creating an external data exfiltration path. In this skill's context, the messages may include revenue, performance, and operational status, so automatic outbound transmission increases sensitivity even though the destination is a legitimate API.

Credential Access

High
Category
Privilege Escalation
Content
## Credentials required

- `TELEGRAM_BOT_TOKEN` — already in agent .env
- `TELEGRAM_CHAT_ID` — already in agent .env

> No external API keys required — all engines run on local files.
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Credentials required

- `TELEGRAM_BOT_TOKEN` — already in agent .env
- `TELEGRAM_CHAT_ID` — already in agent .env

> No external API keys required — all engines run on local files.
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill declares Telegram bot use and outbound requests, but the user-facing description does not warn that proof summaries or alerts may be transmitted externally via bot credentials. Because the skill handles financial and testimonial data, undisclosed external messaging creates a serious confidentiality and consent risk.

Missing User Warnings

High
Confidence
95% confidence
Finding
The skill gathers broad categories of financial, client, audience, and media data, but the description does not prominently warn users about the breadth and sensitivity of that collection. In this context, the omission is risky because the datasets include P&L, client testimonials, and operational metrics that can expose confidential business information.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill description omits a strong warning that captured proof is automatically deployed into other skills and channels. Automatic downstream propagation magnifies the harm from any mistaken, confidential, or non-consensual data capture because the information can quickly spread into brand, outreach, and sales assets.

Scope Creep

High
Confidence
99% confidence
Finding
The skill documents writes to /workspace/brand/proof/ and /workspace/voice/scripts/ but those destinations are absent from declared write permissions. Because these paths belong to other skills/domains, this creates an undeclared cross-skill modification channel that could inject content into brand or voice workflows without explicit authorization.

Credential Access

High
Category
Privilege Escalation
Content
→ Telegram for notifications (already in agent .env)

AGENT ALREADY HAS:
  TELEGRAM_BOT_TOKEN  → already in agent .env
  TELEGRAM_CHAT_ID    → already in agent .env
```
Confidence
92% confidence
Finding
The skill explicitly depends on TELEGRAM_BOT_TOKEN from the agent environment, indicating credential use tied to network transmission. In combination with broad automation and external notifications, this expands the attack surface for secret misuse or unauthorized data exfiltration through the bot channel.

Credential Access

High
Category
Privilege Escalation
Content
AGENT ALREADY HAS:
  TELEGRAM_BOT_TOKEN  → already in agent .env
  TELEGRAM_CHAT_ID    → already in agent .env
```

### Bootstrap Checklist
Confidence
90% confidence
Finding
The skill also relies on TELEGRAM_CHAT_ID from environment configuration, reinforcing that it is set up to send messages to an external recipient automatically. While a chat ID is less sensitive than a token, pairing it with bot credentials and autonomous alerts facilitates silent outbound communication of potentially sensitive business data.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The README makes a misleading trust claim that no external API keys are required and that all engines run on local files, while simultaneously requiring Telegram bot credentials from the agent environment. This can cause operators to underestimate external data flows and approve a skill that may transmit sensitive business proof, financial, or testimonial data off-host through Telegram.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Listing Telegram credentials while claiming local-only operation without any warning about outbound messaging creates a transparency and data-exfiltration risk. In the context of a skill that aggregates cross-domain business proof and financial dashboard data, undisclosed external transmission materially increases the chance of sensitive data being sent to a third-party messaging platform.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill declares substantial capabilities—file reads/writes, environment variable use, and outbound network access—but does not define an explicit tool permission boundary such as allowed-tools or permissions. That makes the effective privilege surface ambiguous and increases the chance the runtime grants broader access than reviewers or users expect.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The skill is described as transforming results across all business domains and deploying proof broadly, which implies very wide operational scope. Overbroad scope increases the chance of activation in contexts containing sensitive financial, client, or reputational data without sufficient guardrails or human approval.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The autonomous capture and deployment routines are framed as recurring and automatic, but the trigger boundaries and approval requirements are not clearly constrained. Ambiguous automation around collection and cross-channel deployment can lead to unreviewed propagation of sensitive or inaccurate proof data.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The setup text claims all engines operate on local files only, yet the manifest also requires Telegram credentials and declares outbound network requests. This is dangerous because it misleads reviewers and users about external data transmission, reducing informed consent for sensitive financial and testimonial data handling.

Scope Creep

Medium
Confidence
97% confidence
Finding
The manifest's write permissions do not include /workspace/.learnings/LEARNINGS.md even though the skill documentation says it writes there weekly. This mismatch can cause policy bypass attempts, unexpected permission failures, or later widening of permissions without proper review.

Tainted flow: 'DASHBOARD_F' from os.environ.get (line 18, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
def save_dashboard(data: dict):
    data["last_updated"] = datetime.now().isoformat()
    with open(DASHBOARD_F, "w") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'index_f' from os.environ.get (line 150, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
def save_vault_index(items: list):
    index_f = f"{VAULT_DIR}/index.json"
    with open(index_f, "w") as f:
        json.dump({"items": items, "last_updated": date.today().isoformat()}, f, indent=2)
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'AUDIT_F' from os.environ.get (line 22, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
def log_audit(message: str):
    ensure_dirs()
    ts = datetime.now().strftime("%Y-%m-%d %H:%M")
    with open(AUDIT_F, "a") as f:
        f.write(f"\n[{ts}] {message}")
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

External Transmission

Medium
Category
Data Exfiltration
Content
import urllib.request
        payload = json.dumps({"chat_id": chat_id, "text": message, "parse_mode": "Markdown"})
        req = urllib.request.Request(
            f"https://api.telegram.org/bot{token}/sendMessage",
            data=payload.encode(),
            headers={"Content-Type": "application/json"}
        )
Confidence
92% confidence
Finding
The code performs external transmission to Telegram, which can leak internal proof data, revenue figures, and operational summaries outside the local environment. Because this skill aggregates business-sensitive information, even intended notifications should be treated as data exfiltration risk unless users explicitly authorize and understand the scope.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The description claims the skill 'scans high-potential business opportunities for 2026,' which implies discovery or analysis from external or dynamic sources. In practice, the opportunities feature just initializes hardcoded entries and supports local view/add/report operations on ranked_2026.json, with no scanning behavior implemented.

Tainted flow: 'opp_f' from os.environ.get (line 693, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
opp_f = f"{OPP_DIR}/ranked_2026.json"
    if not os.path.exists(opp_f):
        opps = _default_opportunities()
        with open(opp_f, "w") as f:
            json.dump({"opportunities": opps, "last_updated": date.today().isoformat()}, f, indent=2)
        print(f"  ✅ opportunities/ranked_2026.json seeded ({len(opps)} opportunities)")
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'opp_f' from os.environ.get (line 693, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
opp_f = f"{OPP_DIR}/ranked_2026.json"
    if not os.path.exists(opp_f):
        opps = _default_opportunities()
        with open(opp_f, "w") as f:
            json.dump({"opportunities": opps, "last_updated": date.today().isoformat()}, f, indent=2)
        print(f"  ✅ opportunities/ranked_2026.json seeded ({len(opps)} opportunities)")
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'opp_f' from os.environ.get (line 693, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
opp_f = f"{OPP_DIR}/ranked_2026.json"
    if not os.path.exists(opp_f):
        opps = _default_opportunities()
        with open(opp_f, "w") as f:
            json.dump({"opportunities": opps, "last_updated": date.today().isoformat()}, f, indent=2)
        print(f"  ✅ opportunities/ranked_2026.json seeded ({len(opps)} opportunities)")
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The capture logic performs broad workspace scanning across unrelated directories such as /workspace/voice, /workspace/memory, /workspace/revenue, and hidden learnings data to infer activity. In a proof/content engine, this exceeds minimally necessary access and can expose sensitive operational metadata or private records without clear scope limitation, making the skill context more dangerous because its stated purpose does not require expansive cross-skill inspection.

Static analysis

No suspicious patterns detected.