可疑 — 风险评分 40/100
上次扫描:1 天前 重新扫描
40 /100
openclaw-usage-manager
Real-time usage dashboard and auto-switcher for dual Claude Max accounts
This is a legitimate dual-account Claude Max usage manager, but it stores API tokens unencrypted in plaintext files and modifies OpenClaw auth profiles with no declared credentials handling in SKILL.md — a significant doc-to-code mismatch for a credential-accessing tool.
技能名称openclaw-usage-manager
分析耗时61.1s
引擎pi
谨慎使用
SKILL.md must declare filesystem:WRITE for token/auth storage, document the plaintext token persistence model, and explain why unencrypted credentials on disk are acceptable. Consider encrypting tokens.json or referencing a secret manager instead of storing raw Bearer tokens.

安全发现 5 项

严重性 安全发现 位置
高危
API tokens stored in plaintext on disk 凭证窃取
Both setup scripts write raw Bearer tokens (sk-ant-...) to ~/.openclaw/workspace/tools/usage-switch/tokens.json as unencrypted JSON. Even with chmod 600, the tokens are recoverable by any process running as the user. SKILL.md does not document this token storage model.
data = {'c1': os.environ['C1_TOKEN'], 'c2': os.environ['C2_TOKEN']}
with open(path, 'w') as f:
    json.dump(data, f, indent=2)
→ Document the token persistence model in SKILL.md. Consider encrypting tokens.json at rest using a tool like gpg or keychain-access, or rely solely on 1Password CLI retrieval at runtime (do not write tokens to disk).
usage-switch/setup-tokens.sh:17
高危
Undeclared modification of OpenClaw agent auth profiles 凭证窃取
check.mjs reads and rewrites ~/.openclaw/agents/main/agent/auth-profiles.json at runtime to perform account switching. This modifies the agent's active authentication configuration — a sensitive operation — with no declaration in SKILL.md.
auth.profiles['anthropic:default'].token = altToken
writeFileSync(tmpFile, JSON.stringify(auth, null, 2))
renameSync(tmpFile, AUTH_FILE)
→ Declare in SKILL.md that this skill reads and modifies OpenClaw agent auth profiles. This is critical information for users who rely on OpenClaw's own auth security model.
usage-switch/check.mjs:61
中危
SKILL.md does not declare any credential handling, token storage, or auth profile access 文档欺骗
SKILL.md describes a dashboard and auto-switcher but omits all credential operations: reading tokens from 1Password, storing them in tokens.json, and modifying auth-profiles.json. This doc-to-code mismatch is the highest-value security signal in this analysis.
SKILL.md: 'Security-audited: Reviewed by Claude Code + Codex before release' — yet credential access is completely undeclared
→ Add a 'Credential Handling' section to SKILL.md explaining: (1) tokens are read from 1Password or stdin, (2) stored unencrypted in tokens.json with chmod 600, (3) used to read/write auth-profiles.json for account switching.
SKILL.md:1
中危
Undeclared filesystem WRITE to OpenClaw agent directory 权限提升
check.mjs writes to ~/.openclaw/agents/main/agent/auth-profiles.json — a path inside OpenClaw's own agent infrastructure. SKILL.md declares no filesystem access beyond 'browser dashboard'.
const AUTH_FILE = `${process.env.HOME}/.openclaw/agents/main/agent/auth-profiles.json`;
→ Declare filesystem:WRITE for OpenClaw agent config paths in SKILL.md's capability requirements section.
usage-switch/check.mjs:8
低危
Hardcoded placeholder 1Password item IDs in server.mjs 代码混淆
The dashboard server has hardcoded 'your-c1-item-id' and 'your-c2-item-id' placeholders in ACCOUNTS config. While these are clearly documented as placeholders, leaving them in production code with no validation could cause confusing errors.
c1: { label: 'C1', opItemId: 'your-c1-item-id' }
→ Validate that opItemId values are not placeholder strings before invoking op CLI. This is low risk but improves operational robustness.
usage-dashboard/server.mjs:19
资源类型声明权限推断权限状态证据
文件系统 NONE WRITE ✗ 越权 setup-tokens.sh:17 writes to ~/.openclaw/workspace/tools/usage-switch/tokens.jso…
网络访问 NONE READ ✗ 越权 server.mjs:58, check.mjs:28 POST to https://api.anthropic.com/v1/messages using …
命令执行 NONE WRITE ✗ 越权 setup-tokens.sh:1, setup-tokens-simple.sh:1 are shell scripts; server.mjs:148 us…
浏览器 NONE READ ✓ 一致 SKILL.md describes a 'browser dashboard' but browser:READ is not in the declared…
凭证 NONE WRITE ✗ 越权 setup-tokens.sh reads from 1Password CLI (op item get --reveal); check.mjs:65 wr…
环境变量 NONE READ ✓ 一致 setup-tokens.sh:17, setup-tokens-simple.sh:18 pass C1_TOKEN/C2_TOKEN via os.envi…
5 项发现
🔗
中危 外部 URL 外部 URL
https://x.com/5dmgmt/status/2032770037728113118
README.md:18
🔗
中危 外部 URL 外部 URL
https://openclaw.ai
README.md:92
🔗
中危 外部 URL 外部 URL
https://developer.1password.com/docs/cli/
README.md:95
🔗
中危 外部 URL 外部 URL
https://x.com/5dmgmt
README.md:653
🔗
中危 外部 URL 外部 URL
https://5dmgmt.com
README.md:655

目录结构

7 文件 · 49.7 KB · 1333 行
Markdown 2f · 738L JavaScript 2f · 293L HTML 1f · 248L Shell 2f · 54L
├─ 📁 usage-dashboard
│ ├─ 📄 index.html HTML 248L · 8.7 KB
│ └─ 📜 server.mjs JavaScript 210L · 5.8 KB
├─ 📁 usage-switch
│ ├─ 📜 check.mjs JavaScript 83L · 3.1 KB
│ ├─ 🔑 setup-tokens-simple.sh Shell 31L · 1.0 KB
│ └─ 🔑 setup-tokens.sh Shell 23L · 1.3 KB
├─ 📝 README.md Markdown 655L · 27.0 KB
└─ 📝 SKILL.md Markdown 83L · 2.8 KB

依赖分析 2 项

包名版本来源已知漏洞备注
Node.js >= 18 unspecified runtime version runtime No package.json / package-lock.json found — no npm dependencies. Uses only built-in Node.js modules (http, crypto, child_process, fs, url, path)
1Password CLI (op) latest system binary External system binary invoked via execSync. SKILL.md declares '1Password CLI recommended' but does not verify installation. Failure is handled gracefully (returns null token)

安全亮点

✓ All network requests target the legitimate Anthropic API endpoint (api.anthropic.com) — no C2 or exfiltration channels detected
✓ Dashboard server binds to 127.0.0.1 only and implements CSRF token validation — good localhost-only design
✓ Atomic file writes using tmp + renameSync pattern for auth-profiles.json — prevents corruption
✓ tokens.json has chmod 600 applied — mitigates other-user file read risk
✓ External URLs point to a named GitHub repo with a real company (5dmgmt.com) — consistent with a legitimate open-source tool, not typosquatting
✓ setup-tokens.sh passes credentials via environment variables to Python rather than string interpolation — mitigates shell injection
✓ server.mjs uses import.meta.url and path-safe file serving — no path traversal vectors
✓ HTML dashboard uses DOM API (createElement) instead of innerHTML — mitigates XSS
✓ AJAX calls to /api/usage require both CSRF token and localhost origin verification — defense in depth