Back to skill

Security audit

知识库归档系统

Security checks for vulnerabilities and agentic risk

Overview

This archiver is coherent at a high level, but unsafe command execution and under-scoped AI/cloud integrations could expose documents or run commands while processing crafted files.

Review before installing. Avoid running this skill on untrusted Office documents or directories until the shell-based extraction and AI/cloud command paths are replaced with argument-based subprocess calls. Keep AI classification and cloud upload disabled unless you are comfortable with document names, summaries, excerpts, or full files leaving the local machine and you have validated the destination and credentials.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (5)

T09 · Insecure Skill Coding Practices

Error
Location
_scripts/archive.mjs:163
Finding
Shell Command Injection in AI Classification<![CDATA[ ## Vulnerability Details **File Location**: `_scripts/archive.mjs`, lines 163-186 and 248-250 **Vulnerability Type**: OS command injection through shell-interpolated document data and environment configuration **Risk Level**: High ### Vulnerable Code ```javascript async function aiClassify(filename, text, summary) { const prompt = `你是一个文件分类助手。请根据以下文件信息判断它应该归类到哪个分类。 文件名: ${filename} 内容摘要: ${summary.substring(0, 500)} 内容片段: ${text.substring(0, AI_CLASSIFY_CONFIG.maxTextLength)} 可选分类: 1. 工作文件 - 数据报表、销售业绩、门店运营、统计分析等 2. 方案文档 - 计划方案、策略规划、制度流程、管理规范等 3. 参考资料 - 话术模板、培训教程、案例经验、指南手册等 4. 其他文档 - 不属于以上分类的文档 请只输出分类名称(工作文件/方案文档/参考资料/其他文档),不要其他内容。`; try { let result; try { result = execSync(`openclaw chat --prompt "${escapeShell(prompt)}" --model ${AI_CLASSIFY_CONFIG.model}`, { encoding: 'utf-8', timeout: 30000, }).trim(); } catch (e) { // Fallback behavior omitted } ``` ```javascript function escapeShell(str) { return str.replace(/"/g, '\\"').replace(/\n/g, ' ').replace(/\r/g, ''); } ``` ### Technical Analysis The implementation constructs a shell command by interpolating the filename, extracted document content, summary, and `OPENCLAW_MODEL` environment variable into a string passed to `execSync()`. The `escapeShell()` function only escapes double quotes and removes line breaks. It does not prevent shell expansion constructs such as: - `$(command)` - Backtick command substitution - Shell metacharacters supplied through the unquoted model value - Other shell expansions interpreted inside double-quoted strings Because `prompt` incorporates attacker-controlled filenames and extracted document text, opening a crafted file with `--ai-classify` can cause the shell to evaluate command substitutions before `openclaw` receives the prompt. The `AI_CLASSIFY_CONFIG.model` value is not quoted or validated at all, allowing direct command injection if the environment variable is attacker-controlled. ### Attack Pa ...[truncated 1151 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace shell-string execution with an argument-based API: ```javascript execFileSync('openclaw', [ 'chat', '--prompt', prompt, '--model', AI_CLASSIFY_CONFIG.model, ], { encoding: 'utf-8', timeout: 30000, shell: false, }); ``` 2. Validate model identifiers using a restrictive allowlist, for example: ```javascript if (!/^[A-Za-z0-9._:/-]+$/.test(AI_CLASSIFY_CONFIG.model)) { throw new Error('Invalid model identifier'); } ``` 3. Never rely on custom shell escaping for untrusted document content. 4. Treat filenames and extracted text as hostile data regardless of file origin. 5. Add regression tests using filenames and content containing `$()`, backticks, quotes, semicolons, and control characters. 6. Run optional model integrations in a restricted process with minimum filesystem and network privileges. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
_scripts/archive.mjs:275
Finding
Shell and Python Code Injection in Office Document Extractors<![CDATA[ ## Vulnerability Details **File Location**: `_scripts/archive.mjs`, lines 275-320 **Vulnerability Type**: Command injection and generated-code injection through untrusted file paths **Risk Level**: High ### Vulnerable Code ```javascript function extractExcel(filePath) { const out = execSync(`python3 -c " import openpyxl, json try: wb = openpyxl.load_workbook('${filePath}', data_only=True) lines = [] for sheet in wb.sheetnames: lines.append(f'Sheet: {sheet}') for row in wb[sheet].iter_rows(values_only=True): if any(c for c in row if c): lines.append(' | '.join(str(c) if c else '' for c in row)) print(json.dumps('\\n'.join(lines))) except Exception as e: print(json.dumps(f'Error: {str(e)}')) "`, { encoding: 'utf-8', maxBuffer: 50 * 1024 * 1024 }); return JSON.parse(out.trim()); } ``` ```javascript function extractDocx(filePath) { const out = execSync(`python3 -c " import zipfile, re, json try: with zipfile.ZipFile('${filePath}') as z: doc = z.read('word/document.xml').decode('utf-8') texts = re.findall(r'<w:t[^>]*>([^<]+)</w:t>', doc) print(json.dumps(''.join(texts))) except Exception as e: print(json.dumps(f'Error: {str(e)}')) "`, { encoding: 'utf-8', maxBuffer: 50 * 1024 * 1024 }); return JSON.parse(out.trim()); } ``` ```javascript function extractPptx(filePath) { const out = execSync(`python3 -c " import zipfile, re, json try: with zipfile.ZipFile('${filePath}') as z: slides = sorted([f for f in z.namelist() if f.startswith('ppt/slides/slide') and f.endswith('.xml')]) texts = [] for sf in slides: slide = z.read(sf).decode('utf-8') texts.extend(re.findall(r'<a:t>([^<]+)</a:t>', slide)) print(json.dumps('\\n'.join(texts))) except Exception as e: print(json.dumps(f'Error: {str(e)}')) "`, { encoding: 'utf-8', maxBuffer: 50 * 1024 * 1024 }); return JSON.parse(out.trim()); } ``` ### ...[truncated 1957 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not generate Python source containing the path. 2. Move extraction logic into a fixed Python script and pass the path as an argument: ```javascript execFileSync('python3', [ path.join(__dirname, 'extract_office.py'), filePath, ], { encoding: 'utf-8', maxBuffer: 50 * 1024 * 1024, shell: false, }); ``` 3. In Python, retrieve the path from `sys.argv[1]`; never evaluate it as source code. 4. Prefer maintained Node.js parsing libraries where practical, while pinning and auditing those dependencies. 5. Use `spawn()` or `execFileSync()` with `shell: false` for every subprocess. 6. Add tests covering paths with single and double quotes, dollar signs, backticks, parentheses, Unicode characters, spaces, and newlines. 7. Consider processing untrusted documents in a sandbox with resource limits due to parser-level risks in third-party libraries. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
_scripts/archive.mjs:223
Finding
Potential Disclosure of Document Content to an Arbitrary AI Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `_scripts/archive.mjs`, lines 54-60 and 163-233 **Vulnerability Type**: Sensitive data transmission to an unrestricted configurable endpoint **Risk Level**: Medium ### Vulnerable Code ```javascript const AI_CLASSIFY_CONFIG = { model: process.env.OPENCLAW_MODEL || 'default', apiEndpoint: process.env.OPENCLAW_API_ENDPOINT || null, maxTextLength: 2000, }; ``` ```javascript async function aiClassify(filename, text, summary) { const prompt = `你是一个文件分类助手。请根据以下文件信息判断它应该归类到哪个分类。 文件名: ${filename} 内容摘要: ${summary.substring(0, 500)} 内容片段: ${text.substring(0, AI_CLASSIFY_CONFIG.maxTextLength)} 可选分类: 1. 工作文件 - 数据报表、销售业绩、门店运营、统计分析等 2. 方案文档 - 计划方案、策略规划、制度流程、管理规范等 3. 参考资料 - 话术模板、培训教程、案例经验、指南手册等 4. 其他文档 - 不属于以上分类的文档 请只输出分类名称(工作文件/方案文档/参考资料/其他文档),不要其他内容。`; ``` ```javascript if (!result && AI_CLASSIFY_CONFIG.apiEndpoint) { const response = await fetch(AI_CLASSIFY_CONFIG.apiEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: AI_CLASSIFY_CONFIG.model, messages: [{ role: 'user', content: prompt }], max_tokens: 20, }), }); const data = await response.json(); result = data.choices?.[0]?.message?.content?.trim(); } ``` ### Technical Analysis When AI classification is enabled, the request prompt contains: - The complete filename - Up to 500 characters from the generated summary - Up to 2,000 characters of extracted document content If the `openclaw` command does not return a result and `OPENCLAW_API_ENDPOINT` is configured, this information is sent in an HTTP POST request to the configured URL. The endpoint is accepted without validation. The implementation does not: - Restrict the hostname or protocol - Require HTTPS for non-loopback destinations - Display the destination before transmission - Obtain explicit per-destination consent - Redact secrets or sensitive document fields - Distinguish a trusted local model from ...[truncated 1367 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default AI classification to a local-only mode. 2. Require explicit confirmation before sending document data to any non-loopback endpoint. 3. Validate endpoints using the `URL` API and maintain an allowlist of trusted schemes and hosts. 4. Require HTTPS for remote destinations and reject embedded credentials, redirects to untrusted hosts, and unsupported protocols. 5. Display the destination and the exact categories of data being transmitted. 6. Provide metadata-only classification and configurable redaction options. 7. Detect and remove likely secrets, access tokens, credentials, personal identifiers, and sensitive structured fields before transmission. 8. Log that transmission occurred without recording the sensitive prompt itself. 9. Document retention and privacy expectations for supported remote AI providers. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
_scripts/archive.mjs:353
Finding
Shell Command Injection in Optional Cloud Upload Configuration<![CDATA[ ## Vulnerability Details **File Location**: `_scripts/archive.mjs`, lines 63-71 and 353-366; configuration example in `SKILL.md`, lines 102-108 **Vulnerability Type**: OS command injection through shell-based cloud upload commands **Risk Level**: Medium ### Vulnerable Code ```javascript const CLOUD_STORAGE = { enabled: false, // type: 'cos', // bucket: '', // prefix: 'knowledge-base/', // region: '', // command: (filepath, remotePath) => `coscmd upload "${filepath}" "${remotePath}"`, }; ``` ```javascript function uploadToCloud(filePath, remotePath) { if (!CLOUD_STORAGE.enabled || !CLOUD_STORAGE.command) { console.log(' ☁️ 云存储未配置,跳过上传'); return null; } try { const cmd = CLOUD_STORAGE.command(filePath, remotePath); execSync(cmd, { timeout: 120000 }); return remotePath; } catch (e) { console.error(` ❌ 云上传失败: ${e.message}`); return null; } } ``` The documented configuration pattern is: ```javascript const CLOUD_STORAGE = { enabled: true, type: 'cos', bucket: 'mybucket-1250000000', prefix: 'knowledge-base/', command: (filepath, remotePath) => `coscmd upload "${filepath}" "${remotePath}"`, }; ``` ### Technical Analysis The shipped cloud feature is disabled, which prevents exploitation in the default configuration. However, the documentation explicitly instructs users to enable a callback that returns a shell command string. Both `filePath` and `remotePath` include attacker-influenced filename data. Wrapping these values in double quotes does not prevent shell command substitution, embedded quotes, or other shell interpretation. The resulting command is executed by `execSync()`. The generic command callback also grants cloud configuration unrestricted local command-execution capability, which is broader than the privilege required to upload a file. ### Attack Path 1. An operator enables cloud storage using the documented command callback. 2. An attacker supplies a file larger than 10 MB ...[truncated 843 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove command callbacks that return shell strings. 2. Represent upload tools as a fixed executable and argument list: ```javascript execFileSync('coscmd', [ 'upload', filePath, remotePath, ], { timeout: 120000, shell: false, }); ``` 3. Prefer official cloud-provider SDKs over command-line shell integration. 4. Validate remote object keys and reject control characters. 5. Restrict executable selection to an allowlist rather than accepting arbitrary command functions. 6. Use narrowly scoped cloud credentials limited to the required bucket and prefix. 7. Keep cloud upload disabled until a safe argument-based implementation is configured. ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:127
Finding
Unpinned Dependencies and Unverified Cloud Utility Download<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 127-146 **Vulnerability Type**: Insecure dependency installation and missing artifact integrity verification **Risk Level**: Low ### Vulnerable Code ```bash pip install coscmd ``` ```bash pip install awscli ``` ```bash wget https://gosspublic.alicdn.com/ossutil/1.7.14/ossutil-v1.7.14-linux-amd64.zip ``` ### Technical Analysis The setup instructions install Python packages without exact versions or hashes. Consequently, the code installed by these commands can change after the Skill has been reviewed. The OSS utility is downloaded as a binary archive over HTTPS, but the instructions do not verify a cryptographic checksum or vendor signature. HTTPS protects transport under normal conditions but does not independently establish that the downloaded artifact is the exact version audited or expected by the publisher. No evidence indicates that the named packages or URL are intentionally malicious. The finding concerns insufficient supply-chain controls rather than a confirmed malicious dependency. ### Attack Path 1. A user follows the cloud-storage setup instructions. 2. The package manager resolves an unpinned package version, or the user downloads the utility archive. 3. A compromised package release, repository account, package index, vendor distribution point, or unexpected future version supplies altered code. 4. The package installation or later utility invocation executes that unreviewed code with the user's permissions. ### Impact Assessment A compromised dependency or binary could execute commands with the installing or invoking user's privileges. It could also access cloud credentials configured for COS, AWS, or OSS and perform operations permitted by those credentials. The risk is conditional on users enabling optional cloud integrations and on a supply-chain compromise or unexpected dependency change. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin exact dependency versions. 2. Use hash-verified installation, such as a locked requirements file with approved hashes. 3. Publish the expected SHA-256 digest for every downloaded binary archive. 4. Verify vendor signatures where available. 5. Prefer package repositories and release channels that provide signed metadata. 6. Document supported, reviewed versions and an update-review process. 7. Install optional utilities in an isolated environment and use least-privileged cloud credentials. ]]>
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 (18)

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node _scripts/archive.mjs /path/to/file.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill documents capabilities that rely on environment variables and network access for AI classification and optional cloud uploads, but it does not declare any explicit tool scope or permissions boundary. This can cause users or hosts to underestimate the skill's ability to access configuration secrets and transmit data externally, increasing the risk of unintended data exposure.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill advertises automatic archiving, content extraction, indexing, and optional cloud upload of user files, but it does not provide a prominent upfront warning about copying, indexing, retaining, and potentially transmitting document contents. Because the skill targets bulk processing of office documents, it may handle sensitive business data, making silent storage and transfer behavior especially risky.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The script invokes external shell commands and Python one-liners using file paths and document-derived text, expanding its attack surface beyond simple archiving. This is dangerous because unsafely composed command strings can lead to command injection or unintended code execution, especially where file paths are interpolated into Python snippets or shell commands.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The skill is presented as a local knowledge-base archiver, but its AI classification configuration supports sending document-derived content to an external CLI-backed model or remote API endpoint. This creates a confidentiality risk because sensitive document summaries and excerpts may leave the local environment without a clear, explicit disclosure at the point of use.

Context-Inappropriate Capability

Medium
Confidence
86% confidence
Finding
The optional cloud-upload capability broadens the skill from local archiving into external data transfer, which changes the trust and privacy model. Even if disabled by default, the presence of this path means archived files may be exfiltrated to third-party storage if enabled without sufficient controls or user awareness.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The AI classification path sends file name, summary, and content excerpts to an external or externally mediated model service without an explicit user-facing warning in the workflow. In a document archiving context, this can expose proprietary, personal, or regulated information during classification.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The cloud upload path can transfer archived files outside the local system without an in-band warning at the moment of archival. Because users may expect a local knowledge-base tool to keep documents on-device, this mismatch can lead to accidental disclosure of sensitive files.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The natural-language instructions and description are presented in Chinese only, which can amount to forcing a specific language without offering a choice. The policy allows locale constraints when justified or opt-in is provided, but no such justification or language-selection guidance appears here.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The user-facing description, help text, and command guidance are written entirely in Chinese, including usage examples and status messages. This imposes a language choice on users without any opt-in or alternative locale, which matches the policy's language/locale violation criterion.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
_scripts/archive.mjs:187

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
_scripts/archive.mjs:48