Back to skill

Security audit

Podcast Intel

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it sends podcast audio and transcripts to AI services and stores untrusted, model-derived podcast content in persistent OpenClaw memory with weak containment.

Review this skill before installing. Use it only with podcast feeds and episode URLs you trust, prefer dry_run until you understand the diary behavior, avoid setting OPENAI_BASE_URL unless you control and trust that endpoint, and assume full audio, transcript excerpts, and derived summaries may be sent to external AI providers and stored locally.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T02 · Agent Memory Poisoning

Error
Location
scripts/segment.py:148
Finding

Untrusted Podcast Content Can Poison Persistent Agent Memory

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/transcribe.py:42
Finding

Audio URL Validation Can Be Bypassed Through DNS Resolution and Redirects

Content
View full analysis
Tuple[bool, str]: """Validate that URL is safe for ffmpeg fetches.""" parsed = urlparse(url) if parsed.scheme not in {"http", "https"}: return False, "Only http/https audio URLs are allowed" host = parsed.hostname if not host: return False, "Audio URL missing hostname" lowered = host.lower() if lowered in {"localhost", "localhost.localdomain"}: return False, "Localhost audio URLs are blocked" try: addr = ipaddress.ip_address(host) if ( addr.is_private or addr.is_loopback or addr.is_link_local or addr.is_multicast or addr.is_reserved or addr.is_unspecified ): return False, "Private/local IP audio URLs are blocked" except ValueError: # Host is a domain name; we allow it. pass return True, "" def download_audio(url: str, temp_dir: Path) -> Optional[Path]: """Download audio from URL to temp WAV file.""" is_valid, reason = validate_audio_url(url) if not is_valid: print(f"Unsafe audio URL rejected: {reason}", file=sys.stderr) return None audio_file = temp_dir / "audio.wav" cmd = [ "ffmpeg", "-nostdin", "-hide_banner", "-loglevel", "error", "-i", url, "-vn", "-ac", "1", "-ar", "16000", "-acodec", "pcm_s16le", "-f", "wav", str(audio_file), "-y", ] try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=900) ``` ### Technical Analysis The validation blocks dangerous addresses only when the hostname itself is a ...[truncated 2059 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/utils/config.py:95
Finding

Unvalidated OpenAI Base URL Can Expose API Credentials and Podcast Content

Content
View full analysis
Dict[str, str]: """Get OpenAI API configuration from environment.""" config = { 'api_key': os.getenv('OPENAI_API_KEY', ''), 'base_url': os.getenv('OPENAI_BASE_URL', 'https://api.openai.com/v1'), 'model': os.getenv('OPENAI_MODEL', 'gpt-4o-mini'), } if not config['api_key']: raise ValueError("OPENAI_API_KEY environment variable not set") return config ``` ```python # scripts/transcribe.py:124-138 def transcribe_with_openai(audio_file: Path, model: str = "whisper-1") -> Optional[Dict[str, Any]]: """Transcribe using OpenAI Whisper API.""" try: from openai import OpenAI from utils import get_openai_config config = get_openai_config() client = OpenAI(api_key=config["api_key"], base_url=config["base_url"]) with open(audio_file, "rb") as handle: transcript = client.audio.transcriptions.create( model=model, file=handle, response_format="verbose_json", ) ``` ```python # scripts/segment.py:138-175 try: from openai import OpenAI except Exception as exc: print(f"Error loading OpenAI client: {exc}", file=sys.stderr) return None try: config = get_openai_config() client = OpenAI(api_key=config["api_key"], base_url=config["base_url"]) except Exception as exc: print(f"Error creating OpenAI client: {exc}", file=sys.stderr) return None max_words = 10000 text_preview = " ".join(transcript_text.split()[:max_words]) prompt = f"""Analyze this podcast transcript and identify distinct topical segments. For each major topic discussed, ...[truncated 2407 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Installer Resolves and Executes Unpinned Third-Party Dependencies

