Back to skill

Security audit

keyue-call

Security checks for vulnerabilities and agentic risk

Overview

This skill is coherent for Baidu AIOB outbound calling, but needs Review because it can trigger real phone calls and logs personal call details without a confirmation or redaction layer.

Install only if you intend to let the agent create Baidu AIOB outbound calls. Use dedicated low-privilege AIOB credentials, avoid passing secrets on the command line, restrict access to config and logs, and confirm recipient number/message before any call or scheduled call is created.

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

Warning
Location
scripts/create_realtime_call.py:170
Finding
Credentials can be exposed through command-line arguments and plaintext configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create_realtime_call.py:170-171`, `scripts/create_realtime_call.py:204-205`; related workflow in `SKILL.md:10-11` **Vulnerability Type**: Credential exposure through process arguments and plaintext configuration **Risk Level**: Medium ### Complete Code Snippet ```python p.add_argument("--access-key", help="Override accessKey") p.add_argument("--secret-key", help="Override secretKey") ``` ```python access_key = get_value(config, args.access_key, "accessKey", required=True) secret_key = get_value(config, args.secret_key, "secretKey", required=True) ``` The documented workflow also directs users to place both credentials in `config.json`: ```text 1. 在 `config.json` 中配置默认参数(可参考 `config.json.example`),包括:`accessKey`、`secretKey`、`robotId`、`mobile`、`callerNum`。 ``` The distributed `config.json` contains masked placeholders rather than real credentials, so no committed live secret was identified. ### Technical Analysis The script accepts the AIOB access key and secret key directly as command-line arguments. Command-line secrets may be exposed through: - Shell history. - Process inspection tools available to other local users or monitoring agents. - Job definitions, scheduler metadata, diagnostic records, and command audit logs. - Agent or automation transcripts that preserve the invoked command. The documented alternative is to store the credentials directly in an ordinary JSON configuration file. The implementation does not enforce restrictive permissions, use a secrets manager, or separate sensitive credentials from non-sensitive call configuration. Credential transmission to `https://aiob-open.baidu.com/api/v2/getToken` is required for the declared AIOB functionality and uses HTTPS. The risk is therefore not the intended network request itself, but insecure local secret handling before that request. ### Attack Path 1. A user invokes the script with `--access-key` and `--secret-key`, or saves ...[truncated 1130 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--access-key` and `--secret-key` command-line options so secrets cannot be passed through process arguments. 2. Retrieve credentials from a dedicated operating-system secret store, cloud secrets manager, or protected runtime credential provider. 3. If environment variables must be supported, document their exposure limitations and inject them only at execution time rather than placing them in command text. 4. Move credentials out of `config.json`; retain only non-sensitive settings such as `robotId`, call defaults, and timeout values there. 5. If a credential file remains supported: - Require restrictive ownership and permissions, such as mode `0600` on Unix-like systems. - Reject files that are group- or world-readable. - Add the credential-bearing file to `.gitignore`. - Provide a placeholder-only example file under a distinct name. 6. Rotate credentials immediately if they have appeared in shell history, logs, agent transcripts, or source control. 7. Use a narrowly scoped AIOB credential where the platform supports account or API-level permission restrictions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create_realtime_call.py:208
Finding
Outbound-call personal data is unconditionally printed to standard output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create_realtime_call.py:208-220` **Vulnerability Type**: Sensitive information exposure through logs **Risk Level**: Medium ### Complete Code Snippet ```python token = get_access_token(access_key, secret_key) call_body = build_call_body(config, args) result = create_realtime_call(token, call_body) except Exception as exc: print(f"ERROR: {exc}", file=sys.stderr) return 1 print(json.dumps({"request": call_body, "response": result}, ensure_ascii=False, indent=2)) return 0 ``` ### Technical Analysis After creating a call task, the script prints the entire request body and complete service response. Depending on supplied options and configuration, `call_body` can contain: - `mobile`: the recipient's phone number. - `callerNum`: caller-number pool entries. - `dialogVar.name` and `dialogVar.owner_name`: personal names or identities. - `dialogVar.user_intent`: potentially private reminder or message content. - `plainText` or `cipherText`: call-related data. - `callBackUrl`: an internal or credential-bearing callback URL. - `extJson`: arbitrary business metadata. - `robotId`, `secretId`, and platform-specific identifiers. Standard output is commonly retained by cron, agent runtimes, CI systems, terminal capture tools, and centralized logging services. Printing the full request violates data minimization and expands access to call information beyond the AIOB service and intended caller. The access token itself is not placed in `call_body` and is therefore not directly printed by this statement. ### Attack Path 1. A user requests an outbound call and supplies a phone number, recipient name, and sensitive message content. 2. The script creates `call_body` containing this information and sends it to the intended AIOB endpoint. 3. On success, the script serializes the complete request and response to standard output. 4. A scheduler, agent framework, shell logger, CI service, or centralized log co ...[truncated 767 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not print the full request body by default. 2. Return only a minimal success result, such as: - Success or failure status. - A non-sensitive task identifier such as `memberId`, if appropriate. - A sanitized service message. 3. Redact or omit at least `mobile`, `callerNum`, `dialogVar`, `plainText`, `cipherText`, `callBackUrl`, and `extJson`. 4. If diagnostic output is needed, place it behind an explicit `--debug` option and still redact credentials, tokens, phone numbers, names, and message content. 5. Configure agent, scheduler, and CI environments with short log-retention periods and access controls. 6. Avoid including secrets in callback URLs or extension fields. 7. Add automated tests confirming that normal stdout and stderr never contain phone numbers, authentication material, or dialog content. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/create_realtime_call.py:72
Finding
Full authentication error responses can leak access tokens into error logs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create_realtime_call.py:72-73`, with output at `scripts/create_realtime_call.py:211-213` **Vulnerability Type**: Authentication token exposure through error handling **Risk Level**: Low ### Complete Code Snippet ```python if data.get("code") != 200 or not data.get("data", {}).get("accessToken"): raise RuntimeError(f"getToken failed: {json.dumps(data, ensure_ascii=False)}") ``` The exception is subsequently printed without sanitization: ```python except Exception as exc: print(f"ERROR: {exc}", file=sys.stderr) return 1 ``` ### Technical Analysis When the token endpoint returns an unsuccessful business code or omits the expected token, the implementation embeds the complete JSON response in an exception. That exception is then printed to standard error. Under ordinary documented success behavior, a valid response containing an access token does not enter this branch. Exposure requires an anomalous, partially successful, or future response format—for example, a response that contains `data.accessToken` but has a non-200 business code. Other sensitive diagnostic fields added by the service could also be exposed. Because stderr is frequently retained by schedulers, agent runtimes, and centralized logging, serializing the complete authentication response creates an avoidable secret-disclosure path. ### Attack Path 1. The script sends legitimate AK/SK credentials to the documented AIOB token endpoint. 2. The service, a compatible proxy, or a changed API response returns a non-success business code while also including an access token or other sensitive authentication metadata. 3. The script serializes the complete response into a `RuntimeError`. 4. `main()` prints the exception to stderr. 5. An agent, scheduler, or log collector retains the output. 6. A party with log access extracts the token and uses it before expiration to invoke API operations permitted by that token. ### Impact A ...[truncated 539 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never include the complete authentication response in exceptions or logs. 2. Extract and report only an allowlisted numeric error code and a sanitized, bounded error message. 3. Explicitly remove fields named `accessToken`, `token`, `secret`, `accessKey`, and `secretKey` before logging any response data. 4. Use a generic error when the response does not match the expected schema, for example: `Token request failed with an invalid response`. 5. Ensure stderr from scheduled or agent-driven executions is access-controlled and retained only as long as operationally necessary. 6. Add tests using malformed and partially successful token responses to verify that no token-like value appears in exceptions or logs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill instructs use of local configuration files and outbound API calls to Baidu AIOB, but it does not declare any explicit tool scope or permissions boundaries. That creates a real security governance gap: an agent may be able to read local files and make network requests without the user being clearly informed of or protected by least-privilege constraints.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This skill is designed to place outbound calls and transmit phone numbers plus message content to an external calling platform, yet the skill text does not present a clear user-facing warning or consent notice about third-party calling and data transfer. In this context, that omission is meaningful because the skill handles personal contact data and can contact third parties on the user's behalf, increasing privacy, compliance, and abuse risk.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The documentation instructs the agent to create outbound calls and one-shot cron jobs via subprocess commands, but it does not require an explicit confirmation step, consent check, or user-facing warning before triggering real-world actions. In this skill context, that is risky because it can cause unintended phone calls or scheduled tasks based on ambiguous natural-language extraction, creating privacy, harassment, or operational-impact issues.

