Back to skill

Security audit

Baidu Content Censor

Security checks for vulnerabilities and agentic risk

Overview

This Baidu moderation skill is mostly coherent, but it needs review because local image handling can upload any readable file path to Baidu and token handling is weakly safeguarded.

Install only if you intend reviewed content to be sent to Baidu. Use restricted Baidu credentials, avoid passing sensitive local paths, verify token-cache permissions, and prefer adding confirmation plus image validation before any local file upload.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
api_client.py:204
Finding

Arbitrary Local Files Can Be Encoded and Uploaded to a Remote Moderation Service

Content
View full analysis
")` or `censor("")`. 3. `os.path.isfile(image)` confirms that the path exists. 4. The Skill opens and reads the complete file using the process's existing filesystem privileges. 5. The file is Base64-encoded and inserted into the outbound request body as `image`. 6. The encoded file contents are transmitted to the configured Baidu endpoint. 7. Even if Baid ...[truncated 865 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
api_client.py:77
Finding

Baidu API Credentials Are Embedded in Request URLs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
api_client.py:51
Finding

Access Token Cache Is Written Without Explicit Restrictive Permissions

Content
View full analysis
None: """保存 token 到缓存文件""" cache_dir = os.path.dirname(TOKEN_CACHE_FILE) if not os.path.exists(cache_dir): os.makedirs(cache_dir) with open(TOKEN_CACHE_FILE, "w") as f: json.dump(token_data, f) ``` ### Technical Analysis The Skill stores a reusable Baidu access token in plaintext at: ```text ~/.claude/skills/baidu-content-censor/token_cache.json ``` The directory and file are created without explicit permission modes. Their effective permissions therefore depend on the process umask and any pre-existing filesystem objects. In a permissively configured environment, another local user or process could read the token. The implementation also does not check whether the cache path is a symbolic link, does not verify the owner or permissions of an existing cache file, and writes the JSON directly rather than using an atomic replacement. These properties permit local tampering, partial writes, and potential redirection of the write where an attacker can manipulate the cache path or its parent directories. ### Attack Path 1. The Skill obtains a valid access token from Baidu. 2. `save_token_cache` creates or overwrites the cache using default permissions inherited from the current umask. 3. In an environment with permissive permissions, another local account or process reads the cache file. 4. The attacker extracts the reusable `access_token`. 5. The attacker submits requests to Baidu APIs until the token expires or is revoked. A related tampering path is possible if an attacker can pre-create or replace the cache file or a parent path with a malicious symbolic link. The practical exploitability of both paths depends on local directory ownership and permissions. ### Impact Assess ...[truncated 484 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
Findings (18)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · api_client.py (reported line 78)May include surrounding context.

python
url = f"{TOKEN_URL}?grant_type=client_credentials&client_id={ak}&client_secret={sk}"

    response = requests.post(url)
    result = response.json()

    if "access_token" in result:

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · api_client.py (reported line 104)May include surrounding context.

python
url = f"{TOKEN_URL}?grant_type=client_credentials&client_id={ak}&client_secret={sk}"

    response = requests.post(url)
    result = response.json()

    if "access_token" in result:

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · api_client.py (reported line 148)May include surrounding context.

python
if appid:
        data["appid"] = appid

    response = requests.post(
        url,
        data=data,
        headers={"Content-Type": "application/x-www-form-urlencoded"}

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · api_client.py (reported line 163)May include surrounding context.

python
if appid:
        data["appid"] = appid

    response = requests.post(
        url,
        data=data,
        headers={"Content-Type": "application/x-www-form-urlencoded"}

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · api_client.py (reported line 217)May include surrounding context.

python
if appid:
        data["appid"] = appid

    response = requests.post(
        url,
        data=data,
        headers={"Content-Type": "application/x-www-form-urlencoded"}

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · api_client.py (reported line 232)May include surrounding context.

python
if appid:
        data["appid"] = appid

    response = requests.post(
        url,
        data=data,
        headers={"Content-Type": "application/x-www-form-urlencoded"}

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill instructs the agent to send text, image URLs, and local image files to Baidu's third-party moderation APIs but does not require any user warning or consent notice before transmission. This is a significant privacy issue because sensitive content, private URLs, or local files may be exfiltrated to an external provider unexpectedly.

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 · SKILL.md (reported line 52)May include surrounding context.

md
## Token 缓存机制

- Access Token 会自动从百度云 API 获取
- 缓存文件位置:`~/.claude/skills/baidu-content-censor/token_cache.json`
- 缓存过期时间:提前 5 分钟自动刷新
- 如果 API 返回 110(access_token 无效)或 111(access_token 过期),会自动刷新并重试

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 137)May include surrounding context.

md
## Token 缓存机制

- Access Token 会自动从百度云 API 获取
- 缓存文件位置:`~/.claude/skills/baidu-content-censor/token_cache.json`
- 缓存过期时间:提前 5 分钟自动刷新
- 如果 API 返回 110(access_token 无效)或 111(access_token 过期),会自动刷新并重试

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 · api_client.py (reported line 159)May include surrounding context.

python
# 如果返回 110 或 111,强制刷新 token 并重试
    if result.get("error_code") in [110, 111]:
        if skip_cache:
            raise ValueError(f"Access token 无效: {result}")
        access_token = refresh_access_token()
        _last_access_token = access_token
        url = f"{TEXT_CENSOR_URL}?access_token={access_token}"

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 · api_client.py (reported line 228)May include surrounding context.

python
# 如果返回 110 或 111,强制刷新 token 并重试
    if result.get("error_code") in [110, 111]:
        if skip_cache:
            raise ValueError(f"Access token 无效: {result}")
        access_token = refresh_access_token()
        _last_access_token = access_token
        url = f"{TEXT_CENSOR_URL}?access_token={access_token}"

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases include very broad everyday expressions such as '检测一下...' and '请审核...', which can cause the skill to activate in contexts the user did not intend for third-party moderation. In this skill, accidental activation is more dangerous because it may send user text, image URLs, or local image paths to an external censorship service without clear confirmation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module docstring names and describes the skill entirely in Chinese, which can impose a language-specific experience without any opt-in or justification. Under the policy, language constraints should either offer a choice or be explicitly documented as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code persists access tokens to a predictable file under the user's home directory without setting restrictive permissions or warning that credentials are stored on disk. On multi-user systems or misconfigured environments, other local users or processes may read the token and reuse it until expiration.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The callable interfaces transmit caller-provided text, local image files, or image URLs to Baidu moderation services without any built-in notice, consent gate, or privacy warning. In a skill context, this can cause users or upstream agents to unknowingly exfiltrate sensitive content, especially because local file paths are automatically read and uploaded as base64.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

整份技能文档仅以中文描述技能名称、触发词和使用方式,未说明是否仅面向中文用户,也未提供其他语言选择或用户可选项。若组织要求避免未经用户同意强制特定语言,这种单一语言设定可能构成自然语言策略违规。

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill states that every request automatically includes isFromSkill=true for telemetry, which is unrelated to the core content-audit function and is not clearly disclosed earlier as a data-sharing behavior. Even if the parameter seems harmless, adding tracking metadata to third-party requests increases privacy exposure and can enable service-side profiling of agent-originated activity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

Natural-language strings in the module docstring and user-facing error messages are Chinese-only, which can effectively force a specific language on users. The file does not indicate that this is a region-specific tool or offer an alternative language/locale option.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.