Back to skill

Security audit

ClawCall - AI Phone Calls

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but it handles real phone calls, account tokens, and sensitive call records while allowing an HTTP API override that could expose them.

Install only if you are comfortable granting this skill access to a ClawCall account that can place calls and read call records. Keep the default HTTPS API endpoint, do not set CLAWCALL_API_BASE to a remote http:// URL, protect the token file, and review every confirmation prompt before allowing calls, schedules, prompt updates, or cancellations.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/clawcall_client.py:29
Finding

Bearer Token and Sensitive Call Data May Be Transmitted over Cleartext HTTP

Content
View full analysis
str: value = os.environ.get("CLAWCALL_API_BASE", DEFAULT_API_BASE).strip().rstrip("/") if not value.startswith(("https://", "http://")): raise ClientError("CLAWCALL_API_BASE must use http:// or https://") return value ``` ```python def request( method: str, path: str, payload: dict[str, Any] | None = None, *, authenticated: bool = True, query: dict[str, Any] | None = None, extra_headers: dict[str, str] | None = None, ) -> Any: url = api_base() + path if query: url += "?" + urllib.parse.urlencode( {key: value for key, value in query.items() if value is not None} ) headers = { "Accept": "application/json", "User-Agent": f"openclaw-clawcall-ai-phone-calls/{CLIENT_VERSION}", } if authenticated: headers["Authorization"] = f"Bearer {read_token()}" if extra_headers: headers.update(extra_headers) data = None if payload is not None: data = json.dumps(payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8") headers["Content-Type"] = "application/json; charset=utf-8" ``` ### Technical Analysis The configurable `CLAWCALL_API_BASE` accepts both HTTPS and cleartext HTTP URLs. The shared request function subsequently attaches the ClawCall bearer token to authenticated requests and serializes request payloads without imposing any additional transport-security requirement. When an HTTP endpoint is selected, the following information may be transmitted without confidentiality or integrity protection: - The bearer token used to authenticate the ClawCall agent. - Destination phone numbers and business search queries. - Call tasks, first messages, and ...[truncated 2195 chars]
Remediation
View remediation
str: value = os.environ.get("CLAWCALL_API_BASE", DEFAULT_API_BASE).strip().rstrip("/") parsed = urllib.parse.urlsplit(value) if parsed.scheme == "https" and parsed.hostname: return value if parsed.scheme == "http" and parsed.hostname in {"127.0.0.1", "::1", "localhost"}: return value raise ClientError( "CLAWCALL_API_BASE must use HTTPS; HTTP is permitted only for loopback testing" ) ``` 2. Prefer an explicit development-only opt-in flag before permitting loopback HTTP. Keep that flag disabled by default. 3. Validate the parsed URL rather than relying only on a string prefix. Reject malformed URLs, embedded credentials, fragments, and unexpected schemes. 4. Prevent authenticated requests from being redirected from HTTPS to HTTP or to an untrusted origin. Validate the destination of every redirect before forwarding the `Authorization` header. 5. Document that bearer tokens, phone numbers, prompts, transcripts, and call tasks must never be sent through a cleartext remote endpoint. 6. Rotate the bearer token immediately if it may previously have been used with an HTTP endpoint, and review account call history, scheduled calls, inbound-prompt changes, and billing activity. ]]>
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 (8)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill invokes shell scripts, uses environment variables, reads/writes token files, and performs network actions, but it does not declare an explicit tool/permission boundary. That increases the chance an agent platform grants broader capabilities than intended or auto-routes common user requests into a skill with side effects, including outbound calls and token handling.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad and map to common everyday language like 'make a call' or 'call customer service,' which can cause the skill to activate in many ambiguous contexts. In a skill that can place real phone calls, schedule actions, and incur costs, overbroad activation raises the risk of unintended execution or the model selecting this skill when a safer or more specific workflow was appropriate.

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 · SKILL.md (reported line 15)May include surrounding context.

md
envVars:
      - name: CLAW_TOKEN
        required: false
        description: ClawCall Agent bearer token; the register command can create and store one.
      - name: CLAW_TOKEN_FILE
        required: false
        description: Optional token file path; defaults to ~/.config/clawcall/token.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The 'Use this Skill when' section repeats broad activation conditions and includes contact lookup, scheduling, inbound review, and transcript retrieval without sharp boundaries. Because this skill interacts with external telephony systems and sensitive call data, ambiguous routing can expose transcripts/recordings unnecessarily or initiate workflows that the user did not clearly request.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The validation logic explicitly blocks numbers starting with +86 and instructs the user to use a different skill. This is a locale/region-specific restriction expressed in natural language, but the file does not offer user choice or explain a justified compliance reason for the constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

This markdown file documents reading authentication tokens from local files and retrieving call transcripts and recordings, which involve sensitive credentials and personal data. While it explains the mechanics, it does not include any explicit warning about handling sensitive data or protecting user privacy, which is the kind of disclosure SQP-2 expects for markdown files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The reference states that GET /agent/v1/call/{call_id} returns transcript, summary, recording, and cost, but does not warn users that these artifacts may contain sensitive information. For markdown skill documentation, SQP-2 calls for warnings when behavior could affect user privacy or data handling.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/clawcall_client.py (reported line 431)May include surrounding context.

python
try:
        args = build_parser().parse_args()
        for field in ("after", "wait_timeout", "poll_interval", "in_minutes"):
            value = getattr(args, field, None)
            if value is not None and value < 0:
                raise ClientError(f"{field.replace('_', ' ')} cannot be negative")
        if getattr(args, "wait_timeout", 1) == 0 or getattr(args, "poll_interval", 1) == 0:

Static analysis

No suspicious patterns detected.