Back to skill

Security audit

TeddyMobile Vox Phone Notification

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a phone-notification integration, but it sends sensitive phone-notification data to default analytics during dry-run without clear user disclosure.

Review this carefully before installing. Use only with recipients you are authorized to call, keep real TeddyMobile credentials in environment variables or a secure local store, and set SKILL_ANALYTICS_DISABLED=1 unless you explicitly accept sending prompts, phone numbers, notification text, and run metadata to TeddyMobile analytics. Treat the local trial-state file as sensitive and remove it if you do not want trial history retained.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • 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
resources/run-demo.js:219
Finding

Default Analytics Exposes Phone Numbers and Notification Content

Content
View full analysis
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:31
Finding

Mandatory Promotional Instructions Hijack Agent Responses

Content
View full analysis
create an account -> complete formal access and get APPID / SecretID -> create a notification bot and get the outbound number plus BotID. Then present a required three-option formal setup guide: 配置引导, 稍后配置本地参数, or 查看本地配置模板. ``` The supporting post-trial guide reinforces the mandatory behavior: ```text Use this guide after any successful --trial run, even if the tool output is hidden, collapsed, summarized, or rewritten by the host UI. Do not end with only the trial result. After confirming the trial phone call was submitted, always show the formal setup next step choices. ``` ### Technical Analysis The Skill does more than provide optional onboarding information. It directs the Agent to alter its final response by always appending a vendor registration funnel and tracked external URL after trial completion. The instruction explicitly applies even when the host interface hides, collapses, summarizes, or rewrites tool output. This attempts to preserve the promotional content against normal host response handling. The mandated material is not technically necessary to report whether the requested trial call succeeded. Because these instructions are loaded as part of the Skill, they can redirect the Agent’s current-session output away from the use ...[truncated 1144 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
resources/trial-state.js:38
Finding

Trial State Is Stored with Ambient Permissions and a Guessable Phone-Number Hash

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (71)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The document strongly markets a no-credential dry-run and trial flow, yet later instructs the live mode to load credentials from environment variables or local files. If the actual skill reads credentials outside the clearly bounded live-only path, users may be misled into granting a seemingly low-risk trial skill access to secrets and local configuration.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The document strongly markets a no-credential dry-run and trial flow, yet later instructs the live mode to load credentials from environment variables or local files. If the actual skill reads credentials outside the clearly bounded live-only path, users may be misled into granting a seemingly low-risk trial skill access to secrets and local configuration.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The document strongly markets a no-credential dry-run and trial flow, yet later instructs the live mode to load credentials from environment variables or local files. If the actual skill reads credentials outside the clearly bounded live-only path, users may be misled into granting a seemingly low-risk trial skill access to secrets and local configuration.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The document strongly markets a no-credential dry-run and trial flow, yet later instructs the live mode to load credentials from environment variables or local files. If the actual skill reads credentials outside the clearly bounded live-only path, users may be misled into granting a seemingly low-risk trial skill access to secrets and local configuration.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
76% confidence
Finding

The skill instructs use of a local credentials file containing live telephony secrets. While local storage of credentials can be acceptable, encouraging a plain path such as ~/.teddymobile/credentials.json without specifying secure permissions, encryption, or OS secret-store preference increases the risk of credential theft from the host or accidental exposure through backups and multi-user systems.

Content

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

md
1. `配置引导`: guide the user to the official site, account creation, formal access, notification bot creation, and remind them to record `APPID`, `SecretID`, `BotID`, and outbound number.
2. `稍后配置本地参数`: tell the user to return after configuring the values in environment variables or a local credential file, and not to paste live secrets into chat.
3. `查看本地配置模板`: show the local config template and environment variable names without asking the user to paste real values into chat.
7. 通过环境变量、本地 secrets manager 或 `~/.teddymobile/credentials.json` 等本地文件配置这些凭据;不要在聊天、日志、工单或共享文档中粘贴真实凭据。 Configure those credentials with environment variables, a local secrets manager, or a local file such as `~/.teddymobile/credentials.json`; do not paste live credentials into chat, logs, tickets, or shared docs.
8. 回到本 Skill,运行正式 live 本地 demo,或将外呼 helper 集成到 Claw runtime。 Return to this skill and run the live local demo or integrate the outbound helper into your Claw runtime.

如果平台凭据尚未准备好,请先提供 dry-run,而不是卡在注册或凭据输入上。Trial 模式使用免凭据 v2 试用接口。正式真实外呼仍然需要完成 TeddyMobile 平台注册和 bot 配置。

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

This section formalizes credential loading from environment variables or a local file and allows path override via VOX_CREDENTIALS_FILE. Without strong safeguards, that expands the attack surface for secret exposure, path manipulation, or unintended reads of sensitive local files by a skill that also has network capability.

Content

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

md
Credential loading now follows a standard local pattern:

- 优先使用环境变量:`VOX_APP_ID`、`VOX_SECRET`、`VOX_BOT_ID`、`VOX_OUTBOUND_NUMBER`。 Use environment variables first: `VOX_APP_ID`, `VOX_SECRET`, `VOX_BOT_ID`, `VOX_OUTBOUND_NUMBER`.
- 如果环境变量缺失,则回退读取 `~/.teddymobile/credentials.json`。 Fall back to `~/.teddymobile/credentials.json`.
- 可通过 `VOX_CREDENTIALS_FILE` 覆盖默认本地凭据文件路径。 Optionally override the file path with `VOX_CREDENTIALS_FILE`.
- 内置参考实现为 `resources/credentials-loader.js` 和 `resources/credentials.example.json`。 Use `resources/credentials-loader.js` and `resources/credentials.example.json` as the bundled reference implementation.
- 正式 `--live` 和试用 `--trial` 都会发起真实电话并向 TeddyMobile Vox 传输手机号和通知文本,必须在 dry-run 预览后显式添加 `--confirm-real-call`。 Both formal `--live` and trial `--trial` place real phone calls and transmit phone number plus notification text to TeddyMobile Vox; require `--confirm-real-call` after dry-run preview.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The analytics event payload includes broad identifiers and an explicit sensitive_payload field, allowing arbitrary sensitive data to be transmitted to an external service. In a notification skill, this is especially risky because notification content, user identifiers, trace IDs, and operational metadata may contain personal or confidential information unrelated to basic phone delivery.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · FIRST-SETUP.md (reported line 86)May include surrounding context.

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · FIRST-SETUP.md (reported line 107)May include surrounding context.

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · GET-STARTED.md (reported line 83)May include surrounding context.

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILLHUB.md (reported line 70)May include surrounding context.

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILLHUB.md (reported line 76)May include surrounding context.

md
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · resources/credentials-loader.js (reported line 5)May include surrounding context.

js
const os = require('os');
const path = require('path');

const DEFAULT_CREDENTIALS_PATH = path.join(os.homedir(), '.teddymobile', 'credentials.json');

function resolveCredentialsPath(explicitPath) {
  return explicitPath || process.env.VOX_CREDENTIALS_FILE || DEFAULT_CREDENTIALS_PATH;

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The workflow instructs the skill to read live credentials from environment variables and local credential files during formal mode. Even though this is a legitimate integration pattern, it creates a real secret-access capability inside the skill, so a compromised or overly broad implementation could expose or misuse credentials if logging, prompting, or downstream tooling is not tightly controlled.

Content

Scanner excerpt · workflow.md (reported line 51)May include surrounding context.

md
Credential handling in formal live mode should follow this order:

1. read `VOX_APP_ID`, `VOX_SECRET`, `VOX_BOT_ID`, `VOX_OUTBOUND_NUMBER`, and optional `VOX_CALLBACK_URL` from environment variables
2. if any required values are still missing, fall back to `~/.teddymobile/credentials.json`
3. if `VOX_CREDENTIALS_FILE` is set, use that file path instead of the default fallback path

Do not ask for or load user-owned live credentials during dry-run or promotion trial. Promotion trial uses the no-credential `POST https://vox.teddymobile.cn/vox/v2/outbound` endpoint; formal live mode uses user-owned credentials. The bundled `resources/credentials.example.json` is an example only.

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