External Transmission

Medium
Category
Data Exfiltration
Content
def get_access_token(access_key: str, secret_key: str, timeout: int = 15) -> str:
    payload = {"accessKey": access_key, "secretKey": secret_key}
    resp = requests.post(TOKEN_URL, json=payload, timeout=timeout)
    resp.raise_for_status()
    data = resp.json()
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"Content-Type": "application/json",
        "Authorization": access_token,
    }
    resp = requests.post(REALTIME_CALL_URL, headers=headers, json=body, timeout=timeout)
    resp.raise_for_status()
    return resp.json()
Confidence
88% confidence
Finding
The script transmits phone numbers, dialog variables, and optional plaintext/ciphertext fields to a remote service to trigger real-world phone calls, but it applies no validation, consent enforcement, or destination restrictions. In a skill/agent environment, this can enable privacy-impacting data exfiltration and unauthorized outbound actions if upstream prompts or automation supply attacker-controlled inputs.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script can immediately place outbound calls using phone/contact data with no interactive confirmation, consent check, allowlist, or dry-run safeguard. In an agent-skill context, this makes accidental or unauthorized real-world actions more likely, especially if user input is mapped directly to call parameters or the skill is triggered automatically.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
This markdown file contains user-facing natural-language instructions exclusively in Chinese, and there is no indication that the skill is region-specific or that users can opt into this locale. Under the stated policy, forcing a specific language without user choice can be a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The entire skill guidance, examples, and command semantics are presented only in Chinese, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking context. Under the stated policy, forcing a specific language without opt-in can be a natural-language policy violation.

Missing User Warnings

Low
Confidence
87% confidence
Finding
The script reads accessKey and secretKey from config or CLI and immediately uses them to request an access token from a remote service. There is no comment, warning, or user-facing notice indicating that credentials from the local config will be transmitted for authentication.

Static analysis

No suspicious patterns detected.