T09 · Insecure Skill Coding Practices
- Location
scripts/ripe-scan.py:783- Finding
Predictable Shared Temporary Cache Allows Local Cache Poisoning and Symlink Attacks
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real market-scanning skill, but it needs review because it claims local/no-key operation while making third-party network requests, optionally using a Tavily API key, and writing an unsafe shared cache.
Install only if you are comfortable with the skill contacting market and sentiment services, sending ticker interests to third parties, and using TAVILY_API_KEY for Tavily-backed Reddit sentiment when that environment variable exists. Prefer running it in a dedicated environment, avoid sudo, review or disable the /tmp cache on shared systems, and treat its output as informational rather than financial advice.
scripts/ripe-scan.py:783Predictable Shared Temporary Cache Allows Local Cache Poisoning and Symlink Attacks
SKILL.md:15Unpinned Third-Party Dependencies Create Supply-Chain Exposure
scripts/ripe-scan.py:231Documentation Misrepresents Tavily Credential and Data-Disclosure Requirements
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
try:
url = f"https://api.stocktwits.com/api/2/streams/symbol/{clean_sym}.json"
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
resp = json.loads(urllib.request.urlopen(req, timeout=10).read())
messages = resp.get('messages', [])
if not messages:
return None
The code reads TAVILY_API_KEY from the environment and includes it in a JSON body sent to an external service. While this is expected for authenticating to Tavily, it still transmits a secret off-host without explicit user-facing disclosure, and any compromise or misuse of that endpoint could expose or abuse the credential. In this skill context, outbound use of ambient credentials is more sensitive because the manifest presents a scanner and the header claims 'fully local computation'.
}).encode()
req = urllib.request.Request('https://api.tavily.com/search', data=data,
headers={'Content-Type': 'application/json'})
resp = json.loads(urllib.request.urlopen(req, timeout=10).read())
posts = resp.get('results', [])
if not posts:
return None
The skill advertises command execution that uses network access, reads environment-dependent paths, and writes persistent files, but it does not declare any tool scope or permissions boundaries. This weakens auditability and consent, because an agent may invoke a skill with broader capabilities than the user expects, including outbound requests and disk writes.
The trigger phrases are broad enough to match many generic investing or market questions, increasing the chance this skill is auto-selected when the user did not intend to run a networked, file-writing scanner. Overbroad routing is dangerous because it can cause unnecessary execution of code with side effects and expose user workflows to unintended external data access.
The markdown states that daily snapshots and signal logs are stored persistently under the workspace memory path, but it does not prominently warn the user before enabling retention. Persistent writes can create privacy, storage, and data governance issues, especially if users do not realize market activity history and generated logs are being accumulated over time.
The docstring claims 'Zero API cost, fully local computation,' but the implementation fetches data from Wikipedia, Yahoo Finance, StockTwits, and optionally Tavily. This mismatch is a security-relevant transparency issue because users may authorize the skill under false assumptions about data locality and network exposure. Misrepresentation increases risk in an agent setting where users rely on manifests and descriptions to judge trust boundaries.
The code contradicts its own claim of local-only operation by relying on remote services and an environment API key for Tavily. This is dangerous because it obscures both external data flows and credential use, undermining informed consent and safe deployment decisions. In a skill marketplace context, inaccurate declarations are especially problematic because they can bypass user scrutiny.
This code sends ticker symbols to StockTwits, creating an external data flow that is not clearly disclosed to users. The transmitted data is low sensitivity, but it still leaks user interest or queried assets to a third party and conflicts with the claim of local-only operation. In context, this is more of a privacy/transparency issue than a severe exploit path.
# Skip crypto tickers on StockTwits (different format)
clean_sym = symbol.replace('-USD', '.X') if '-USD' in symbol else symbol
try:
url = f"https://api.stocktwits.com/api/2/streams/symbol/{clean_sym}.json"
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
resp = json.loads(urllib.request.urlopen(req, timeout=10).read())
messages = resp.get('messages', [])
This request transmits both query content and an API key-backed request to Tavily, exposing the user's looked-up symbols and relying on a third-party service. The main risk is undisclosed external transmission coupled with credential use; if the remote service is compromised or logs are mishandled, both usage metadata and secret-backed access may be affected. The mismatch with the advertised local behavior makes this more concerning.
'search_depth': 'basic',
'max_results': 10
}).encode()
req = urllib.request.Request('https://api.tavily.com/search', data=data,
headers={'Content-Type': 'application/json'})
resp = json.loads(urllib.request.urlopen(req, timeout=10).read())
posts = resp.get('results', [])
The skill persists snapshots and signal logs under the user's workspace and home directory, creating longer-lived local state than the description suggests. Persistent storage is not inherently malicious, but undisclosed retention can expose trading interests, usage history, and derived analytics to other local processes, backups, or later agents with filesystem access.
The script creates cache and history files in /tmp and the user's home workspace without a clear warning. Although the stored content is not highly sensitive by default, it can reveal watchlists, scan behavior, signal history, and timestamps, which may matter in multi-user or shared-agent environments. The issue is primarily undisclosed persistence rather than direct code execution or exfiltration.
The skill silently reads an environment API key and uses it in an outbound request path, without explicit disclosure in the interface or description. Even though using a key for API access is normal, undisclosed consumption of ambient credentials is risky in agent ecosystems because users may not expect a 'free' scanner to leverage existing secrets. The danger is increased by the misleading 'fully local' claim.