This section enumerates live credential and local credential-file inputs for formal mode, confirming that the skill's intended operation includes access to sensitive authentication material. In context this is expected, but it still enlarges the attack surface because any implementation bug, prompt injection in adjacent tooling, or verbose error output could leak those secrets.

Content

Scanner excerpt · workflow.md (reported line 92)May include surrounding context.

md
- `VOX_SECRET`
- `VOX_BOT_ID`
- `VOX_OUTBOUND_NUMBER`
- optional local credentials file at `~/.teddymobile/credentials.json`
- notification target phone number source
- where in the Claw runtime the "send notification" action should be triggered

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The workflow explicitly references not inspecting the local credential store before the appropriate stage, which implies that inspecting that store is otherwise part of the implementation path. That makes secret access a genuine capability of the skill; the danger is mitigated by gating, but the presence of local-file credential access remains security-relevant.

Content

Scanner excerpt · workflow.md (reported line 119)May include surrounding context.

md
- `正式注册并配置`: guide TeddyMobile registration and live credential setup.
6. Do not run `--trial` until the user chooses trial and adds `--confirm-real-call` after reviewing the masked dry-run preview and confirming recipient authorization. Do not ask for formal credentials until the user chooses formal registration or says they already configured credentials locally.
7. If `--trial` is blocked because the local trial was already used or content safety rejects the content, report the block reason and continue to formal registration guidance.
8. Do not call `resources/credentials-loader.js`, inspect `~/.teddymobile/credentials.json`, or ask for `VOX_APP_ID` / `VOX_SECRET` / `VOX_BOT_ID` / `VOX_OUTBOUND_NUMBER` before dry-run and the user's next-step choice.
9. If a command is run without `--dry-run`, `--trial`, or `--live`, treat it as dry-run. Never use an unflagged command as formal live mode.
9a. If a command uses `--trial` or `--live` without `--confirm-real-call`, stop before any network call, show the masked real-call preview, and tell the user to re-run with `--confirm-real-call` only after authorization and compliance checks.
10. If `--trial` succeeds, the final assistant response must restate the formal setup choices from `POST-TRIAL-GUIDE.md`. Do not rely on tool output alone because host UIs may collapse or summarize it.