Back to skill

Security audit

Custom Podcast Discovery & Generation

Security checks for vulnerabilities and agentic risk

Overview

The skill is a plausible podcast automation tool, but its auto-publishing flow and safety claims are under-scoped enough that users should review it before installing.

Install only if you are comfortable reviewing and controlling the workflow. Prefer manual mode, keep storage local until tested, use least-privilege AWS credentials, avoid sensitive topics or private research inputs, and treat generated scripts as untrusted until a human verifies sources. Do not rely on the advertised verification gate to stop auto publication without modifying or supervising the pipeline.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
sources/rss.py:39
Finding

Configurable RSS URLs Permit Server-Side Request Forgery and Local Resource Access

Content
View full analysis
str: """Fetch URL content""" try: req = urllib.request.Request(url, headers={ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" }) with urllib.request.urlopen(req, timeout=timeout) as resp: return resp.read().decode("utf-8", errors="replace") except Exception as e: print(f" WARNING: Failed to fetch {url}: {e}") return "" ``` ### Technical Analysis The URL is obtained from the user-configurable RSS source definition and passed directly to `urllib.request.urlopen()` without validating: - The URL scheme - The resolved destination address - Whether the destination is loopback, private, link-local, or reserved - Redirect destinations - The response content type - The maximum response size A timeout only limits request duration and does not prevent requests to internal resources. Depending on available URL handlers and the runtime environment, non-HTTP schemes may also permit access to local resources. An initially public URL may redirect to an internal destination because redirect targets are not revalidated. The entire response is read into memory without a byte limit, which also exposes the process to memory exhaustion from a malicious or unexpectedly large feed. ### Attack Path 1. An attacker obtains the ability to create or modify the Skill's `config.yaml`, or convinces an operator to add an attacker-controlled RSS feed. 2. The attacker configures a feed URL targeting a local, private, link-local, cloud metadata, or attacker-controlled redirect endpoint. 3. `scripts/discover.py` loads the source and invokes `RSSSource.fetch()`. 4. `_fetch_url()` sends the request from the OpenClaw host without destination restri ...[truncated 917 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
scripts/generate-script.py:116
Finding

Untrusted Web Research Is Embedded Directly Into an LLM Instruction Prompt

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pipeline.py:157
Finding

Failed Fact Verification Does Not Block Audio Generation or Upload

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • 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 (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The declared description presents a broad end-to-end podcast generation system, but the supplied code chunk is narrowly limited to discovery and ranking of topics. It does not perform research synthesis, script generation, fact-checking, citation enforcement, TTS, episode production, or storage orchestration. Additionally, the description mentions LLM use, while this chunk uses straightforward keyword matching for interest ranking and contains no LLM calls. Because the actual code behavior is a subset and materially narrower than the declared purpose, this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents a broad end-to-end automated podcast pipeline, including discovery, research, script generation, fact-checking, citation enforcement, and TTS episode generation. The supplied code chunk is much narrower: it preprocesses an already-written script by removing citation and structural markup, saves cleaned text, and writes a .pending marker for an external worker to later invoke TTS. It does not perform discovery, research, script generation, fact-checking, citation enforcement, RSS handling, S3/local storage integration, or the actual ElevenLabs API call. Because the code’s primary behavior is only TTS preparation rather than full podcast episode automation, the description materially overstates what this code chunk does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description claims a broad, automated podcast-production capability, including discovery, research, script generation, fact-checking, citation enforcement, and TTS. This code chunk has a much narrower function: it prepares a prompt from existing research input and saves a placeholder output. The script even states that actual LLM generation must be performed by an external OpenClaw worker. Therefore, the implemented behavior in this chunk materially underdelivers relative to the declared purpose. There is no evidence here of undeclared malicious behavior, but there is a clear description-to-behavior mismatch because the code does not itself perform most of the claimed core capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

There is a clear description-to-behavior mismatch for this code chunk. The declared purpose describes a full automated podcast production pipeline with research, script generation, fact-checking, citations, and TTS. In contrast, the code is only a framework/placeholder for the research stage: it generates a template JSON file and suggested search queries, with no web search, source fetching, fact extraction, verification, script generation, audio generation, or storage integrations. The script even explicitly says actual research must be done by another worker. Therefore the implemented behavior is substantially narrower than the declared functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description presents a broad podcast automation pipeline, but the supplied code only implements the storage/publication step for an already existing audio file. While S3/local storage support is consistent with part of the description, the primary declared capabilities—discovery, research, scripting, fact-checking, citations, and TTS—are absent from this code chunk. This is a material description-to-behavior mismatch because the actual code’s purpose is limited to uploading/copying episode audio, not generating podcast episodes automatically.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `SKILL.md` — This file

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guidance says to spawn a worker when a user asks to 'generate a podcast' and then run the full pipeline automatically. That broad trigger can cause external actions—web research, LLM processing, TTS generation, and possible storage/upload—without a clear confirmation step, increasing the risk of unintended execution, cost incurrence, or processing of sensitive prompts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The worker instructions encourage automatic execution of a multi-stage pipeline that uses web search, LLM access, ElevenLabs TTS, and potentially S3 storage, but do not warn about network access, third-party data sharing, or API-cost side effects. In an agent setting, missing these warnings can lead operators or users to trigger external processing of sensitive content without understanding privacy, compliance, or billing consequences.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · DEPLOYMENT.md (reported line 125)May include surrounding context.

md
This will:
- Validate skill.json
- Check required files exist
- Create tarball
- Upload to ClawHub

### 3. Test Installation

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README advertises automated web research, ElevenLabs TTS, and S3/local upload, but it does not clearly warn users that content, prompts, scripts, and possibly sensitive research data may be transmitted to third-party services or remote storage. In a skill that automates multiple external integrations, lack of explicit privacy and data-flow disclosure can cause unintended exfiltration of user-provided topics, generated content, or credentials-derived uploads.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
### Source System
Pluggable architecture for topic sources. Easy to add new sources:

1. Create class inheriting from `TopicSource`
2. Implement `fetch()` method
3. Register in `sources/__init__.py`

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Content

Scanner excerpt · SECURITY.md (reported line 31)May include surrounding context.

md
- Uses `check=True` for error detection

2. **upload.py**: AWS CLI for S3 upload
   - Commands are hardcoded (aws s3 cp)
   - File paths are sanitized/validated before use
   - Bucket names come from config.yaml (not command-line input)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documentation instructs users to run shell commands, fetch network resources, and write output files, but it does not declare any explicit tool scope or permissions boundary. This increases the chance that an agent or user invokes broader capabilities than expected, reducing least-privilege protections and making misuse or unintended data movement harder to control.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill advertises automated research, LLM script generation, TTS, and S3/local output, but it does not prominently warn users that topic content and generated materials may be transmitted to external services and written or uploaded to storage. This omission can lead to accidental disclosure of sensitive prompts, research material, or generated media to third parties or public buckets.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
71% confidence
Finding

The skill is designed around persistent local state and generated artifacts under ~/.openclaw/skills/podcast and output/, including discovery data, research files, scripts, verification reports, and pipeline state. Persistence itself is expected for this workflow, but without retention guidance or scoping, it can accumulate sensitive research content, unpublished scripts, or credentials-adjacent operational data longer than intended.

Content

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

md
- "Generate a podcast"
- "Make a podcast episode"
- "Discover podcast topics"
- "Create an audio episode about X"
- "Find topics for podcast"
- "Research and script a podcast"
- "Produce a podcast episode"

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · config.example.yaml (reported line 32)May include surrounding context.

yaml
# ── Science & Research ─────────────────────────────────
  - type: rss
    url: https://api.quantamagazine.org/feed/
    name: Quanta Magazine
    category: Science/Math

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module docstring and usage text present this file as an audio generator using ElevenLabs TTS. In reality, the code strips citations, saves a text file, and creates a .pending marker while explicitly stating that the actual TTS call must be performed elsewhere, so the described behavior does not match the implemented behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The top-level docstring actively describes direct audio generation, creating the impression that the script itself performs TTS. Later code contradicts that by printing that the actual ElevenLabs TTS call must be performed by an OpenClaw worker and by creating only a pending marker instead of an MP3.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file header, docstring, and CLI description state that the script generates a podcast script, but the implementation only writes a prompt file and a placeholder output. In an automated pipeline, downstream components or users may treat the placeholder as a completed, verified artifact, causing false trust in content that was never generated or validated.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code writes a placeholder beginning with '[VERIFIED] Podcast Script' even though no script has been generated or fact-checked. That misleading label can cause operators, other tools, or publication workflows to accept unreviewed placeholder content as authentic output, which is especially risky in a content-generation skill that emphasizes citation enforcement and verification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring says the pipeline orchestrates the full podcast generation flow through script, verification, audio, upload, and delivery. However, later prompts explicitly say the worker should populate research with actual data, generate the script with an LLM, and call ElevenLabs to generate audio, which contradicts the claim of a fully run end-to-end pipeline in this file.

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

python
print(f"{'='*60}")
    
    try:
        result = subprocess.run(cmd, check=True, capture_output=True, text=True)
        print(result.stdout)
        if result.stderr:
            print(result.stderr, file=sys.stderr)

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

After successfully invoking research.py and generate-script.py, the code prints that the worker should populate actual data or generate the actual script with an LLM. That documentation-like operator guidance conflicts with the code path, which has already executed those stages and recorded their outputs as completed pipeline artifacts.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The pipeline runs generate-audio.py as the audio generation stage and stores an .mp3 path in state, implying audio generation occurred. Immediately afterward, the prompt says only TTS text was prepared and that a worker should call ElevenLabs, which is inconsistent with the executed behavior and the manifest's automated generation framing.

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

python
]
    
    try:
        subprocess.run(cmd, check=True, capture_output=True)
        url = f"https://{bucket}.s3.{region}.amazonaws.com/{key}"
        
        # Verify accessible

Static analysis

No suspicious patterns detected.