Back to skill

Security audit

baize-task-bot

Security checks for vulnerabilities and agentic risk

Overview

The skill’s outbound-call management purpose is coherent, but it can perform high-impact campaign and account changes using a shared API token with weak in-skill safeguards.

Install only in a controlled Baize operations environment. Use an HTTPS-only BAIZE_BASE_URL, a least-privileged BAIZE_TOKEN, and external approval controls for every write action, especially campaign starts, concurrency or line changes, and account creation. Avoid using this skill with broad admin tokens until role checks and confirmation enforcement are added in code or on the server side.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
skill.py:835
Finding
Sensitive Write Operations Lack Enforced Authorization and Confirmation<![CDATA[ ## Vulnerability Details **File Location**: `skill.py:835-856` **Related Locations**: `SKILL.md:46-48`; `skill.py:468-492`, `515-527`, `554-571`, `601-620`, `652-673`, `711-734`, `773-796`, `885-905`, `926-938` **Vulnerability Type**: Missing authorization and confirmation enforcement **Risk Level**: High ### Vulnerable Code ```python async def create_main_account( ctx: SkillContext, account: str, password: str, name: str, tenant_id: int, is_for_encryption: bool = False, ) -> str: body = { "account": account, "password": password, "name": name, "tenantId": tenant_id, "isForEncryptionPhones": is_for_encryption, } endpoint = "/AiSpeech/admin/addMainUser" try: result = _baize_post(endpoint, body) if str(result.get("code")) == "2000": return f"主账号 [{account}]({name})已成功创建,所属商户ID:{tenant_id}。" return f"创建主账号失败:{result.get('msg', '未知错误')}" except Exception as exc: return f"创建主账号时发生错误:{exc}" ``` The documented confirmation requirement is present only in the Skill instructions: ```markdown - 执行**启动/暂停/恢复任务**、**切换线路**、**调整并发**、**新建账号**等**写操作**前, 必须先向用户展示操作详情,等待确认后再执行。 ``` ### Technical Analysis The Skill documentation states that write operations require prior user confirmation and that creation of a main account is restricted to administrators. These requirements are not enforced by the implementation. The `ctx` parameter is accepted but never inspected to establish the caller's identity, role, tenant, or authorization. The function immediately constructs an administrative request using caller-supplied values and sends it through `_baize_post`. There is no confirmation token, operation-bound approval record, role check, tenant ownership check, or validation that the requested tenant and role identifiers belong to the authenticated caller. The same design is used by other mutating operations, including starting, stopping, a ...[truncated 2036 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce authorization in both the Skill and the Baize API. The server must remain the authoritative security boundary. 2. Derive the caller's identity, tenant, and roles from authenticated `SkillContext` data rather than accepting security-sensitive identity information solely as tool parameters. 3. Reject `create_main_account` unless the authenticated context proves that the caller has an explicit administrator permission. 4. For subaccount creation, validate that the requested `role_id` is assignable by the caller and cannot exceed the caller's own privileges. 5. Validate that task IDs, line IDs, and tenant IDs belong to a tenant the authenticated caller is permitted to manage. 6. Introduce a short-lived confirmation nonce for every mutation. Bind it cryptographically or server-side to the caller, operation type, target IDs, parameter values, and expiration time. 7. Require the action function to consume that nonce before sending the API request. A general conversational acknowledgment must not authorize a different operation or modified parameters. 8. Apply least privilege to `BAIZE_TOKEN`. Separate administrative account-management credentials from campaign-operation credentials. 9. Validate all inputs, including nonempty task arrays, allowed task and operator types, positive concurrency, permitted line-ratio ranges, and valid date formats. 10. Record an audit event containing the authenticated principal, approved operation, target resources, and remote response, while excluding passwords and tokens. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
skill.py:106
Finding
API Token and Account Passwords Can Be Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `skill.py:106-113` **Related Locations**: `skill.py:26-27`, `835-852`, `885-901`; `SKILL.md:69-70` **Vulnerability Type**: Plaintext transmission of sensitive credentials **Risk Level**: Medium ### Vulnerable Code The configuration permits a plaintext HTTP endpoint: ```python _BAIZE_BASE_URL = os.getenv("BAIZE_BASE_URL", "http://localhost:8860/market") _BAIZE_TOKEN = os.getenv("BAIZE_TOKEN", "") ``` The complete request helper sends the token to the configured endpoint without requiring HTTPS: ```python def _baize_post(path: str, body: dict) -> dict: """Send a POST request to the Baize API and return the parsed response.""" url = _BAIZE_BASE_URL + path headers = {"token": _BAIZE_TOKEN, "Content-Type": "application/json"} with httpx.Client(timeout=30) as client: resp = client.post(url, json=body, headers=headers) resp.raise_for_status() return resp.json() ``` Account-creation requests also include plaintext passwords in the request body: ```python body = { "account": account, "password": password, "password2": password, "name": name, "roleId": role_id, } ``` ### Technical Analysis `_baize_post` trusts the `BAIZE_BASE_URL` environment variable and does not validate its URL scheme or destination. The documented default uses `http://`. While the default host is loopback, operators can configure any remote HTTP URL. For every write request, the helper sends `BAIZE_TOKEN` in an HTTP header. Account-creation operations additionally transmit initial account passwords in the JSON body. When the configured destination is remote and uses plaintext HTTP, neither the token nor the request body receives transport confidentiality or integrity protection. A network observer, compromised proxy, malicious gateway, or attacker positioned on the request path could capture or alter these values. The issue is configuration-dependent: loopback-only use reduces ...[truncated 1345 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require `https://` for `BAIZE_BASE_URL` in all production configurations. 2. Permit plaintext HTTP only for explicitly verified loopback development addresses such as `127.0.0.1`, `::1`, or `localhost`, and require a deliberate development-mode flag. 3. Parse and validate the URL during initialization. Reject unsupported schemes, embedded credentials, malformed hosts, and unexpected destinations. 4. Keep TLS certificate verification enabled and configure an approved certificate authority or certificate pinning where the deployment model warrants it. 5. Do not follow redirects to a different scheme or untrusted host when sending authenticated requests. 6. Use separate, least-privileged, short-lived API credentials instead of a broadly privileged reusable token. 7. Avoid administrator-selected reusable initial passwords where possible. Prefer one-time activation links or temporary credentials that must be changed at first login. 8. Never log request headers or account-creation bodies containing tokens or passwords. 9. Fail closed when `BAIZE_TOKEN` is empty rather than sending an unauthenticated request whose behavior depends on the remote service. 10. Document secure deployment requirements, including TLS termination, proxy trust boundaries, secret rotation, and credential-revocation procedures. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (13)

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The change_concurrency tool claims to only adjust concurrency, but it calls an endpoint named editConcurrencyAndStartTask, which can start tasks as a side effect. That mismatch violates least surprise and can trigger outbound calling when the user intended only a non-starting configuration change, causing unauthorized operational actions and potential compliance or cost impact.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The change_tenant_line tool is documented as switching lines, but it invokes the same editConcurrencyAndStartTask endpoint that can also start tasks. This creates a hidden side effect where a seemingly administrative line switch may actually launch outbound activity, which is especially risky in a telephony operations context.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises capabilities that read local files, consume environment variables, and perform network write operations, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization gap: a host or reviewer cannot easily constrain the skill to the minimum required surface, increasing the risk of unintended file access, secret use, or outbound API actions beyond what the user expects.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The manifest description and primary instructions are written as a Chinese-only assistant persona, directing the skill to operate in Chinese without any opt-in or alternative language handling. This is a natural-language locale policy concern because the file imposes a specific language by default rather than offering user choice or explaining a region-specific requirement.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This JSON file defines multiple script names and remarks entirely in Chinese, such as loan, credit card, insurance, and wealth-management call scripts, with no indication that language selection is optional or region-specific. Under the policy rules, a skill that effectively enforces a specific language without user opt-in can be a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
This JSON file uses Chinese-only natural-language values for names, notes, supplier labels, and industry categories, with no indication that the skill is region-specific or that users can choose another language/locale. Under the policy criteria, natural-language content that effectively enforces one language without documented opt-in or justification is a reportable locale-policy issue.

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
This JSON manifest-like file uses only Chinese-language task names, comments, and speech-craft labels with no indication that language selection is optional or configurable. Under the policy for natural-language violations, forcing a specific language without user opt-in can be a locale-policy issue.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This JSON file contains user-facing natural-language fields such as task and script names entirely in Chinese, with no indication that the skill offers language choice or that the locale restriction is intentionally limited to a Chinese-only deployment. The policy requires flagging language/locale constraints when they are imposed without user opt-in or clear justification.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
This outbound-operations skill includes privileged account-provisioning actions that expand its authority well beyond read/query and task-operation workflows. In an agent setting, this increases blast radius: a prompt-injected or mistaken invocation could create new operator accounts or admin-linked identities on the remote platform without a dedicated admin boundary.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The main-account creation action collects and forwards a plaintext password to a remote API, while the default base URL may be plain HTTP. In this skill context, that means highly sensitive credentials may be exposed in transit, logs, traces, or agent/tool telemetry, enabling account compromise if intercepted or retained insecurely.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The sub-account creation path likewise transmits plaintext passwords to a remote API and duplicates the secret in both password and password2 fields, increasing exposure surface. Because this is an agent-executed skill, secrets may leak through observability pipelines or insecure transport if the configured endpoint is not protected.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
This JSON file contains multiple user-facing text fields entirely in Chinese, including line names, notes, and industry labels. For a general-purpose skill asset, hard-coding a single language without any documented opt-in or locale justification can violate language/locale policy requirements.

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
Natural-language descriptions, parameter help text, and returned messages throughout the file are written exclusively in Chinese, and the skill name itself is Chinese, with no indication that the user can choose another language or that the skill is intentionally limited to a Chinese-only environment. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern unless the locale restriction is explicit and justified.

Static analysis

No suspicious patterns detected.