低风险 — 风险评分 20/100
上次扫描:1 天前 重新扫描
20 /100
x-bookmark-triage
Automatically triages X/Twitter bookmarks into structured knowledge cards posted to a Discord channel using Claude Haiku scoring
Legitimate bookmark-triage pipeline with documented network access and OAuth token handling, but shell execution via spawnSync(curl) is not declared in SKILL.md and docs reference persona-specific identifiers.
技能名称x-bookmark-triage
分析耗时56.6s
引擎pi
可以安装
Add spawnSync/shell usage to SKILL.md capabilities section, replace 'Watson'/'Jeremy' persona references in adapting.md, and declare the markdown.new web proxy fetch in the skill description.

安全发现 4 项

严重性 安全发现 位置
低危
Shell execution not declared in SKILL.md 文档欺骗
SKILL.md describes a bookmark-triage pipeline but does not disclose that all HTTP I/O uses spawnSync('curl') and spawnSync('sleep') — shell:WRITE operations. The README documents this, but SKILL.md is the authoritative skill manifest.
const res = spawnSync('curl', ['-s', '--max-time', '10', apiUrl]);
→ Add a Capabilities section to SKILL.md: 'Uses subprocess (spawnSync) for HTTP requests and delays. Uses Node.js built-in https for Anthropic API calls.'
scripts/triage-url.js:70
低危
Undocumented markdown.new web proxy 文档欺骗
SKILL.md describes fetching 'tweet content via fxtwitter' for tweets but does not mention that non-tweet web URLs are fetched via https://markdown.new/ — a proxy service for converting web pages to markdown.
const fetchUrl = `https://markdown.new/${encodeURIComponent(url)}`;
→ Add 'Web pages → markdown.new proxy' to the fetch description in SKILL.md.
scripts/triage-url.js:90
低危
Persona cleanup required before deployment 文档欺骗
references/adapting.md contains a '⚠️ Before You Start: Remove Persona References' warning telling users to replace 'Watson', 'Jeremy', and '@jeremyknowsvf'. This indicates a template was published with hardcoded identity markers that could confuse users or leak context.
If you see references to 'Watson', 'Jeremy', or '@jeremyknowsvf' in any script, replace with your own identity.
→ Remove all persona-specific references from published files. The SKILL.md already uses generic terminology, but the adapting.md warning suggests they exist elsewhere.
references/adapting.md:3
低危
No npm dependencies — pure Node.js, no lock file 供应链
The skill uses zero npm packages (only Node.js built-ins: child_process, fs, path, https, http, crypto, url). This eliminates supply-chain risk but means no package-lock.json to audit.
No package.json found — pure Node.js with built-in modules only
→ No action needed. Pure stdlib is a positive security trait.
package.json
资源类型声明权限推断权限状态证据
文件系统 NONE WRITE ✓ 一致 scripts/triage-url.js:37 — writes SEEN_FILE to WORKSPACE/data/
网络访问 NONE READ ✓ 一致 spawnSync('curl') calls to X API, Discord API, fxtwitter, Anthropic, markdown.ne…
命令执行 NONE WRITE ✓ 一致 spawnSync('curl') and spawnSync('sleep') used in all JS scripts — shell:WRITE no…
环境变量 NONE READ ✓ 一致 Reads X_OAUTH2_*, ANTHROPIC_DEFAULT_KEY, DISCORD_BOT_TOKEN, etc. — legitimately …
17 项发现
🔗
中危 外部 URL 外部 URL
https://developer.x.com
README.md:28
🔗
中危 外部 URL 外部 URL
https://discord.com/developers/applications
README.md:32
🔗
中危 外部 URL 外部 URL
https://console.anthropic.com
README.md:35
🔗
中危 外部 URL 外部 URL
https://x.com/someone/status/123
README.md:59
🔗
中危 外部 URL 外部 URL
https://x.com/...
README.md:81
🔗
中危 外部 URL 外部 URL
https://x.com/anthropic/status/...
README.md:128
🔗
中危 外部 URL 外部 URL
https://x.com/@username/status/1234567890
SKILL.md:55
🔗
中危 外部 URL 外部 URL
http://www.apple.com/DTDs/PropertyList-1.0.dtd
references/cron-setup.md:31
🔗
中危 外部 URL 外部 URL
https://x.com/i/oauth2/authorize?...
references/oauth-setup.md:34
🔗
中危 外部 URL 外部 URL
https://api.x.com/2/users/me
references/oauth-setup.md:73
🔗
中危 外部 URL 外部 URL
https://api.x.com/2/oauth2/token
scripts/backlog-sweep.js:71
🔗
中危 外部 URL 外部 URL
https://api.x.com/2/users/$
scripts/backlog-sweep.js:112
🔗
中危 外部 URL 外部 URL
https://discord.com/api/v10/channels/$
scripts/poll-channel.js:47
🔗
中危 外部 URL 外部 URL
https://nodejs.org
scripts/setup-check.js:27
🔗
中危 外部 URL 外部 URL
https://api.fxtwitter.com/$
scripts/triage-url.js:70
🔗
中危 外部 URL 外部 URL
https://markdown.new/$
scripts/triage-url.js:90
🔗
中危 外部 URL 外部 URL
https://twitter.com/i/oauth2/authorize
scripts/x-oauth2-authorize.js:45

目录结构

13 文件 · 73.6 KB · 2103 行
JavaScript 6f · 1308L Markdown 5f · 751L Shell 1f · 23L Text 1f · 21L
├─ 📁 references
│ ├─ 📝 adapting.md Markdown 126L · 4.3 KB
│ ├─ 📝 cron-setup.md Markdown 96L · 2.8 KB
│ └─ 📝 oauth-setup.md Markdown 79L · 2.6 KB
├─ 📁 scripts
│ ├─ 📜 backlog-sweep.js JavaScript 305L · 11.8 KB
│ ├─ 📜 bookmark-poll.js JavaScript 270L · 9.2 KB
│ ├─ 📜 poll-channel.js JavaScript 123L · 4.1 KB
│ ├─ 🔧 run-poll.sh Shell 23L · 990 B
│ ├─ 📜 setup-check.js JavaScript 84L · 2.2 KB
│ ├─ 📜 triage-url.js JavaScript 360L · 12.6 KB
│ └─ 📜 x-oauth2-authorize.js JavaScript 166L · 5.4 KB
├─ 📄 LICENSE.txt Text 21L · 1.1 KB
├─ 📝 README.md Markdown 218L · 7.7 KB
└─ 📝 SKILL.md Markdown 232L · 8.8 KB

安全亮点

✓ No external npm dependencies — eliminates supply-chain attack surface entirely
✓ OAuth tokens stored with 0o600 permissions (owner-only read/write) in backlog-sweep.js and x-oauth2-authorize.js
✓ Secrets file path uses a parent-directory traversal pattern (../../../secrets/) but only accessed if X_OAUTH2_SECRETS_FILE env is set
✓ Token values are never printed to stdout (only file path on rotation)
✓ No eval(), no base64 decode, no obfuscation, no anti-analysis patterns
✓ No access to ~/.ssh, ~/.aws, .env (only skill-scope data files and env vars explicitly named for this skill)
✓ Dedup mechanism prevents re-processing already-seen URLs
✓ Rate-limit handling implemented for both X API and Discord API
✓ Dry-run mode available for backlog-sweep to test without side effects
✓ No hardcoded credentials — all secrets from environment variables