Back to skill

Security audit

Zhipu Z.ai web search

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent ZHIPU AI web-search integration, but it under-discloses the risk of storing a paid API key in plaintext inside the skill folder.

Install only if you are comfortable sending searches to ZHIPU AI and managing a ZHIPU API key. Prefer ZAI_API_KEY or a protected user-level config over skill-folder config.json, do not commit or share any populated config file, restrict file permissions, and rotate the key if it may have been exposed.

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

Warning
Location
config.json:1
Finding

API Credentials Are Stored in a Plaintext Project Configuration File

Content
View full analysis

Vulnerability Details

File Location: config.json, lines 1-9; README.md, lines 91-109; scripts/zai-search.js, lines 15-21
Vulnerability Type: Plaintext sensitive credential storage
Risk Level: Medium

The project supplies a tracked config.json and instructs users to place their Zhipu AI API key directly in that file. The audited directory does not contain the .gitignore file referenced by the documentation, creating a realistic risk that a configured API key will be committed, packaged, backed up, or otherwise disclosed with the skill directory.

Vulnerable Code

config.json, lines 1-9:

json
{
  "apiKey": "your-zhipu-api-key-here",
  "engine": "search_std",
  "intent": false,
  "count": 10,
  "recency": "noLimit",
  "content": "medium",
  "domain": ""
}

README.md, lines 91-109:

markdown
# Copy example config file
cp config.json.example config.json

# Edit config file (with your preferred editor)
# For example: vim config.json, nano config.json, or open with VS Code
json
{
  "apiKey": "paste your API Key here",
  "engine": "search_std",
  "intent": false,
  "count": 10,
  "recency": "noLimit",
  "content": "medium",
  "domain": ""
}

scripts/zai-search.js, lines 15-21:

javascript
const skillDir = path.dirname(__dirname); // scripts/.. = skill root
const skillConfigPath = path.join(skillDir, 'config.json');
try {
  const skillConfig = JSON.parse(fs.readFileSync(skillConfigPath, 'utf8'));
  Object.assign(config, skillConfig);
} catch {}

Technical Analysis

API keys are bearer credentials: possession is generally sufficient to invoke the associated API. Storing such a credential as an ordinary plaintext file inside the skill installation directory exposes it to every process or user that can read that directory.

