Back to skill

Security audit

Tour Booking

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent tour-booking purpose, but live mode can place real calls while sending API credentials and client/listing data to an environment-selected URL and saving unredacted call records.

Review before installing. Use only with trusted booking inputs, keep dry-run and human payload review in the workflow, restrict or remove ELEVENLABS_OUTBOUND_URL, use a narrowly scoped ElevenLabs key, and treat output JSON files as sensitive records that may need redaction or deletion.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/place_outbound_call.py:57
Finding

Unrestricted endpoint override can disclose API credentials and personal data

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/prepare_call_payload.py:17
Finding

Untrusted booking fields are interpolated into the voice agent's system prompt

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/parse_call_result.py:13
Finding

Untrusted response text can falsely classify a failed call as confirmed

Content
View full analysis
str: if call.get("mode") == "dry_run": return "pending" signal_fields = { "status": call.get("status"), "api_response": call.get("api_response"), "error_body": call.get("error_body"), "error": call.get("error"), } text = json.dumps(signal_fields).lower() if "confirmed" in text or "booked" in text: return "confirmed" if "callback" in text or "call back" in text: return "pending_callback" if "no answer" in text or "voicemail" in text: return "no_answer" if call.get("status") == "error": return "failed" return "pending" ``` ### Technical Analysis The parser serializes the complete status, API response, error body, and exception text, then classifies the call using substring searches. It does not verify a documented response schema or require a successful call state before reporting a booking as confirmed. The word `confirmed` in phrases such as `not confirmed`, `confirmation failed`, or an arbitrary server error is sufficient to return `confirmed`. The confirmation check also occurs before the explicit error check. Consequently, a result with `"status": "error"` can still be classified as confirmed if its error body contains `confirmed` or `booked`. Because `api_response` and `error_body` originate from a remote service, they must be treated as untrusted input rather than authoritative confirmation records. ### Attack Path 1. The remote API returns an error or response containing the substring `confirmed` or `booked`. 2. Alternatively, an attacker who can influence the endpoint through `ELEVENLABS_OUTBOUND_URL` returns a crafted JSON response containing one of those words. 3. `place_ou ...[truncated 900 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The code substantially supports part of the declared purpose: it can perform dry-run output generation and make live outbound ElevenLabs API requests using structured payloads. However, the description claims broader behavior than is present. In particular, this script does not parse call outcomes into booking statuses, does not process conversation results beyond returning the API response/error, and does not implement logic for requesting/confirming showing slots other than passing through a system prompt and phone number. It also appears to handle a single payload per invocation rather than orchestrating calls for one or more listings. Therefore the description overstates the implemented functionality, creating a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill invokes local scripts that imply file reads/writes, possible environment access, and network-based outbound calling, but it declares no explicit tool restrictions or permissions. In an agentic environment, missing scope boundaries can let the skill run with broader capabilities than intended, increasing the chance of unauthorized file access, secret exposure, or unintended network actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script explicitly instructs the caller to share buyer/client identity if required and to confirm callback contact details, but it provides no minimization, consent, or disclosure guidance for handling personal information. In a live outbound-calling workflow, this can lead to unnecessary disclosure of PII to third parties, inconsistent privacy practices, and potential policy or legal noncompliance.

Content

No source excerpt is available for this finding.

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/elevenlabs-env.md (reported line 9)May include surrounding context.

md
from pathlib import Path


DEFAULT_OUTBOUND_URL = "https://api.elevenlabs.io/v1/convai/phone-calls"


def post_json(url: str, headers: dict[str, str], payload: dict) -> dict:

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

python
from pathlib import Path


DEFAULT_OUTBOUND_URL = "https://api.elevenlabs.io/v1/convai/phone-calls"


def post_json(url: str, headers: dict[str, str], payload: dict) -> dict:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

In live mode, this script initiates a real outbound phone call based on CLI input and environment variables, then persists the full request and API response to disk. In an agent-skill context, that creates a meaningful risk of unintended real-world actions and storage of sensitive call metadata or prompt contents without stronger confirmation, redaction, or safety interlocks.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.