安全决策报告

wip-xai-grok

Skill executes undeclared shell commands via 1Password CLI to resolve credentials without declaring shell:WRITE permission in SKILL.md, creating a doc-to-code mismatch on the most sensitive operation.

安装决策优先 来源: 手动上传 扫描时间: 2026/4/4
文件 10
IOC 10
越权项 2
发现 4
最直接的威胁证据
高危 权限提升
Undeclared shell:WRITE via 1Password CLI execSync

The resolveApiKey() function uses Node.js execSync to execute 'op read "op://Agent Secrets/X API/api key"', which is a shell command. This provides shell:WRITE capability but is not declared anywhere in SKILL.md's capabilities, metadata.dependencies, or allowed-tools mapping. The SKILL.md metadata shows dependencies: [] but the code has an implicit dependency on the 1Password CLI binary (op). While the README.md mentions this, SKILL.md is the canonical capability declaration and is silent on this.

core.mjs:28

为什么得出这个结论

2/4 个维度触发
阻止
声明与实际能力

发现 2 项声明之外的能力或越权行为。

复核
隐藏执行与外联

提取到 10 个一般风险产物,需要结合上下文判断。

阻止
攻击链与高危发现

报告包含 0 步攻击链,另有 1 项高危或严重发现。

复核
依赖与供应链卫生

发现 1 项需要关注的依赖或供应链线索。

风险分是怎么被拉高的

Undeclared shell execution +25

core.mjs:28 uses execSync to call 'op read' CLI (1Password) for credential resolution. This is shell:WRITE access not declared in SKILL.md capabilities or metadata.dependencies

Credential access via CLI subprocess +15

The 1Password CLI integration reads secrets from a password manager, but the execSync call itself is undeclared shell access that could be swapped for arbitrary commands

SKILL.md declares zero dependencies but code uses exec +10

SKILL.md metadata shows 'dependencies: []' yet core.mjs imports node:child_process for shell execution

Local file read for image editing undeclared +5

edit_image() silently reads local files and base64-encodes them (core.mjs:252-258). SKILL.md describes image editing as URL-only without mentioning local filesystem access

最关键的证据

高危 权限提升

Undeclared shell:WRITE via 1Password CLI execSync

The resolveApiKey() function uses Node.js execSync to execute 'op read "op://Agent Secrets/X API/api key"', which is a shell command. This provides shell:WRITE capability but is not declared anywhere in SKILL.md's capabilities, metadata.dependencies, or allowed-tools mapping. The SKILL.md metadata shows dependencies: [] but the code has an implicit dependency on the 1Password CLI binary (op). While the README.md mentions this, SKILL.md is the canonical capability declaration and is silent on this.

core.mjs:28
Declare the 1Password CLI dependency in SKILL.md metadata.dependencies or switch to environment-variable-only credential resolution. If 1Password is intentional, document it explicitly as a required binary dependency.
中危 文档欺骗

SKILL.md declares zero dependencies but code requires 1Password CLI

SKILL.md metadata shows 'dependencies: []' and the skill is described as requiring only XAI_API_KEY. However, the implementation silently requires the 'op' (1Password CLI) binary to be installed. The 1Password path 'op://Agent Secrets/X API/api key' is hardcoded with no fallback notice to the user. If 1Password is unavailable and XAI_API_KEY is not set, the error message is opaque.

SKILL.md:12
Update metadata.dependencies to include 'op (1Password CLI)' if the 1Password integration is intentional, or remove the execSync entirely and rely only on environment variable resolution.
中危 敏感访问

Silent local filesystem read in edit_image undeclared in docs

edit_image() accepts image file paths (not just URLs) and silently reads them from disk using readFileSync, base64-encodes them, and sends to the xAI API (core.mjs:252-258). SKILL.md describes edit_image as requiring a 'URL or base64 data URI' but never mentions that local file paths are also silently accepted and read. The function has filesystem:READ access that is neither declared in capabilities nor documented in the function description.

core.mjs:252
Document in SKILL.md that edit_image accepts local file paths as images, not just URLs. Declare filesystem:READ in the capability map for this skill.
低危 文档欺骗

