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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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
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.

Content

Scanner excerpt · proof_manager.py (reported line 103)May include surrounding context.

python
data=payload.encode(),
            headers={"Content-Type": "application/json"}
        )
        with urllib.request.urlopen(req, timeout=10):
            pass
        print("  ✅ Telegram sent")
    except Exception as e:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 18)May include surrounding context.

md
## 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.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 19)May include surrounding context.

md
## 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.

Missing User Warnings

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Scope Creep

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
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.

Content

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

→ Telegram for notifications (already in agent .env)

AGENT ALREADY HAS: TELEGRAM_BOT_TOKEN → already in agent .env TELEGRAM_CHAT_ID → already in agent .env

text

Credential Access

High
Category
Privilege Escalation
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.

Content

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

AGENT ALREADY HAS: TELEGRAM_BOT_TOKEN → already in agent .env TELEGRAM_CHAT_ID → already in agent .env

text

### Bootstrap Checklist

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Scope Creep

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · proof_manager.py (reported line 57)May include surrounding context.

python
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)

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · proof_manager.py (reported line 71)May include surrounding context.

python
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)

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · proof_manager.py (reported line 78)May include surrounding context.

python
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}")

External Transmission

Medium
Category
Data Exfiltration
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.

Content

Scanner excerpt · proof_manager.py (reported line 99)May include surrounding context.

python
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"}
        )

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · proof_manager.py (reported line 159)May include surrounding context.

python
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)")

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · proof_manager.py (reported line 718)May include surrounding context.

python
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)")

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · proof_manager.py (reported line 736)May include surrounding context.

python
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)")

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.