Back to skill

Security audit

Pitch

Security checks for vulnerabilities and agentic risk

Overview

This pitch-coaching skill stays local, but it can insert made-up business metrics into generated pitches and stores pitch or meeting records locally without strong safeguards.

Review this skill before installing. Do not use its 60-second or 120-second elevator pitches as factual output until you replace every traction, revenue, market, team, and fundraising claim with verified information. Be aware that it stores pitch foundations, objections, and meeting metadata locally under ~/.openclaw/workspace/memory/pitch, so avoid sensitive details on shared machines unless you can protect or delete those files.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_elevator_pitch.py:55
Finding

Generated pitches contain fabricated business and fundraising claims

Content
View full analysis

Vulnerability Details

File Location: scripts/create_elevator_pitch.py, lines 55–82
Vulnerability Type: Unvalidated hardcoded business claims
Risk Level: High

Vulnerable Code

python
elif args.length == 60:
    print(f"\n[HOOK - 10 sec]")
    print(f"{problem}")
    print(f"\n[SOLUTION - 20 sec]")
    print(f"{company} {solution}")
    print(f"\n[TRACTION - 20 sec]")
    print("We've signed 12 customers and are growing 20% monthly")
    print(f"\n[ASK - 10 sec]")
    if args.audience == 'investor':
        print("We're raising $500K to hit $30K MRR. Are you interested?")
    elif args.audience == 'customer':
        print("Can I show you a 5-minute demo next week?")

else:  # 120 seconds
    print(f"\n[HOOK - 15 sec]")
    print(f"{problem}")
    print(f"\n[SOLUTION - 30 sec]")
    print(f"{company} {solution}")
    print(f"\n[MARKET - 20 sec]")
    print("This is a $2B market growing 30% annually")
    print(f"\n[TRACTION - 30 sec]")
    print("12 customers, $15K MRR, growing 20% monthly, 58 NPS")
    print(f"\n[TEAM - 15 sec]")
    print("Ex-Stripe and Google engineers")
    print(f"\n[ASK - 10 sec]")
    if args.audience == 'investor':
        print("We're raising $500K. Can I send you our deck?")

Technical Analysis

The script inserts fixed customer counts, growth rates, market size, revenue, Net Promoter Score, employee backgrounds, and fundraising targets into generated pitches. These statements are presented as company facts even though the selected foundation record does not supply or validate them.

Because the generated output resembles a finished pitch rather than a template, a user can reasonably mistake these values for data derived from their stored foundation. The script does not mark them as placeholders, request confirmation, or omit claims for which verified data is unavailable.

Attack Path

  1. A user creates a foundation containing o ...[truncated 1049 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove all hardcoded factual claims from generated pitches.
  • Read traction, market, team, and fundraising values from the selected foundation record.
  • Validate that each value exists and has been explicitly confirmed by the user before presenting it as fact.
  • Omit sections for which no verified information is available, or display conspicuous placeholders such as [ADD VERIFIED MRR].
  • Add an explicit review step listing every factual claim and requiring user confirmation before producing a final version.
  • Distinguish template examples from generated output through clear labels.
  • Add automated tests confirming that one user's pitch cannot acquire example metrics or claims absent from that user's foundation.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/build_foundation.py:24
Finding

Confidential pitch and meeting records are written without restrictive file permissions

Content
View full analysis

Vulnerability Details

File Locations: scripts/build_foundation.py, lines 24–26; scripts/draft_followup.py, lines 23–25; scripts/prep_objections.py, lines 24–26
Vulnerability Type: Insecure local storage permissions
Risk Level: Medium

Vulnerable Code

scripts/build_foundation.py:

python
def save_foundations(data):
    ensure_dir()
    with open(FOUNDATION_FILE, 'w') as f:
        json.dump(data, f, indent=2)

scripts/draft_followup.py:

python
def save_meetings(data):
    ensure_dir()
    with open(MEETINGS_FILE, 'w') as f:
        json.dump(data, f, indent=2)

scripts/prep_objections.py:

python
def save_objections(data):
    ensure_dir()
    with open(OBJECTIONS_FILE, 'w') as f:
        json.dump(data, f, indent=2)

Technical Analysis

The scripts store business plans, pitch strategy, objection preparation, and investor or customer meeting details under ~/.openclaw/workspace/memory/pitch. Files are created through ordinary open(..., 'w') calls, while the parent directory is created without an explicit restrictive mode.

Consequently, access permissions depend on the process umask and existing directory permissions. Under a common 022 umask, newly created files may receive mode 0644, making them readable by other local accounts that can traverse the parent directories. Existing files with permissive modes are not corrected on subsequent writes.

The implementation conflicts with the skill documentation's claim that confidential pitch materials remain private and locally controlled. Local storage alone does not provide confidentiality when file permissions are not restricted.

Attack Path

  1. The skill runs on a shared or multi-user host with a permissive umask.
  2. A user creates a foundation, drafts a follow-up, or prepares objections.
  3. The corresponding JSON file is created with permissions derived from the permissive umask.

...[truncated 835 chars]

Remediation
View remediation

Remediation Suggestions

  • Create the pitch storage directory with mode 0700 and explicitly correct the mode if the directory already exists.
  • Create data files with mode 0600, using os.open with restrictive flags or applying os.chmod immediately and safely.
  • Use atomic writes: create a temporary file in the same protected directory, set mode 0600, flush and synchronize it, and then replace the destination with os.replace.
  • Audit and tighten permissions on existing foundations.json, meetings.json, and objections.json files.
  • Verify that all parent directories prevent traversal by unauthorized local users.
  • Handle symbolic links and unexpected file types defensively before replacing stored records.
  • Document the local threat model and warn users when secure permissions cannot be enforced.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • 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 (3)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs use of local storage and scripts that read and write files, but it does not declare an explicit tool scope such as permissions or allowed-tools. That mismatch can cause the runtime to expose broader file capabilities than reviewers or platform policy expect, increasing the risk of unintended access to workspace data or unauthorized modification of local files.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script injects specific traction, market size, team pedigree, and fundraising claims that are not derived from the user's stored foundation data, but presents them as part of the generated pitch. In a pitch-coaching skill, this is dangerous because users may reasonably assume generated content reflects their inputs and could unknowingly deliver false or misleading business claims to investors or customers.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script presents itself as a follow-up email drafting tool, but it also silently writes meeting metadata to persistent local storage under ~/.openclaw/workspace/memory/pitch without explicit user notice or consent. Because the stored fields can include company names, meeting type, discussion topics, and next steps, this creates an unintended data retention risk for potentially sensitive business relationship and pipeline information.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.