T09 · Insecure Skill Coding Practices
- Location
scripts/fatsecret-cli.sh:67- Finding
<![CDATA[Arbitrary Python Code Execution Through CLI Argument Interpolation]]>
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill fits a FatSecret nutrition and diary workflow, but it needs Review because crafted CLI input can execute Python and the skill stores and exposes long-lived account credentials unsafely.
Install only if you are comfortable giving the skill FatSecret account access and storing long-lived tokens locally. Before use, fix the CLI interpolation bug, stop printing or returning token secrets, restrict credential-file permissions, pin dependencies, and treat diary logging as an account-write capability that should require explicit user confirmation.
scripts/fatsecret-cli.sh:67<![CDATA[Arbitrary Python Code Execution Through CLI Argument Interpolation]]>
scripts/fatsecret_agent_helper.py:56<![CDATA[Long-Lived OAuth Credentials Stored Without Enforced Restrictive Permissions]]>
scripts/fatsecret_auth.py:157<![CDATA[OAuth Token Secrets Disclosed Through Standard Output and Agent Return Values]]>
requirements.txt:1<![CDATA[Unpinned, Redundant, and Incomplete Dependency Declaration]]>
The skill claims broad nutrition features but the documented implementation focuses on loading OAuth credentials, using proxies, and making authenticated requests. When sensitive behaviors are more prominent than the public description indicates, users may unknowingly authorize a skill with materially greater privacy and account-access implications than expected.
The skill claims broad nutrition features but the documented implementation focuses on loading OAuth credentials, using proxies, and making authenticated requests. When sensitive behaviors are more prominent than the public description indicates, users may unknowingly authorize a skill with materially greater privacy and account-access implications than expected.
The skill claims broad nutrition features but the documented implementation focuses on loading OAuth credentials, using proxies, and making authenticated requests. When sensitive behaviors are more prominent than the public description indicates, users may unknowingly authorize a skill with materially greater privacy and account-access implications than expected.
The skill claims broad nutrition features but the documented implementation focuses on loading OAuth credentials, using proxies, and making authenticated requests. When sensitive behaviors are more prominent than the public description indicates, users may unknowingly authorize a skill with materially greater privacy and account-access implications than expected.
The skill claims broad nutrition features but the documented implementation focuses on loading OAuth credentials, using proxies, and making authenticated requests. When sensitive behaviors are more prominent than the public description indicates, users may unknowingly authorize a skill with materially greater privacy and account-access implications than expected.
The skill explicitly stores consumer secrets and OAuth access tokens on local disk, including long-lived OAuth1 tokens. Local token persistence is dangerous because any other process, compromised agent, shared container, backup system, or misconfigured volume with read access to that directory can steal credentials and gain ongoing access to the user's FatSecret account and diary data.
| File | Contents | Created By |
|------|----------|------------|
| `$CONFIG_DIR/config.json` | Consumer Key/Secret | User (manual) |
| `$CONFIG_DIR/oauth1_access_tokens.json` | OAuth1 access tokens | `auth` command |
| `$CONFIG_DIR/token.json` | OAuth2 token (auto-refreshed) | OAuth2 client |
Where `$CONFIG_DIR` is `~/.config/fatsecret` by default, or the value of `FATSECRET_CONFIG_DIR` if set.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
#!/usr/bin/env python3
"""
Simple OAuth1 3-legged authentication script for FatSecret.
Guides the user step-by-step to obtain access tokens.
"""
import json
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
#!/usr/bin/env python3
"""
Simple OAuth1 3-legged authentication script for FatSecret.
Guides the user step-by-step to obtain access tokens.
"""
import json
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
#!/usr/bin/env python3
"""
Simple OAuth1 3-legged authentication script for FatSecret.
Guides the user step-by-step to obtain access tokens.
"""
import json
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
#!/usr/bin/env python3
"""
Simple OAuth1 3-legged authentication script for FatSecret.
Guides the user step-by-step to obtain access tokens.
"""
import json
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
#!/usr/bin/env python3
"""
Simple OAuth1 3-legged authentication script for FatSecret.
Guides the user step-by-step to obtain access tokens.
"""
import json
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
return auth_url
def step3_get_access_token(consumer_key, consumer_secret, oauth_token, oauth_token_secret):
"""Step 3: Get access token with PIN."""
print("\n" + "="*60)
print("STEP 3: Getting Access Token")
print("="*60)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
return auth_url
def step3_get_access_token(consumer_key, consumer_secret, oauth_token, oauth_token_secret):
"""Step 3: Get access token with PIN."""
print("\n" + "="*60)
print("STEP 3: Getting Access Token")
print("="*60)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
return auth_url
def step3_get_access_token(consumer_key, consumer_secret, oauth_token, oauth_token_secret):
"""Step 3: Get access token with PIN."""
print("\n" + "="*60)
print("STEP 3: Getting Access Token")
print("="*60)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
return auth_url
def step3_get_access_token(consumer_key, consumer_secret, oauth_token, oauth_token_secret):
"""Step 3: Get access token with PIN."""
print("\n" + "="*60)
print("STEP 3: Getting Access Token")
print("="*60)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def step3_get_access_token(consumer_key, consumer_secret, oauth_token, oauth_token_secret):
"""Step 3: Get access token with PIN."""
print("\n" + "="*60)
print("STEP 3: Getting Access Token")
print("="*60)
# Ask user for PIN
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
access_token_secret = response_params.get("oauth_token_secret")
if not access_token or not access_token_secret:
print("❌ Access tokens not received!")
return None, None
print(f"✅ Access Token: {access_token}")
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
access_token_secret = response_params.get("oauth_token_secret")
if not access_token or not access_token_secret:
print("❌ Access tokens not received!")
return None, None
print(f"✅ Access Token: {access_token}")
The script prints the OAuth access token to stdout, which can expose credentials through terminal scrollback, shell history capture tools, CI logs, remote session logging, or shared support transcripts. In the context of an authentication utility, displaying live bearer-equivalent secrets materially increases the chance of credential compromise.
print("❌ Access tokens not received!")
return None, None
print(f"✅ Access Token: {access_token}")
print(f"✅ Access Token Secret: {access_token_secret}")
return access_token, access_token_secret
The script prints the access token secret to stdout, exposing a credential component required for OAuth1 request signing. Leakage of this secret, especially alongside the token and consumer credentials stored elsewhere in the script, can allow unauthorized API access on behalf of the user.
return None, None
print(f"✅ Access Token: {access_token}")
print(f"✅ Access Token Secret: {access_token_secret}")
return access_token, access_token_secret
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# Pause to let user authorize
input("\nPress ENTER when you have authorized the app and have the PIN...")
# Step 3: Access token
access_token, access_token_secret = step3_get_access_token(
consumer_key, consumer_secret, oauth_token, oauth_token_secret
)
The implementation materially differs from the declared skill purpose: it routes nutrition lookups to Open Food Facts instead of the FatSecret integration promised by the manifest. In an agent setting, this is dangerous because it can bypass expected provider constraints, data provenance, authentication, and user trust boundaries, causing the agent to call an unintended third-party service and return mismatched or lower-assurance data.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Get credentials from https://platform.fatsecret.com
mkdir -p ~/.config/fatsecret
cat > ~/.config/fatsecret/config.json << EOF
{
"consumer_key": "YOUR_KEY",
The skill documentation describes capabilities that require environment access, local file writes, shell execution, and outbound network access, but it does not declare any explicit tool scope or permission boundaries. In an agent setting, missing scope declarations can cause the skill to be invoked with broader privileges than reviewers or users expect, increasing the chance of credential handling, persistence, and network behavior occurring without adequate guardrails.
The authentication section says the skill supports OAuth2 for read-only access and OAuth1 for full access, but the changelog later states OAuth2 was removed and OAuth1 is now used for all operations. Security-sensitive documentation contradictions can cause agents or operators to choose a weaker review path, assume lower privilege, or mis-handle tokens and consent flows.
No suspicious patterns detected.