T09 · Insecure Skill Coding Practices
- Location
scripts/refresh_token.sh:13- Finding
Unvalidated OAuth Token Endpoint Permits Credential Exfiltration and SSRF
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill’s Granola meeting-note access is coherent, but its token refresh script handles sensitive OAuth credentials with unsafe endpoint trust and response handling that should be reviewed before use.
Install only if you trust the publisher and are comfortable granting access to private Granola meeting data. Before use, hardcode or allowlist the Granola token endpoint, avoid interpolating token values into Python source, restrict credential files to the owning user, and avoid enabling the optional cron refresh until those issues are fixed.
scripts/refresh_token.sh:13Unvalidated OAuth Token Endpoint Permits Credential Exfiltration and SSRF
scripts/refresh_token.sh:28OAuth Response Fields Are Interpolated into Python Source, Enabling Code Injection
The skill explicitly handles OAuth secrets and instructs execution of a shell script that reads refresh tokens, contacts a token endpoint, and rewrites credential-bearing config files. Even though this is intended functionality, it creates a credential-handling pathway with shell execution and secret persistence, which is high risk if logs, files, subprocess arguments, or broader agent capabilities are exposed or misused.
bash {baseDir}/scripts/refresh_token.sh
The script reads `config/granola_oauth.json`, posts to the token endpoint (`https://mcp-auth.granola.ai/oauth2/token`), and updates both `config/granola_oauth.json` and `config/mcporter.json` with the new access token.
Then retry the call. If refresh also fails, the user needs to re-authenticate manually via the OAuth flow above.
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
REFRESH_TOKEN=$(python3 -c "import json; print(json.load(open('$OAUTH_FILE'))['refresh_token'])")
TOKEN_ENDPOINT=$(python3 -c "import json; print(json.load(open('$OAUTH_FILE'))['token_endpoint'])")
RESPONSE=$(curl -s -X POST "$TOKEN_ENDPOINT" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=${REFRESH_TOKEN}&client_id=${CLIENT_ID}")
The skill declares shell and file-write capable behavior but does not define any explicit tool scope or permission boundary. That makes it easier for an agent runtime to invoke powerful actions implicitly, including running token-refresh scripts and modifying local config files, which increases the blast radius if the skill is triggered unexpectedly or influenced by untrusted input.
The activation guidance is broad enough that the skill may be invoked for generic meeting-related requests, even when the user did not clearly intend access to Granola data. In context, this matters because the skill can query sensitive meeting notes and transcripts, so over-triggering can expose private organizational information unnecessarily.
The script reads the token endpoint from a local JSON file and posts the refresh token to that URL without validating that it is an expected trusted HTTPS endpoint. If an attacker can tamper with granola_oauth.json, they can redirect the request to an attacker-controlled server and exfiltrate the refresh token, which may enable long-lived unauthorized access to meeting data.
REFRESH_TOKEN=$(python3 -c "import json; print(json.load(open('$OAUTH_FILE'))['refresh_token'])")
TOKEN_ENDPOINT=$(python3 -c "import json; print(json.load(open('$OAUTH_FILE'))['token_endpoint'])")
RESPONSE=$(curl -s -X POST "$TOKEN_ENDPOINT" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=${REFRESH_TOKEN}&client_id=${CLIENT_ID}")
This shell script updates both granola_oauth.json and mcporter.json with fresh bearer credentials, which is a safety-relevant file write involving sensitive authentication data. While comments describe the behavior for developers, there is no user-facing disclosure, prompt, or explicit warning before modifying these files.
No suspicious patterns detected.