Back to skill

Security audit

Clip2MD

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its stated clip2md purpose, but it needs review because it stores a bearer token locally and can send that token to an environment-selected API host without strong safeguards.

Review before installing. Use it only in a trusted local environment, avoid setting CLIP2MD_API_BASE except for trusted test/private servers, ensure ~/.clip2md/config.json is readable only by your user, and require explicit approval before submitting URLs that consume clip2md quota.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/clip2md.js:35
Finding

Bearer Token Stored Without Explicit Restrictive File Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/clip2md.js, lines 35–38
Vulnerability Type: Plaintext credential storage with permissions dependent on the process umask
Risk Level: Medium

Vulnerable Code:

javascript
function saveConfig(config) {
  fs.mkdirSync(CONFIG_DIR, { recursive: true });
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
}

Technical Analysis

The application stores the clip2md bearer token in plaintext at ~/.clip2md/config.json. Neither the configuration directory nor the file is created with an explicit restrictive mode. Their effective permissions therefore depend on the process umask.

Under a common umask of 0022, the directory may be created as 0755 and the file as 0644, allowing other local users to traverse the directory and read the credential. The bundled smoke test expects directory mode 0700 and file mode 0600, but the audited implementation does not explicitly enforce either mode.

The network transmission of the token to the clip2md service is required for the declared functionality, but making the locally persisted credential potentially readable by unrelated users exceeds the minimum access necessary.

Attack Path

  1. A victim runs node scripts/clip2md.js config <token> in an environment with a permissive umask.
  2. The CLI creates ~/.clip2md/config.json without explicitly assigning mode 0600.
  3. Another local user checks the victim's home directory and configuration-file permissions.
  4. If traversal and read permissions are available, the attacker reads ~/.clip2md/config.json.
  5. The attacker extracts the bearer token and uses it to authenticate directly to the clip2md API.
  6. The attacker can consume the victim's quota and access API operations authorized by that token, including task metadata available to the account.

Impact Assessment

Exploitation requires access as another local user and permiss ...[truncated 283 chars]

Remediation
View remediation

Remediation Suggestions

  • Create ~/.clip2md with mode 0700:
    javascript
    fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
    fs.chmodSync(CONFIG_DIR, 0o700);
    
  • Write the token file with mode 0600 and explicitly correct permissions on an existing file:
    javascript
    fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), {
      mode: 0o600,
    });
    fs.chmodSync(CONFIG_FILE, 0o600);
    
  • Prefer an atomic write to a securely created temporary file in the same directory, followed by a rename, to avoid partial files and permission races.
  • Where supported, store the token in an operating-system credential manager rather than a plaintext JSON file.
  • Update the smoke test so its permission assertions are run in continuous integration and cannot diverge from the implementation.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/clip2md.js:7
Finding

Environment-Controlled API Endpoint Can Receive the Stored Bearer Token

Content
View full analysis

Vulnerability Details

File Location: scripts/clip2md.js, lines 7 and 89–103
Vulnerability Type: Credential disclosure through an unrestricted network destination override
Risk Level: High

Vulnerable Code:

javascript
const BASE_URL = (process.env.CLIP2MD_API_BASE || 'https://clip2.md/api/v1').replace(/\/+$/, '');