process.env cached with the actual API key value

resolveApiKey() caches the retrieved 1Password secret into process.env.XAI_API_KEY (core.mjs:33), meaning subsequent calls won't need the execSync but the key will live in the environment. This is a minor info-leak risk if the process memory is exposed.

core.mjs:33
Be aware that caching API keys in process.env makes them accessible via inspection of the process environment. This is standard practice but worth noting.

声明能力 vs 实际能力

网络访问 通过
声明 READ
推断 READ
core.mjs - all functions call https://api.x.ai/* for legitimate xAI API access
命令执行 阻止
声明 NONE
推断 WRITE
core.mjs:28 - execSync('op read "op://Agent Secrets/X API/api key"')
文件系统 阻止
声明 NONE
推断 READ
core.mjs:252-258 - edit_image reads local file paths and base64-encodes them
环境变量 通过
声明 NONE
推断 READ
core.mjs:25 - reads XAI_API_KEY from process.env
技能调用 通过
声明 NONE
推断 NONE
No self-invocation detected

可疑产物与外联

中危 外部 URL
https://console.x.ai/

README.md:29

中危 外部 URL
https://clawhub.ai/castanley/grok

README.md:122

中危 外部 URL
https://clawhub.ai

README.md:122

中危 外部 URL
https://api.x.ai/v1

SKILL.md:8

中危 外部 URL
https://docs.x.ai/developers/tools/web-search

SKILL.md:141

中危 外部 URL
https://docs.x.ai/developers/tools/x-search

SKILL.md:142

中危 外部 URL
https://docs.x.ai/docs/guides/image-generations

SKILL.md:143

中危 外部 URL
https://docs.x.ai/docs/guides/video-generations

SKILL.md:144

中危 外部 URL
https://opencollective.com/express

package-lock.json:137

中危 外部 URL
https://opencollective.com/fastify

package-lock.json:448

依赖与供应链

包名版本来源漏洞备注
@modelcontextprotocol/sdk ^1.27.1 npm Version loosely pinned with caret. Contains no known vulnerabilities at this version.
op (1Password CLI) any system binary Not declared in package.json or SKILL.md. Implicit runtime dependency for credential resolution.

文件构成

10 个文件 · 2243 行
JSON 2 个文件 · 1183 行JavaScript 3 个文件 · 733 行Markdown 5 个文件 · 327 行
需关注文件 · 4
package-lock.json JSON · 1142 行
https://opencollective.com/express · https://opencollective.com/fastify
core.mjs JavaScript · 389 行
Undeclared shell:WRITE via 1Password CLI execSync · Silent local filesystem read in edit_image undeclared in docs · process.env cached with the actual API key value
SKILL.md Markdown · 144 行
SKILL.md declares zero dependencies but code requires 1Password CLI · https://api.x.ai/v1 · https://docs.x.ai/developers/tools/web-search · https://docs.x.ai/developers/tools/x-search · https://docs.x.ai/docs/guides/image-generations · https://docs.x.ai/docs/guides/video-generations
README.md Markdown · 130 行
https://console.x.ai/ · https://clawhub.ai/castanley/grok · https://clawhub.ai
其他文件 · cli.mjs · mcp-server.mjs · CHANGELOG.md · package.json · RELEASE-NOTES-v1-0-3.md · PUNCHLIST.md

安全亮点

All network requests go to legitimate, declared xAI API endpoints (api.x.ai) only
No obfuscation detected — no base64 eval, no dynamic code generation, no anti-analysis patterns
No credential exfiltration — the 1Password read is only used locally to obtain the API key for xAI
No remote code execution or reverse shell patterns present
No access to sensitive paths like ~/.ssh, ~/.aws, or .env files beyond the declared XAI_API_KEY
No hidden instructions in HTML comments or documentation
Package.json has version-pinned dependencies (except SDK peer deps resolved by host)
Input validation present (max limits on domains, handles, image count, etc.)
No data exfiltration — all API calls are to the legitimate xAI service
No supply-chain concerns — @modelcontextprotocol/sdk is a well-known, widely-used package