Content
View full analysis
=6.0 openai>=1.0 pydantic>=2.0 pyyaml>=6.0 numpy>=1.24 httpx>=0.27 ``` ### Technical Analysis All direct dependencies use open-ended minimum-version constraints. There is no upper bound, exact lock file, hash verification, or transitive dependency inventory. Each installation may therefore resolve a different set of packages than the set considered during this audit. Python package installation can execute package build backends and installation-related code. If a future release or transitive dependency is compromised, the installer can execute unaudited code with the privileges of the user running `install.sh`. The use of standard package names and the default package index reduces dependency-confusion risk, but it does not mitigate compromised releases, future malicious versions, or unexpected compatibility changes. ### Attack Path 1. A direct or transitive dependency account, release process, or distribution channel is compromised. 2. A newer package version is published that still satisfies the `>=` constraint. 3. A user runs `install.sh`. 4. `pip` resolves the newer, unaudited package or transitive dependency. 5. Package build or runtime code executes on the user's system. 6. Malicious code gains the permissions available to the installing user. ### Impact Assessment The immediate execution scope is the account running `pip`. A compromised dependency may read or alter files accessible to that account, access environment variables such as `OPENAI_API_KEY`, modify the Python environment, or establish additional network co ...[truncated 314 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (34)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

To clear cache:

bash
rm -rf ~/.openclaw/cache/podcast-intel/

Cost Estimates

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

To clear cache:

bash
rm -rf ~/.openclaw/cache/podcast-intel/

Cost Estimates

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

sudo apt-get install ffmpeg

Fedora

sudo dnf install ffmpeg

text

### 4. Set up environment

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README states that only RSS feeds, Whisper API, and an LLM API are contacted, but it does not clearly and explicitly warn users that full podcast audio, transcripts, and derived analyses may be transmitted to third-party AI providers for processing. This can cause users to underestimate privacy, confidentiality, and data-handling implications, especially if feeds contain copyrighted, sensitive, or private material.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The activation text includes a broad catch-all phrase covering essentially any request involving podcast content analysis, which can cause the skill to trigger outside narrowly intended scenarios. Overbroad auto-activation increases the chance of inappropriate tool use, unnecessary external data processing, and unintended access to configured feeds, transcripts, or the local consumption diary when a user request only loosely relates to podcasts.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
fi
    elif command -v apt-get &> /dev/null; then
        # Ubuntu/Debian
        sudo apt-get update
        sudo apt-get install -y ffmpeg
    elif command -v dnf &> /dev/null; then
        # Fedora

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · install.sh (reported line 35)May include surrounding context.

sh
fi
    elif command -v apt-get &> /dev/null; then
        # Ubuntu/Debian
        sudo apt-get update
        sudo apt-get install -y ffmpeg
    elif command -v dnf &> /dev/null; then
        # Fedora

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · install.sh (reported line 36)May include surrounding context.

sh
fi
    elif command -v apt-get &> /dev/null; then
        # Ubuntu/Debian
        sudo apt-get update
        sudo apt-get install -y ffmpeg
    elif command -v dnf &> /dev/null; then
        # Fedora

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · install.sh (reported line 39)May include surrounding context.

sh
fi
    elif command -v apt-get &> /dev/null; then
        # Ubuntu/Debian
        sudo apt-get update
        sudo apt-get install -y ffmpeg
    elif command -v dnf &> /dev/null; then
        # Fedora

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · references/env-check.sh (reported line 28)May include surrounding context.

sh
# OpenAI Base URL
if [ -z "$OPENAI_BASE_URL" ]; then
    echo "→ OPENAI_BASE_URL: NOT SET (using default: https://api.openai.com/v1)"
else
    echo "✓ OPENAI_BASE_URL: $OPENAI_BASE_URL"
fi

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · scripts/utils/config.py (reported line 99)May include surrounding context.

python
# OpenAI Base URL
if [ -z "$OPENAI_BASE_URL" ]; then
    echo "→ OPENAI_BASE_URL: NOT SET (using default: https://api.openai.com/v1)"
else
    echo "✓ OPENAI_BASE_URL: $OPENAI_BASE_URL"
fi

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

python
cmd = ["python3", str(script_path)] + args

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
    except subprocess.TimeoutExpired:
        print(f"Error running {script_name}: timeout after {timeout}s", file=sys.stderr)
        return None

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code appends analysis results to a diary, which is a file/data write operation with persistent effects. While a dry-run option exists and stderr logging announces the update when it happens, there is no upfront warning in the file's documented behavior that running the skill will modify diary data by default.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code sends transcript content to an external OpenAI-compatible service in LLM mode by embedding transcript text directly into the prompt, but it provides no explicit consent, warning, or data-classification check at the transmission point. Because transcripts may contain sensitive or proprietary content, this creates a real confidentiality and privacy risk, especially when the default method is 'llm'.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script caches transcript-derived summaries and entities to disk automatically, which can persist sensitive information beyond the immediate run and expose it to other local users, backups, or later compromise. This is a genuine data-handling weakness because the cache write occurs silently and is not clearly disclosed to the user at the write point.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
74% confidence
Finding

The code invokes ffmpeg on a user-supplied remote URL, which can trigger server-side requests and media parsing of attacker-controlled content. Although shell injection is mitigated by passing an argument list and there is some URL validation, the validation only checks the literal hostname/IP and does not prevent DNS rebinding/resolution to internal addresses or risks inherent in ffmpeg processing untrusted media.

Content

Scanner excerpt · scripts/transcribe.py (reported line 106)May include surrounding context.

python
]

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=900)
    except Exception as exc:
        print(f"Error downloading audio: {exc}", file=sys.stderr)
        return None

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code uploads the audio file to a remote API via client.audio.transcriptions.create, which transmits user-provided audio content off-system. While the module docstring mentions use of the Whisper API, there is no explicit user-facing warning at the point of operation about sending audio data to an external service.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a lower-bound constraint only, which allows future installs to resolve to different versions over time. This weakens build reproducibility and makes it harder to verify whether a deployed version includes known security fixes or newly introduced vulnerable releases.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
feedparser>=6.0
openai>=1.0
pydantic>=2.0
pyyaml>=6.0

Unverifiable Dependency: feedparser has 10 known advisory(ies) (CVE-2011-1157 (feedparser Cross-site Scripting vulnerability); CVE-2009-5065 (feedparser Cross-site Scripting vulnerability); CVE-2011-1158 (feedparser Cross-site Scripting vulnerability) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding

feedparser has known advisories, and because the manifest does not pin a version, it is impossible to determine from this file whether a safe or affected release will be installed. This creates uncertainty in security review and allows vulnerable versions to be selected depending on resolution time and environment.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The openai package is unpinned and may resolve to different versions in different environments or at different times. That can introduce supply-chain risk, unexpected breaking changes, or accidental installation of a version with a security issue that has not been reviewed.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
feedparser>=6.0
openai>=1.0
pydantic>=2.0
pyyaml>=6.0
numpy>=1.24

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

Using pydantic>=2.0 permits any newer major or minor release, reducing reproducibility and making security posture difficult to assess. If a vulnerable or incompatible release is pulled in, downstream validation logic or service reliability could be affected.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
feedparser>=6.0
openai>=1.0
pydantic>=2.0
pyyaml>=6.0
numpy>=1.24
httpx>=0.27

Unverifiable Dependency: pydantic has 4 known advisory(ies) (CVE-2021-29510 (Use of "infinity" as an input to datetime and date fields causes infinite loop i); CVE-2024-3772 (Pydantic regular expression denial of service); CVE-2021-29510 (Pydantic is a data validation and settings management using Python type hinting.) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding

pydantic has known advisories, including denial-of-service related issues, and the unpinned constraint prevents verification that an installed version is unaffected. If the application validates untrusted input, a vulnerable release could amplify risk through parser or regex-related abuse.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

PyYAML has a history of unsafe deserialization issues, and leaving it unpinned makes it unclear which release will be installed. In contexts where YAML may be parsed from untrusted sources, version drift can materially affect exposure to known parser and deserialization flaws.

Content

Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

text
feedparser>=6.0
openai>=1.0
pydantic>=2.0
pyyaml>=6.0
numpy>=1.24
httpx>=0.27

Unverifiable Dependency: pyyaml has 8 known advisory(ies) (CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
97% confidence
Finding

PyYAML has multiple historical security advisories, and without version pinning the deployment may resolve to an affected release. Given PyYAML's relevance to deserialization and parsing, the uncertainty is more dangerous than for purely local utility packages if untrusted YAML is ever processed.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

An unpinned numpy dependency allows unreviewed releases to be installed, undermining reproducibility and making vulnerability status uncertain. While often lower risk than network-facing libraries, it still creates avoidable supply-chain and maintenance risk.

Content

Scanner excerpt · requirements.txt (reported line 5)May include surrounding context.

text
openai>=1.0
pydantic>=2.0
pyyaml>=6.0
numpy>=1.24
httpx>=0.27

Static analysis

Detected: suspicious.destructive_delete_command

Documentation contains a destructive delete command without an explicit confirmation gate.

Warn
Code
suspicious.destructive_delete_command
Location
README.md:204