Back to skill

Security audit

baidu qianfan agent chat

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward Baidu Qianfan chat API wrapper, with ordinary privacy cautions around sending prompts to Baidu and saving a local conversation ID.

Install only if you intend to send chat prompts and selected request metadata to Baidu Qianfan. Keep QIANFAN_API_KEY private, avoid sending sensitive data unless authorized, and delete or protect artifact/state/session.json if conversation linkage matters on your machine.

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

Note
Location
scripts/chat.py:24
Finding
Insecure Plaintext Session-State Storage<![CDATA[ ## Vulnerability Details **File Location**: `scripts/chat.py`, lines 24–42 and 331–350 **Vulnerability Type**: Plaintext sensitive state storage with unsafe default file handling **Risk Level**: Low ### Vulnerable Code ```python # Session state file path SESSION_STATE_FILE = Path(__file__).parent.parent / "state" / "session.json" def load_session_state() -> Dict[str, Any]: """Load session state""" if SESSION_STATE_FILE.exists(): try: with open(SESSION_STATE_FILE, "r", encoding="utf-8") as f: return json.load(f) except Exception: pass return {} def save_session_state(state: Dict[str, Any]) -> None: """Save session state""" SESSION_STATE_FILE.parent.mkdir(parents=True, exist_ok=True) with open(SESSION_STATE_FILE, "w", encoding="utf-8") as f: json.dump(state, f, ensure_ascii=False, indent=2) ``` The state is subsequently loaded and saved as follows: ```python # Process conversation ID conversation_id = args.conversation_id if not conversation_id and not args.new_session: # Read conversation ID from state file state = load_session_state() conversation_id = state.get("conversation_id") if conversation_id: print(f"[Using saved conversation: {conversation_id}]", file=sys.stderr) # Call API result = chat( query=args.query or "", app_id=args.app_id, stream=args.stream, conversation_id=conversation_id, file_ids=file_ids, tools=tools, tool_choice=tool_choice, tool_outputs=tool_outputs, action=action, end_user_id=args.end_user_id, metadata_filter=metadata_filter, custom_metadata=custom_metadata, ) # Save conversation ID if "conversation_id" in result: save_session_state({"conversation_id": result["conversation_id"]}) ``` ### Technical Analysis The returned conversation identifier is stored in plaintext at the predictable path `state/session.json`. The code creates the directory and file wi ...[truncated 2883 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store session state in a user-specific data directory rather than inside the Skill package, such as a platform-appropriate application-state directory. 2. Create the state directory with mode `0700` and the state file with mode `0600`. 3. Open files using flags that reject symbolic links where supported, such as `os.O_NOFOLLOW`, and verify that the destination is a regular file owned by the current user. 4. Write updates atomically: - Create a temporary file securely in the same private directory. - Set its permissions to `0600`. - Write and flush the JSON. - Call `os.fsync()` when durability is required. - Replace the destination with `os.replace()`. 5. Validate loaded state before use. Require an object containing only an appropriately formatted string `conversation_id`, and reject unexpected fields or types. 6. Detect and reject state directories or files that are writable by group or other users. 7. Provide an option to disable persistence and document that conversation identifiers are retained locally. 8. If conversation identifiers are considered sensitive in the deployment model, use an operating-system credential store or another protected storage mechanism. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (9)

Tainted flow: 'headers' from os.environ.get (line 91, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
body["custom_metadata"] = custom_metadata
    
    try:
        response = requests.post(
            API_URL,
            headers=headers,
            json=body,
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill declares access to sensitive capabilities via metadata requirements and documented behavior—environment variables, local state persistence for conversation IDs, and outbound API calls—but does not define an explicit permission or allowed-tools boundary. This can lead to overbroad execution in agent environments, making it harder to constrain or audit what the skill may read, write, or send over the network.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger conditions are broad and ambiguous, including any mention of '千帆', 'qianfan', or generic need for Baidu AI chat, which can cause the skill to activate outside the user's actual intent. In an agent system with network and file capabilities, accidental activation may expose prompts, session context, or files to an external API and create unintended side effects such as persisted conversation state.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This markdown file documents request fields such as `file_ids` and `end_user_id` that can send user documents and user identifiers to a remote API, but the surrounding description does not warn readers about privacy, data handling, or external transmission implications. Under the markdown-specific SQP-2 criterion, documentation should disclose behaviors that may affect user data or privacy.

External Transmission

Medium
Category
Data Exfiltration
Content
### 基础请求示例

```bash
curl --location 'https://qianfan.baidubce.com/v2/app/conversation/runs' \
--header 'Authorization: Bearer <API Key>' \
--header 'Content-Type: application/json' \
--data '{
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The module docstring and all user-facing CLI descriptions are written exclusively in Chinese, presenting the skill as a Chinese-language tool without any opt-in or alternative language support. Under the policy, forcing a specific language without user choice is a natural-language policy concern unless the locale restriction is explicitly justified.

External Transmission

Medium
Category
Data Exfiltration
Content
body["custom_metadata"] = custom_metadata
    
    try:
        response = requests.post(
            API_URL,
            headers=headers,
            json=body,
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The function description states that only Chinese cities are supported and other countries are not supported, which is a locale restriction expressed in natural language. The document does not present this as an explicit user opt-in choice or provide a policy or compliance justification for excluding other locales.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The script persists the conversation_id to disk automatically without notifying the user or offering an opt-in. While a conversation_id is not typically a secret like an API key, it is still session-related metadata that can leak chat linkage, create privacy surprises on shared systems, or enable unintended session reuse by other local users/processes.

Static analysis

No suspicious patterns detected.