Suspicious — Risk Score 45/100
Last scan:1 day ago Rescan
45 /100
calendar_memo
本地日程记事本 - 添加、查看、完成和删除待办事项和日程安排
Skill executes undeclared shell commands via child_process.exec and runs persistent background timers without proper documentation disclosure.
Skill Namecalendar_memo
Duration46.9s
Enginepi
Use with caution
Add explicit documentation about shell execution, background processes, and required network permissions. Consider using a safer IPC mechanism instead of exec() for inter-process communication.

Attack Chain 4 steps

Entry Skill loaded via SKILL.md documentation describing only local scheduling features
SKILL.md:1
Escalation onStart() triggers startReminderChecker() which creates persistent setInterval
SOUL.md:44
Escalation Every 60 seconds, checkReminders() builds command string with user-controlled title
reminder.js:35
Impact exec() executes 'openclaw message send' through system shell with potentially unsanitized input
reminder.js:18

Findings 4 items

Severity Finding Location
High
Undeclared shell command execution Priv Escalation
The skill uses child_process.exec() to execute 'openclaw message send' but SKILL.md only mentions '飞书等通道' (Feishu channels) without explaining the shell execution mechanism. Users cannot make informed decisions about allowing this skill.
exec(cmd, (error, stdout, stderr) => {...})
→ Document shell:WRITE permission and explain that the skill executes external CLI commands for notifications.
reminder.js:18
Medium
Shell command injection risk in notification function RCE
The sendPushNotification function builds a shell command by interpolating user-controlled event title into a command string. While only double quotes are escaped, other shell metacharacters could potentially be dangerous if the message format changes.
const cmd = `openclaw message send --channel feishu --recipient current --text "${messageText.replace(/"/g, '\\"')}"`
→ Use an array-based exec() API or proper argument escaping via a library like shell-quote instead of string interpolation.
reminder.js:14
Medium
Hidden background daemon without disclosure Persistence
The skill starts a setInterval timer that runs checkReminders() every 60 seconds. This creates a persistent background process that continues running until skill is explicitly stopped. SKILL.md does not mention this behavior.
intervalId = setInterval(() => { checkReminders(); }, 60 * 1000);
→ Document that the skill runs background checks and the interval frequency. Allow users to configure or disable reminder checking.
reminder.js:55
Low
Minor doc-to-code mismatch on filesystem permissions Doc Mismatch
SKILL.md capability section mentions '读取和编辑MEMORY.md' (read and edit) but only declares filesystem:READ. The code writes to MEMORY.md using writeFileSync.
fs.writeFileSync(MEMORY_FILE, JSON.stringify(events, null, 2), 'utf8');
→ Update SKILL.md to declare filesystem:WRITE permission.
SOUL.md:13
ResourceDeclaredInferredStatusEvidence
Filesystem READ WRITE ✓ Aligned reminder.js:3 - fs module available; SOUL.md:13 - fs.writeFileSync writes MEMORY…
Shell NONE WRITE ✗ Violation reminder.js:4 - const { exec } = require('child_process'); reminder.js:18 - exec…
Network NONE WRITE ✗ Violation reminder.js:18 - exec runs 'openclaw message send --channel feishu' which sends …
Environment NONE NONE No direct environment variable access found

File Tree

4 files · 11.3 KB · 363 lines
Markdown 3f · 279L JavaScript 1f · 84L
├─ 📝 MEMORY.md Markdown 1L · 2 B
├─ 📜 reminder.js JavaScript 84L · 2.3 KB
├─ 📝 SKILL.md Markdown 52L · 1.9 KB
└─ 📝 SOUL.md Markdown 226L · 7.1 KB

Security Positives

✓ No credential harvesting or sensitive data exfiltration detected
✓ No base64 encoding, eval(), or obfuscation techniques found
✓ No network requests to unknown external IPs
✓ Data stays local in MEMORY.md without transmission
✓ User input is processed through structured parsing rather than eval()