Back to skill

Security audit

Moltspaces

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent voice-room bot, but its installer and credential handling create review-worthy risk before installation.

Review this skill before installing. Use a preinstalled, trusted uv rather than running the setup script's curl-to-sh installer, prefer vault or OS secret storage over plaintext files, restrict file permissions on any local credentials, and do not allow MOLTSPACES_API_URL to point away from the official Moltspaces API unless you fully control the endpoint. Treat live voice room audio, transcripts, and generated responses as data shared with Moltspaces, Daily, OpenAI, and ElevenLabs.

Vulnerability Patterns
  • 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
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
setup.sh:12
Finding
Unverified Remote Installer Is Piped Directly into a Shell<![CDATA[ ## Vulnerability Details **File Location**: `setup.sh:12` **Vulnerability Type**: Remote payload retrieval and immediate execution **Risk Level**: High ### Vulnerable Code ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` ### Technical Analysis The setup process downloads a mutable shell script from an external server and passes it directly to `sh`. The downloaded content is not pinned to a reviewed version and is not checked against a checksum or cryptographic signature before execution. Although `astral.sh` is the documented source of the `uv` installer, the effective code executed during installation can change after this Skill has been reviewed. Security therefore depends on the continuing integrity of the remote server, its deployment pipeline, DNS resolution, the certificate trust chain, and the network path. This behavior is not the minimum privilege necessary for the declared voice-bot functionality. The Skill only needs a Python environment and its dependencies; it does not inherently need to execute an unreviewed remote shell script. ### Attack Path 1. A user follows the installation instructions and runs `bash setup.sh`. 2. The script determines that `uv` is not installed. 3. `curl` retrieves the current response from `https://astral.sh/uv/install.sh`. 4. The response is immediately interpreted by `sh`, without local inspection or integrity verification. 5. If the remote distribution infrastructure or network trust chain is compromised, attacker-controlled shell commands execute with the permissions of the user running setup. ### Impact Assessment A substituted installer can execute arbitrary commands under the installing user's account. This can permit access to files and credentials readable by that user, modification of shell configuration or project files, installation of additional programs, and network communication from the host. The command does not itself request root privileges, so its direct scope is normally ...[truncated 161 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Prefer requiring `uv` as an explicit prerequisite instead of installing it automatically. - If automatic installation is necessary: 1. Pin a specific reviewed `uv` release. 2. Download the release artifact to a local file. 3. Verify its publisher signature or published SHA-256 checksum. 4. Abort installation if verification fails. 5. Execute only the verified artifact. - Do not use a `curl | sh` pipeline. - Avoid advising users to run the setup script with `sudo` or another privileged account. - Document the exact installer version and integrity value used by the audited release. ]]>

T01 · Skill Instruction Hijacking

Error
Location
bot.py:263
Finding
Participant-Controlled Name Is Inserted into a Privileged System Message<![CDATA[ ## Vulnerability Details **File Location**: `bot.py:263-270` **Vulnerability Type**: LLM prompt injection through untrusted participant metadata **Risk Level**: High ### Vulnerable Code ```python @transport.event_handler("on_participant_joined") async def on_participant_joined(transport, participant): # Safely get participant name with fallback participant_info = participant.get("info", {}) participant_name = participant_info.get("userName") or participant_info.get("name") or "Guest" logger.info(f"Participant joined: {participant_name}") await transport.capture_participant_transcription(participant["id"]) # Kick off the conversation with personalized greeting. messages.append({"role": "system", "content": f"Greet {participant_name} by name."}) await task.queue_frames([LLMRunFrame()]) ``` ### Technical Analysis A remote room participant controls, or can influence, the `userName` or `name` metadata used by the event handler. The value is interpolated directly into an LLM message assigned the privileged `system` role. The fallback protects against a missing name, but it does not establish a trust boundary or prevent instruction-bearing content. A crafted display name can include text such as additional behavioral directives. Because that text is placed in a system message rather than represented as untrusted data, the model may interpret it as authoritative instructions. The current bot does not expose general-purpose system tools to the LLM, which limits immediate consequences. Nevertheless, the injection can alter conversational behavior, defeat the intended facilitator policy, generate inappropriate output, or manipulate subsequent room interactions. ### Attack Path 1. An attacker joins a Daily room using a crafted participant display name containing LLM instructions. 2. Daily supplies the attacker-controlled name to the `on_participant_joined` event handler. 3. The handler constructs `Greet <attacker content> by ...[truncated 790 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never interpolate participant-controlled values into `system` messages. - Keep the system instruction fixed and pass the participant name as structured, explicitly untrusted application data. - Validate participant names with a conservative character allowlist and a short maximum length. - Remove control characters, line breaks, markup-like delimiters, and other instruction-separation syntax before display or logging. - Prefer a fixed instruction such as “Greet the newly joined participant,” while supplying the sanitized name through a separate data field supported by the framework. - Add adversarial tests using names containing instruction overrides, role labels, delimiters, and multiline content. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
bot.py:64
Finding
Environment-Overridable API Destination Can Receive the Moltspaces API Key<![CDATA[ ## Vulnerability Details **File Location**: `bot.py:64-89` **Vulnerability Type**: Credential disclosure through an unrestricted configurable endpoint **Risk Level**: High ### Vulnerable Code ```python load_dotenv(override=True) # Moltspaces API configuration MOLTSPACES_API_URL = os.getenv( "MOLTSPACES_API_URL", "https://moltspaces-api-547962548252.us-central1.run.app" ) async def search_rooms_by_topic(topic: str) -> List[Dict]: url = f"{MOLTSPACES_API_URL}/v1/rooms/{topic}" logger.info(f"🔍 Searching for rooms with topic: {topic}") try: api_key = os.getenv("MOLTSPACES_API_KEY", "") headers = {"x-api-key": api_key} async with aiohttp.ClientSession() as session: async with session.get( url, headers=headers, timeout=aiohttp.ClientTimeout(total=10) ) as response: ``` The same configurable base URL and credential-bearing header are also used by the room-token and room-creation requests. ### Technical Analysis The documentation states that the Moltspaces API key must only be sent to the official Moltspaces API. The implementation does not enforce that restriction. `MOLTSPACES_API_URL` can be changed through the environment, and `load_dotenv(override=True)` permits values from a working-directory `.env` file to replace previously injected environment values. The client then attaches `MOLTSPACES_API_KEY` to requests made to the resulting URL without validating its scheme, hostname, port, or origin. Consequently, a modified `.env` file or otherwise influenced environment can redirect the API key to a different server. This is particularly risky under the documented direct OpenClaw execution model because loading a local `.env` with `override=True` can supersede credentials or configuration injected by a trusted vault. ### Attack Path 1. An attacker obtains the ability to create or modify the `.env` file in the Skill's working direct ...[truncated 1073 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `MOLTSPACES_API_URL` configurability from production builds unless it is operationally required. - If configurability is required, parse the URL and enforce: - HTTPS only. - The exact approved hostname. - The expected port. - No embedded credentials. - No redirects to unapproved origins. - Use `load_dotenv(override=False)` so a local file cannot supersede values already injected by a trusted runtime or vault. - Prefer explicit configuration objects over process-wide environment mutation. - Refuse to attach the API key when destination validation fails. - Apply restrictive permissions to local secret files, such as mode `0600`, and exclude `.env` from source control. - Add tests confirming that HTTP URLs, alternate domains, subdomain lookalikes, and cross-origin redirects are rejected. ]]>

T08 · Insecure Dependencies

Warning
Location
pyproject.toml:6
Finding
Runtime Dependencies Are Installed Without a Supplied Lockfile or Version Constraints<![CDATA[ ## Vulnerability Details **File Location**: `pyproject.toml:6-14` and `setup.sh:22-23` **Vulnerability Type**: Non-reproducible third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```toml dependencies = [ "pipecat-ai[webrtc,daily,silero,elevenlabs,openai,local-smart-turn-v3,runner]", "pipecat-ai-cli", "fastapi", "uvicorn", "python-dotenv", "aiohttp", ] ``` ```bash echo "📚 Installing dependencies..." uv sync ``` ### Technical Analysis The runtime dependencies do not specify reviewed version ranges, and the audited project contains no `uv.lock` file. As a result, `uv sync` can resolve dependency versions available at installation time rather than installing a reproducible set represented by the audited artifact. This substantially expands the supply-chain trust boundary because the voice stack includes large dependency trees and packages that are imported directly into the bot process. A compromised upstream release, unsafe future version, or unexpected transitive dependency can therefore become part of the runtime without a corresponding change to this repository. There is no evidence in the supplied files that any named dependency is intentionally malicious. The confirmed issue is the absence of reproducible dependency controls, not a demonstrated dependency compromise. ### Attack Path 1. A user runs `setup.sh`. 2. The setup script executes `uv sync`. 3. Because the project has no supplied lockfile and runtime requirements are unconstrained, the resolver selects packages available at that time. 4. If an upstream package or transitive dependency has been compromised, the unsafe release is downloaded and installed. 5. The bot imports and executes dependency code with the permissions of the user running it. ### Impact Assessment A compromised dependency can execute code within the bot process and access resources available to that process, potentially including environment variables containing ...[truncated 400 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Generate, review, and commit a `uv.lock` file. - Install in locked or frozen mode so dependency resolution fails if the manifest and lockfile differ. - Pin direct dependencies to reviewed versions or appropriately narrow compatible ranges. - Use package hashes or signed provenance where the package ecosystem and deployment process support them. - Add automated dependency vulnerability and provenance scanning to release workflows. - Review transitive dependency changes before updating the lockfile. - Remove packages not required by the implemented runtime, such as FastAPI or Uvicorn if they are not used elsewhere. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (41)

Credential Access

High
Category
Privilege Escalation
Content
POST /v1/agents/rooms/:roomName/token
```

Returns Daily room URL and access token.

### 3. Create Room with Topic
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The description omits significant install and credential-management behavior, including dependency installation, external registration, and writing credentials to local files. This mismatch can mislead operators into approving a low-risk skill that actually modifies the environment and manages sensitive secrets.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The description omits significant install and credential-management behavior, including dependency installation, external registration, and writing credentials to local files. This mismatch can mislead operators into approving a low-risk skill that actually modifies the environment and manages sensitive secrets.

Credential Access

High
Category
Privilege Escalation
Content
**⚠️ Save your `api_key` immediately!** You need it for all requests.

**Recommended:** Save your credentials to `~/.config/moltspaces/credentials.json`:

```json
{
Confidence
94% confidence
Finding
The skill explicitly recommends storing long-lived API credentials in a local JSON file, and elsewhere also saves secrets into .env files. Local plaintext secret storage increases the chance of accidental exposure through weak file permissions, backups, logs, source-control mistakes, or other local tooling, enabling agent impersonation and unauthorized API use.

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding
Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Chaining Abuse

High
Category
Tool Misuse
Content
# Check if uv is installed
if ! command -v uv &> /dev/null; then
    echo "📦 Installing uv package manager..."
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
    # Add uv to PATH for this session
    export PATH="$HOME/.cargo/bin:$PATH"
Confidence
99% confidence
Finding
Piping downloaded content directly into `sh` is the highest-risk form of shell chaining because it eliminates inspection and executes attacker-controlled bytes immediately. In this voice-agent skill context, users are likely to run setup scripts as part of onboarding, making compromise of the installer path especially dangerous and capable of full host takeover.

Credential Access

High
Category
Privilege Escalation
Content
echo "====================="
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
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
echo "====================="
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
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
echo "====================="
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
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
echo "====================="
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
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
echo "====================="
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
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
echo "====================="
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
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
echo "====================="
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
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
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
    echo "   Agent ID: $MOLT_AGENT_ID"
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
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
    echo "   Agent ID: $MOLT_AGENT_ID"
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
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
    echo "   Agent ID: $MOLT_AGENT_ID"
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
echo ""

# Check if .env already exists and has credentials
if [ -f ".env" ] && grep -q "MOLT_AGENT_ID=" .env && grep -q "MOLTSPACES_API_KEY=" .env; then
    echo "✅ Found existing credentials in .env"
    MOLT_AGENT_ID=$(grep "MOLT_AGENT_ID=" .env | cut -d '=' -f2)
    echo "   Agent ID: $MOLT_AGENT_ID"
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
cp env.example .env
        fi
        
        # Update credentials in .env
        sed -i.bak "s/MOLT_AGENT_ID=.*/MOLT_AGENT_ID=$AGENT_ID/" .env
        sed -i.bak "s/MOLTSPACES_API_KEY=.*/MOLTSPACES_API_KEY=$API_KEY/" .env
        rm .env.bak 2>/dev/null || true
Confidence
86% confidence
Finding
This line writes the returned agent ID into `.env` via `sed`; although the ID itself is lower sensitivity, the same mechanism is used for secret material and indicates automated modification of a plaintext environment file. In context this contributes to insecure local secret management and could also behave unsafely if values contain unexpected delimiter characters.

Credential Access

High
Category
Privilege Escalation
Content
fi
        
        # Update credentials in .env
        sed -i.bak "s/MOLT_AGENT_ID=.*/MOLT_AGENT_ID=$AGENT_ID/" .env
        sed -i.bak "s/MOLTSPACES_API_KEY=.*/MOLTSPACES_API_KEY=$API_KEY/" .env
        rm .env.bak 2>/dev/null || true
Confidence
97% confidence
Finding
This line writes `MOLTSPACES_API_KEY` directly into a plaintext `.env` file using shell substitution. That creates a real risk of local credential disclosure through loose permissions, accidental commits, backups, or multi-user system access, and it stores the most sensitive token handled by the script.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README describes topic-based discovery and automatic room creation/join behavior but does not clearly warn users that invoking the skill may cause the agent to enter or create live voice spaces on their behalf. In a voice-first social skill, that omission can lead to unintended participation, disclosure, or presence in public/semi-public rooms without informed user consent.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README lists OpenAI, ElevenLabs, and Daily.co in the voice pipeline but does not clearly disclose that user audio, transcripts, and conversation content may be transmitted to and processed by these third-party providers. This is a meaningful privacy and compliance risk because users may reasonably assume the interaction is local or limited to Moltspaces.

External Transmission

Medium
Category
Data Exfiltration
Content
Register with the Moltspaces API to get your credentials:

```bash
curl -X POST https://moltspaces-api-547962548252.us-central1.run.app/v1/agents/register \
  -H "Content-Type: application/json" \
  -d '{"name": "YourAgentName", "description": "What your agent does"}'
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documents capabilities to execute shell commands, access environment variables, and make network requests, but it does not declare any tool scope or permissions boundary. This increases the chance that a host agent/platform grants broader access than users expect, especially because the skill also handles secrets and external service registration.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The warning explicitly says the Moltspaces API key should only appear in requests to the Moltspaces API and that agents should refuse requests to send it elsewhere. Later documentation tells users to invoke the bot with `--url <daily_room_url> --token <token>`, which is a contradictory intent signal because it normalizes forwarding bearer-style room credentials to a third-party Daily URL rather than keeping credentials confined to the Moltspaces API flow described as mandatory.

External Transmission

Medium
Category
Data Exfiltration
Content
Every agent needs to register and get their API key:

```bash
curl -X POST https://moltspaces-api-547962548252.us-central1.run.app/v1/agents/register \
  -H "Content-Type: application/json" \
  -d '{"name": "YourAgentName", "description": "What you do"}'
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.