async function request(method, path, body = null) {
  const token = ensureToken();

  const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`,
  };

  const options = { method, headers };
  if (body) options.body = JSON.stringify(body);

  const res = await fetch(`${BASE_URL}${path}`, options);

Technical Analysis

CLIP2MD_API_BASE can replace the legitimate API origin with an arbitrary URL. The value is not restricted to HTTPS, checked against an allowlist, or bound to a separate credential. Every authenticated operation then sends the stored bearer token in the Authorization header to the selected destination.

Support for test environments and private deployments is documented, and the default destination is the expected https://clip2.md/api/v1; therefore, this behavior is not evidence of intentional exfiltration. Nevertheless, an attacker who can influence the process environment can redirect the production credential to an attacker-controlled HTTP or HTTPS server. Permitting plaintext HTTP also exposes the credential to network interception.

The endpoint override is useful for testing, but forwarding the same persistent production token to any environment-selected host is broader than the minimum privilege required.

Attack Path

  1. The victim has previously configured a valid token in ~/.clip2md/config.json.
  2. An attacker influences the environment used to launch the Skill, for example through a compromised wrapper, service configuration, shell initialization file, automation configuration, or inherited environment ...[truncated 1141 chars]
Remediation
View remediation

Remediation Suggestions

  • Require HTTPS for all non-loopback API endpoints and reject unsupported URL schemes.
  • Use https://clip2.md as the only permitted production origin by default.
  • Introduce an explicit trusted-host allowlist for private deployments instead of accepting any environment-provided destination.
  • Require an explicit configuration or confirmation step before sending credentials to a non-default host.
  • Store separate credentials per API origin and never automatically forward the production clip2md token to test or private endpoints.
  • Permit HTTP only for loopback test servers, such as 127.0.0.1 or localhost, and only when an explicit test mode is enabled.
  • Parse the override with new URL() and validate its protocol, hostname, port, username, and password before constructing a request.
  • Document that environment variables are security-sensitive and clear untrusted inherited values when the Skill is launched by automation.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (15)

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

md
---
name: clip2md
description: Use clip2md to configure an access token, save web pages or article URLs as Markdown clipping tasks, check remaining daily/permanent quota, query task status, and wait for clipping completion or failure. Use when the user mentions clip2md, 剪藏, clip, 保存网页为 Markdown, 查询额度, 提交链接, 查询任务, 等待剪藏完成, or wants an Agent to operate the clip2md product tool.
metadata:
  openclaw:
    requires:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/clip2md.js <command>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/clip2md.js <command>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/clip2md.js <command>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/clip2md.js <command>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/clip2md.js <command>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/clip2md.js <command>

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes a Node.js CLI that reads from the environment/home directory and calls a remote API, but it does not declare any explicit tool scope such as allowed tools or permissions. This creates an authorization gap where the agent may be permitted broader filesystem, environment, or network access than the skill actually needs, increasing the blast radius if the skill is misused or modified.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation description lists generic phrases such as "clip" and broad intents like "wants an Agent to operate the clip2md product tool," which are ambiguous and could match ordinary conversation unrelated to this specific skill. The trigger guidance does not provide clear scope boundaries or negative examples to constrain when the skill should versus should not activate.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The default prompt is broadly phrased and can match common user intents like saving a web page as Markdown without requiring an explicit request to use this specific skill. That increases the chance of unintended invocation, which could trigger external actions such as submitting URLs or consuming user quota when the user only described a general task.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Enabling implicit invocation without clear scope constraints allows the skill to be triggered automatically from ambiguous user language. In this skill's context, automatic invocation can cause state-changing operations against an external service, including token-backed submissions and quota usage, making accidental or over-broad activation materially risky.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The skill description hard-codes Chinese trigger phrases alongside English and later uses Chinese status text such as "已生成" without stating that the skill is region-specific or allowing the user to choose a preferred language. This can violate language/locale policy when a skill implicitly forces a locale in natural-language interactions.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
75% confidence
Finding

This manifest file describes the skill only as "剪藏链接、查询额度" (clip links, query quota) without specifying the exact trigger phrases, context, or limits for when it should activate. In a manifest file, such broad wording can lead to unclear invocation boundaries and unintended matching against generic user requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script's natural-language strings, including error messages and usage guidance, are presented only in Chinese. This imposes a specific language on all users without opt-in or any indication that the tool is intentionally limited to a Chinese-speaking context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The string literal 账号授权失效 forces a Chinese-language message in the simulated API response. Under the policy, locale-specific language should be optional or clearly justified; this file provides neither a user opt-in nor documentation that the skill is intentionally Chinese-only.

Content

No source excerpt is available for this finding.