T09 · Insecure Skill Coding Practices
- Location
src/setup.js:17- Finding
OAuth secrets and sensitive health records are stored without restrictive filesystem permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a transparent WHOOP data helper, but it stores OAuth tokens and health history locally, so users should protect those files.
Install only if you are comfortable granting WHOOP read scopes and keeping OAuth tokens plus health metrics in local JSON files. Use this on a trusted single-user machine, restrict permissions on ~/.clawdbot/whoop and ~/clawd/health/logs/whoop, avoid entering tokens in recorded/shared terminals, and revoke WHOOP tokens or delete local logs if you stop using it.
src/setup.js:17OAuth secrets and sensitive health records are stored without restrictive filesystem permissions
src/auth.js:385OAuth callback reflects unescaped query parameters into an HTML response
Error: ${error}
` + (errorDescription ? `Description: ${errorDescription}
` : '') + (errorHint ? `Hint: ${errorHint}
` : '') + `Check the terminal for details.
` ); console.error(`\n❌ Authorization error: ${error}`); if (errorDescription) console.error(` Description: ${errorDescription}`); if (errorHint) console.error(` Hint: ${errorHint}`); server.close(); resolve(false); return; } ``` The listener is started without an explicit loopback address at `src/auth.js:438`: ```js server.listen(LISTEN_PORT, () => { ``` ### Technical Analysis The callback handler obtains `error`, `error_description`, and `error_hint` directly from request query parameters and interpolates them into an HTML response without context-appropriate escaping. An attacker can supply HTML elements or script content in these parameters, causing the browser to interpret the injected value as markup. The error branch is evaluated before the OAuth `state` comparison. Consequently, an attacker does not need to know the randomly generated OAuth state to reach the vulnerable rendering logic. The server also calls `listen()` without specifying a host. Depending on the Node.js and operating-system network configuration, this can bind to an unspecified address rather than exclusively to loopback. That increases exposure during the five-minute authentication window, particularly on shared or untrusted networks. No evidence shows that this origin directly exposes the stored token or credentials. Therefore, the demonstrated impact is constrained to script execution in ...[truncated 1484 chars]This skill description emphasizes data retrieval, but the setup instructions prominently collect and store client credentials and OAuth tokens on disk. Undisclosed local secret storage is risky because operators may enable the skill without realizing it persists sensitive authentication material.
This skill description emphasizes data retrieval, but the setup instructions prominently collect and store client credentials and OAuth tokens on disk. Undisclosed local secret storage is risky because operators may enable the skill without realizing it persists sensitive authentication material.
The skill explicitly writes credentials to ~/.clawdbot/whoop/credentials.json, which strongly suggests persistent local storage of secrets. Plain filesystem storage of client credentials is dangerous because other local users, backups, logs, or misconfigured permissions may expose them.
# 1) One-time setup (writes ~/.clawdbot/whoop/credentials.json)
node src/setup.js
# 2) Recommended: Get tokens via Postman (see Auth section), then verify
Referenced artifact was not completely inspected
node src/setup.js
Referenced artifact was not completely inspected
node src/setup.js
Referenced artifact was not completely inspected
node src/verify.js
Referenced artifact was not completely inspected
node src/verify.js
Referenced artifact was not completely inspected
node src/verify.js
Referenced artifact was not completely inspected
node src/verify.js
Referenced artifact was not completely inspected
node src/verify.js
Referenced artifact was not completely inspected
node src/today.js
Referenced artifact was not completely inspected
node src/summary.js
Referenced artifact was not completely inspected
node src/summary.js
Referenced artifact was not completely inspected
node src/summary.js
Referenced artifact was not completely inspected
node src/recovery.js
Referenced artifact was not completely inspected
node src/recovery.js
Referenced artifact was not completely inspected
node src/recovery.js
Referenced artifact was not completely inspected
node src/sleep.js
Referenced artifact was not completely inspected
node src/sleep.js
Referenced artifact was not completely inspected
node src/sleep.js
Referenced artifact was not completely inspected
node src/strain.js
Referenced artifact was not completely inspected
node src/strain.js
Referenced artifact was not completely inspected
node src/workouts.js
Referenced artifact was not completely inspected
node src/workouts.js
Referenced artifact was not completely inspected
node src/workouts.js
Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.potential_exfiltration