Back to skill

Security audit

Google Voice

Security checks for vulnerabilities and agentic risk

Overview

This Google Voice skill is mostly coherent, but it grants broad authenticated account actions without strong built-in guardrails.

Review before installing. Use this only with a Google Voice account you are comfortable automating, keep it away from shared workspaces, prefer browser/CDP mode over cookie exports, avoid gv_raw_call unless you understand the exact endpoint, and do not run audio mode as a privileged user. Treat exported SMS records, HAR samples, generated speech, and call recordings as sensitive private data.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/google-voice-mcp.js:112
Finding

Unrestricted Raw API Tool Can Perform Unauthorized Google Voice Operations

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/google-voice-mcp.js:111
Finding

External SMS and Call Actions Lack an Enforced Approval Boundary

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/google-voice-call-audio-engine.js:9
Finding

Google Session Cookies Are Loaded into an Unsandboxed Chromium Process

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/google-voice-call-audio-engine.js:8
Finding

Sensitive Messages and Call Audio Use Predictable or Insufficiently Protected Files

Content
View full analysis
{ if(!window.myRecorder) return null; window.myRecorder.stop(); await new Promise(r=>setTimeout(r,2000)); const blob=new Blob(window.chunks,{type:'audio/webm'}); return new Promise(resolve=>{ const reader=new FileReader(); reader.onloadend=()=>resolve(reader.result.split(',')[1]); reader.readAsDataURL(blob); }); }); if (audioBase64) fs.writeFileSync(recordingPath, Buffer.from(audioBase64, 'base64')); ``` ```bash TIMESTAMP=$(date +%s); GREET_WAV="/tmp/gv_greet_$TIMESTAMP.wav"; SILENCE_WAV="/tmp/gv_silence_$TIMESTAMP.wav"; FINAL_WAV="/tmp/gv_call_final_$TIMESTAMP.wav" edge-tts --text "$TEXT" --write-media "/tmp/gv_tts_$TIMESTAMP.mp3" >/dev/null ffmpeg -i "/tmp/gv_tts_$TIMESTAMP.mp3" -ar 16000 -ac 1 "$GREET_WAV" -y >/dev/null 2>&1 ffmpeg -f lavfi -i anullsrc=r=16000:cl=mono -t 600 "$SILENCE_WAV" -y >/dev/null 2>&1 ffmpeg -i "$GREET_WAV" -i "$SILENCE_WAV" -filter_complex "[0:a][1:a]concat=n=2:v=0:a=1" "$FINAL_WAV" -y >/dev/null 2>&1 AUDIO_PATH="$FINAL_WAV" ... RECORDING_WEB="/tmp/gv_recorded_incoming.webm"; RECORDING_MP3="/tmp/gv_call_$(date +%Y%m%d_%H%M%S).mp3"; rm -f "$RECORDING_WEB" ``` ```js async function main(){const args=parseArgs(process.argv.slice(2)); const raw=await gvFetch('/voice/v1/voiceclient/api2thread/get',[args.itemId,args.limit,args.context,[null,1,1]]); const data=summarizeThread(raw,args.itemId,args.raw); const out=args.format==='md'?toMarkdown(data):JSON.stringify(data,null,2); if(args.out) fs.writeFileSync(args.out,out+'\n'); else process.stdout.write(out+'\n');} ``` ### Technical Analysis The fixed path `/tmp/ ...[truncated 1701 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze_voice_har.py:13
Finding

HAR Analyzer Uses Incomplete Heuristic Redaction Before Printing Request Bodies

Content
View full analysis
',text) text=re.sub(r'"![^"]{20,}"', '""', text) text=re.sub(r'"[^"]{40,}"', '""', text) text=re.sub(r'"[^"]{20,}"', lambda m: '""' if any(c.isspace() for c in m.group(0)) else m.group(0), text) text=re.sub(r'"[^"\\]*(token|id|text|message|recipient|phone)[^"\\]*"\s*:\s*"[^"\\]+"','"":""',text, flags=re.I) samples[key]=text[:500] for (method,path),n in counts.most_common(): print(f'{n:3} {method} {path}') if samples.get((method,path)): print(' sample:', samples[(method,path)].replace('\n',' ')[:500]) ``` ### Technical Analysis The analyzer prints the first 500 characters of captured request bodies after applying regular-expression substitutions. This is a denylist-based redaction approach and cannot reliably recognize every representation of sensitive data. Short messages, compact identifiers, escaped JSON strings, international phone formats that do not match the expression, protobuf array fields without descriptive keys, and unfamiliar anti-abuse tokens may survive redaction. The HAR format itself can contain authentication and personal communication data, making body printing unsafe by default. ### Attack Path 1. The user runs the analyzer against a Google Voice HAR file. 2. A request body contains a sensitive value not matched by the regular expressions. 3. The value remains in `text` and is included in the 500-character sample. 4. The sample is printed to stdout. 5. Terminal capture, CI logs, agent prompts, or copied reports retain the exposed value. ### Impact Assessment The disclosure can expose message content, phone numbers, thread identifiers, recipients, anti-abuse tokens, or other HA ...[truncated 161 chars]
Remediation
View remediation

other

Warning
Location
scripts/google-voice-call-audio.sh:31
Finding

Call Text Is Transmitted to an External TTS Provider Without Explicit Disclosure

Content
View full analysis
/dev/null || { echo "edge-tts is required for --text" >&2; exit 2; } command -v ffmpeg >/dev/null || { echo "ffmpeg is required for --text" >&2; exit 2; } TIMESTAMP=$(date +%s); GREET_WAV="/tmp/gv_greet_$TIMESTAMP.wav"; SILENCE_WAV="/tmp/gv_silence_$TIMESTAMP.wav"; FINAL_WAV="/tmp/gv_call_final_$TIMESTAMP.wav" edge-tts --text "$TEXT" --write-media "/tmp/gv_tts_$TIMESTAMP.mp3" >/dev/null ``` ### Technical Analysis `edge-tts` is a network-backed text-to-speech client. Passing `--text "$TEXT"` causes the approved call content to be sent to the TTS provider to generate audio. The Skill identifies `edge-tts` as a dependency but does not clearly state that call text leaves the local machine and Google Voice ecosystem or require separate consent for that transfer. This behavior is functionally relevant to TTS generation, but it is not the minimum-privilege approach because an offline TTS engine could perform the same local function without disclosing content to another service. ### Attack Path 1. The user selects call audio generation using `--text`. 2. The wrapper passes the exact call text to `edge-tts`. 3. `edge-tts` sends the text to its external speech service. 4. The provider processes the content and returns generated media. 5. Potentially sensitive call content is exposed to an additional data processor. ### Impact Assessment The transferred content may include personal data, business communications, phone scripts, financial information, or other sensitive material. The issue does not provide system-level privileges, but it expands the network disclosure scope beyond Google Voice and the local machine. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill description does not accurately bound what the implementation can do, while the documented toolset includes a raw endpoint invocation capability (gv_raw_call) and OAuth token refresh behavior that materially expand its power. In a telecom/messaging context, this mismatch is dangerous because operators or agents may rely on the description and overlook that the skill can make arbitrary Google Voice requests or handle additional credentials beyond the declared use cases.

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 53)May include surrounding context.

md
Prefer the CDP `google-voice-start-call.js` mode for simple manual/live calls because it reuses the logged-in visible browser and avoids cookie exports. Use aud

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Prefer the CDP `google-voice-start-call.js` mode for simple manual/live calls because it reuses the logged-in visible browser and avoids cookie exports. Use aud

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/google-voice-call-audio.sh (reported line 41)May include surrounding context.

sh
AUDIO_PATH="$FINAL_WAV"
fi
if [[ "$DRY_RUN" == "1" ]]; then printf '{"dryRun":true,"number":"%s","authuser":"%s","audioPath":"%s","duration":%s}\n' "$NUMBER" "$AUTHUSER" "$AUDIO_PATH" "$DURATION"; exit 0; fi
RECORDING_WEB="/tmp/gv_recorded_incoming.webm"; RECORDING_MP3="/tmp/gv_call_$(date +%Y%m%d_%H%M%S).mp3"; rm -f "$RECORDING_WEB"
node "$SKILL_DIR/scripts/google-voice-call-audio-engine.js" "$NUMBER" "$AUDIO_PATH" "$DURATION" "$AUTHUSER"
if [[ -f "$RECORDING_WEB" ]]; then ffmpeg -i "$RECORDING_WEB" -q:a 0 -map a "$RECORDING_MP3" -y >/dev/null 2>&1 || true; echo "FINISHED_FILE:$RECORDING_MP3"; fi

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill exposes sensitive capabilities involving environment variables, file access, and networked interaction with Google Voice, but it does not declare any explicit tool scope or permissions boundaries. In a high-risk skill that handles HAR-derived credentials, cookies, SMS content, and outbound communications, missing scope declarations increases the chance of unintended tool access or unsafe execution by an agent runtime.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This Python script reads a Google Voice HAR file, extracts request payloads, and prints sample request data after only partial redaction. Although some fields are masked, the code has no confirmation prompt, warning comment, or user-facing disclosure that it processes potentially sensitive communications and metadata from the HAR file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This script silently captures call audio via MediaRecorder and writes it to a predictable file path on disk without any runtime notice, consent enforcement, or jurisdictional compliance checks. In the context of a Google Voice automation skill that can place outbound calls and inject audio, this creates a meaningful risk of covert call recording, unauthorized retention of sensitive communications, and legal/privacy violations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest describes using HAR captures, browser sessions, and bundled MCP integration for Google Voice web automation. In gws mode, the code shells out to a separate gws binary, reads exported OAuth refresh credentials, and exchanges them for access tokens, introducing a distinct credential-handling capability not called out in the stated skill purpose.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/google-voice-mcp.js (reported line 48)May include surrounding context.

js
refresh_token: creds.refresh_token,
    grant_type: 'refresh_token',
  });
  const res = await fetch('https://oauth2.googleapis.com/token', { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: params });
  const j = await res.json();
  if (!res.ok || !j.access_token) throw new Error('gws token refresh failed: ' + JSON.stringify({ error: j.error, error_description: j.error_description }));
  GWS_TOKEN_CACHE = { token: j.access_token, exp: now + (j.expires_in || 3000) };

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The exposed tool set consists of gv_list_threads, gv_get_thread, gv_send_sms, and gv_raw_call. There are no tools or code paths for starting calls, injecting audio/TTS, recording call audio, exporting records, or configuring OpenClaw integration, so the actual behavior of this file is materially narrower than the manifest description claims.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The gv_list_threads and gv_get_thread tools fetch Google Voice thread metadata and message contents using browser cookies, authorization headers, or refreshed OAuth access tokens. While their descriptions say authentication is required, the code provides no explicit runtime disclosure or warning that private communications will be accessed and returned to the caller.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The gv_raw_call tool allows arbitrary authenticated calls to Google Voice endpoints using the user's browser session, cookies, or OAuth-derived bearer token. This bypasses the narrower user-facing purpose of the skill and creates a confused-deputy risk where an agent or prompt can invoke undocumented or sensitive operations against the account.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

A generic raw-call tool with authenticated Google Voice access materially expands the attack surface beyond the described SMS/thread features. In an agent setting, this makes prompt injection or tool misuse more dangerous because arbitrary backend actions can be performed under the user's authority without meaningful guardrails.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script can export Google Voice SMS thread contents to an arbitrary file path via --out with no interactive warning, consent checkpoint, or data-classification notice. Because this skill is explicitly designed to access and export sensitive communications, silent persistence to disk materially increases the risk of unauthorized retention, later exfiltration, or accidental disclosure through logs, backups, or shared workspaces.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The comment suggests a narrowly non-credential-handling design, yet getGwsAccessToken actively retrieves credential material from gws auth export and uses it to mint bearer tokens. Even if credentials are not persisted to disk here, the documentation downplays the code's actual interaction with sensitive auth secrets.

Content

No source excerpt is available for this finding.