Low Risk — Risk Score 10/100
Last scan:2 days ago Rescan
10 /100
run-coach
Science-based running coach with HD visual training plans and Garmin sync
A legitimate running coach skill with well-documented capabilities. All external network access (Telegram Bot API, Garmin Connect) is declared. No hidden functionality, credential theft, or malicious patterns detected.
Skill Namerun-coach
Duration45.8s
Enginepi
Safe to install
Pin the garminconnect library version in SKILL.md to avoid unexpected breakage. Consider explicitly declaring browser:READ for the Playwright-based screenshot pipeline.

Findings 3 items

Severity Finding Location
Low
Playwright dependency not declared
The screenshot pipeline in screenshot.mjs uses playwright-core (and chrome-headless-shell) but SKILL.md only lists 'node' as a required binary. This is a minor doc gap — the browser usage is indirectly declared via the exec-based image pipeline instructions.
import { chromium } from '/app/node_modules/playwright-core/index.mjs';
→ Add 'playwright-core' and 'chrome-headless-shell' to the SKILL.md anyBins list under step 4.
training/screenshot.mjs:1
Low
garminconnect version not pinned
SKILL.md instructs 'pip install garminconnect' without a version constraint. An unversioned pip install could pull a breaking change in the future.
pip install garminconnect
→ Pin the version, e.g., 'pip install garminconnect==2024.12.0' or equivalent.
SKILL.md:77
Info
Telegram bot credentials transmitted to external API
TELEGRAM_BOT_TOKEN is sent in the URL path to api.telegram.org. This is normal and expected for a Telegram bot skill — not credential exfiltration.
const API = `https://api.telegram.org/bot${botToken}`;
→ No action needed — this is the standard Telegram Bot API usage.
training/send-album.mjs:18
ResourceDeclaredInferredStatusEvidence
Filesystem READ WRITE ✓ Aligned SKILL.md: 'pip install garminconnect'; garmin-sync.py writes to garmin/activitie…
Network READ READ ✓ Aligned SKILL.md declares Telegram bot and Garmin Connect usage; send-album.mjs:18 POSTs…
Shell WRITE WRITE ✓ Aligned SKILL.md instructs agent to use exec/bash for training/text-to-image.sh and node…
Environment READ READ ✓ Aligned SKILL.md declares GARMIN_EMAIL, GARMIN_PASSWORD, TELEGRAM_BOT_TOKEN, TELEGRAM_CH…
Browser NONE READ ✓ Aligned screenshot.mjs uses Playwright/chrome-headless-shell to screenshot HTML, used vi…
2 findings
🔗
Medium External URL 外部 URL
https://api.telegram.org/bot$
training/send-album.mjs:18
📧
Info Email 邮箱地址
[email protected]
garmin/garmin-sync.py:37

File Tree

8 files · 31.6 KB · 920 lines
Python 2f · 473L Markdown 2f · 228L JavaScript 2f · 116L Shell 2f · 103L
├─ 📁 garmin
│ ├─ 🐍 garmin-query.py Python 217L · 7.2 KB
│ └─ 🐍 garmin-sync.py Python 256L · 8.4 KB
├─ 📁 training
│ ├─ 📜 screenshot.mjs JavaScript 51L · 1.7 KB
│ ├─ 📜 send-album.mjs JavaScript 65L · 2.5 KB
│ ├─ 🔧 send-plan.sh Shell 45L · 1.4 KB
│ └─ 🔧 text-to-image.sh Shell 58L · 2.5 KB
├─ 📝 MEMORY.md Markdown 44L · 1.4 KB
└─ 📝 SKILL.md Markdown 184L · 6.5 KB

Dependencies 2 items

PackageVersionSourceKnown VulnsNotes
garminconnect * pip No Version not pinned — minor maintenance risk
playwright-core * npm No Assumed pre-installed in /app/node_modules/; not explicitly listed in SKILL.md

Security Positives

✓ All shell execution (bash, node -e) is explicitly declared in SKILL.md agent instructions
✓ Telegram Bot API is the only external network destination — no suspicious IPs or URLs
✓ Garmin Connect is a known, legitimate third-party API — not a hidden exfiltration channel
✓ Garmin credentials are used only for Garmin Connect authentication and immediately discarded
✓ No base64 encoding, obfuscation, eval(), or dynamic code generation patterns
✓ No access to ~/.ssh, ~/.aws, .env, or other sensitive host paths
✓ Playwright uses chrome-headless-shell (not full Chrome), avoiding unnecessary attack surface
✓ Token caching uses .garth file in workspace — not credential stores
✓ All file writes are scoped to the skill's own garmin/ and training/ directories