The risk is increased because:

  • The distributed project already contains config.json, ...[truncated 2278 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove config.json from the distributed project

    • Distribute only a clearly named template such as config.example.json.
    • Ensure templates contain placeholders and never real credentials.
  2. Add and distribute an effective .gitignore

    gitignore
    config.json
    *.local.json
    .env
    .env.*
    

    Confirm that config.json is no longer tracked after adding the rule:

    bash
    git rm --cached config.json
    
  3. Prefer environment-based or protected secret storage

    • Make ZAI_API_KEY the recommended configuration mechanism.
    • For persistent desktop use, consider an operating-system credential manager rather than a plaintext file.
    • If file-based storage remains supported, prefer the user-specific path outside the skill package.
  4. Enforce restrictive file permissions

    • Require user configuration directories to be mode 0700.
    • Require credential-bearing files to be mode 0600.
    • Warn or fail securely when a key file is readable by group or other users.
  5. Separate secret and non-secret configuration

    • Keep search defaults in ordinary JSON.
    • Obtain the API key only from an environment variable or dedicated secret provider.
  6. Reject placeholder credentials

    javascript
    const PLACEHOLDERS = new Set([
      'your-zhipu-api-key-here',
      'your-api-key-here'
    ]);
    
    if (!apiKey || PLACEHOLDERS.has(apiKey)) {
      throw new Error('Configure ZAI_API_KEY with a valid API key.');
    }
    
  7. Update all documentation

    • Stop describing skill-folder storage as the recommended option.
    • Clearly warn users never to commit, package, log, or share API keys.
    • Correct the documented file structure so it matches the distributed files.
  8. Respond to any prior exposure

    • Review repository history and published packages for populated copies of `conf ...[truncated 163 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • 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 (15)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
The CLI script lives at: `scripts/zai-search.js` (relative to this skill directory).

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file applies to SQP-2, and it explicitly tells the user to place an API key into config.json. While the file warns about JSON comments, it does not warn that the API key is a sensitive credential, should not be committed/shared, and will be stored locally in plaintext.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · QUICKSTART.md (reported line 11)May include surrounding context.

Visit https://open.bigmodel.cn to register and get an API Key

2. Create Config File

bash
# Enter skill folder

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The documentation recommends persistent local storage of the API key in config.json within the skill folder, which creates a durable secret on disk and may place it in a location more likely to be copied, synced, or accidentally committed. While persistence itself is common, recommending repo-adjacent storage without strong warnings or safer defaults raises the risk of credential leakage.

Content

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

md
1. **Get API Key**: Visit [https://open.bigmodel.cn](https://open.bigmodel.cn) to register and obtain an API Key

2. **Choose Configuration Method**:
   - Create `config.json` in the skill folder (recommended)
   - Set `ZAI_API_KEY` environment variable
   - Use user config `~/.config/zai-web-search/config.json`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README tells users to place a live API key into a local config file and shows multiple examples containing the secret, but it does not clearly warn that the key is sensitive, must not be shared, and must never be committed to source control. This increases the chance of accidental credential disclosure through screenshots, copied configs, backups, or repository commits, which could allow unauthorized API use and billing abuse.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents access to environment variables and credential-driven behavior but does not declare any explicit tool scope or allowed-tools boundary. In an agent ecosystem, missing capability declarations can cause over-broad execution privileges and make it harder for users or policy layers to understand that the skill may read secrets from the environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill is a web search integration that sends user queries to ZHIPU AI, but the description does not prominently warn that prompts, search terms, and possibly related metadata are transmitted to a third-party service. This creates a privacy risk because users may submit sensitive internal, personal, or regulated data without realizing it leaves the local environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The setup guidance tells users to store an API key in config files or environment variables but does not clearly emphasize that the key is sensitive or describe safe storage practices. This increases the chance of credential leakage through checked-in config files, world-readable files, shell history, logs, or shared skill directories.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The skill recommends persistent storage of the API key in local config files or environment configuration without discussing lifecycle, revocation, or secure storage tradeoffs. Persisted secrets can remain accessible to other local processes, backups, shared folders, or future sessions long after they are needed.

Content

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

md
1. **Get an API Key**: Visit [https://open.bigmodel.cn](https://open.bigmodel.cn) to register and get your API key

2. **Choose Configuration Method**:
   - Create `config.json` in this skill folder (recommended)
   - Set `ZAI_API_KEY` environment variable
   - Use user config at `~/.config/zai-web-search/config.json`

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · SKILL.md (reported line 247)May include surrounding context.

You can also call the API directly via curl:

bash
curl -s https://open.bigmodel.cn/api/paas/v4/web_search \
  -H "Authorization: Bearer $ZAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The human-readable comments throughout this config file are written in Chinese only, which imposes a specific language on users without offering an alternative or opt-in. Under the stated policy, locale or language restrictions should be optional or clearly justified, and no such justification appears here.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

The help text instructs users to store a long-lived API key in a plaintext config file under the skill folder or the user's home directory, creating persistent credential storage. If file permissions are weak, the directory is shared, or the skill folder is synced/committed, the credential can be exposed and reused to access the external API.

Content

Scanner excerpt · scripts/zai-search.js (reported line 142)May include surrounding context.

js
zai-search "React 19" --domain react.dev --content high

Config:
  Create config.json in the skill folder or ~/.config/zai-web-search/config.json
  to set default values:

  {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script sends the user's search query and the API credential to a third-party remote service, but it provides no runtime disclosure, consent prompt, or warning that input will leave the local environment. In an agent-skill context, users may reasonably assume a local helper, so silent exfiltration of prompts or sensitive search terms increases privacy and data-handling risk even though HTTPS is used.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

SQP-3 applies to all file types and includes language or locale policy violations. This quickstart forces a single language presentation for the skill documentation, with no opt-in, alternate language option, or justification that the skill is region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

标题明确将该技能说明限定为“中文说明”,且全文均以中文呈现,没有说明这是可选语言版本或提示用户可切换到其他语言。根据规则,强制特定语言而未提供用户选择属于自然语言层面的语言/地区策略问题。

Content

No source excerpt is available for this finding.