T09 · Insecure Skill Coding Practices
- Location
scripts/hot_scanner.py:22- Finding
Hot Scanner Forwards the Complete Process Environment to a Third-Party Executable
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly a coherent stock-analysis tool, but its optional X/Twitter scanners ask users to handle browser session tokens and pass broad environment secrets to an external CLI.
Review before installing if you plan to use Hot Scanner or Rumor Scanner with X/Twitter. Avoid granting Terminal Full Disk Access, do not store reusable browser session cookies in a repo or shared skill directory, and run the social scanners only with a minimal environment and a trusted pinned bird installation. The core stock, portfolio, watchlist, and dividend features are purpose-aligned but still send ticker and portfolio-interest data to external financial/news services.
scripts/hot_scanner.py:22Hot Scanner Forwards the Complete Process Environment to a Third-Party Executable
scripts/rumor_scanner.py:30Rumor Scanner Exposes All Inherited and Project Secrets to the Bird CLI
docs/HOT_SCANNER.md:122Security-Sensitive Third-Party Components Are Installed and Executed Without Reproducible Version Pinning
docs/HOT_SCANNER.md:132Setup Guidance Requests Excessive Terminal Permissions and Plaintext Browser Session Tokens
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
GET /portfolios
POST /portfolios
PUT /portfolios/{id}
DELETE /portfolios/{id}
GET /portfolios/{id}/assets
POST /portfolios/{id}/assets
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
GET /portfolios/{id}/assets
POST /portfolios/{id}/assets
PUT /portfolios/{id}/assets/{ticker}
DELETE /portfolios/{id}/assets/{ticker}
GET /portfolios/{id}/performance?period=weekly
GET /portfolios/{id}/summary
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
GET /alerts
POST /alerts
DELETE /alerts/{id}
GET /user/subscription
POST /user/subscription/upgrade
This mismatch matters because the skill claims a narrower Yahoo-Finance-style analysis purpose while also referencing additional external sources and an external CLI for Twitter/X searches. Hidden or under-declared subprocess and network dependencies can cause users or host systems to authorize execution they would not have approved if the real behavior were disclosed.
This mismatch matters because the skill claims a narrower Yahoo-Finance-style analysis purpose while also referencing additional external sources and an external CLI for Twitter/X searches. Hidden or under-declared subprocess and network dependencies can cause users or host systems to authorize execution they would not have approved if the real behavior were disclosed.
This mismatch matters because the skill claims a narrower Yahoo-Finance-style analysis purpose while also referencing additional external sources and an external CLI for Twitter/X searches. Hidden or under-declared subprocess and network dependencies can cause users or host systems to authorize execution they would not have approved if the real behavior were disclosed.
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.
- [ ] Add timeout per indicator (10s max)
- [ ] Test with multiple stocks in sequence
- [ ] Measure actual runtime improvement
- [ ] Update SKILL.md with new runtime (target: 3-4s)
**Expected Impact**:
- Reduce runtime from 6-10s to 3-4s per stock
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.
- [ ] Add timeout per indicator (10s max)
- [ ] Test with multiple stocks in sequence
- [ ] Measure actual runtime improvement
- [ ] Update SKILL.md with new runtime (target: 3-4s)
**Expected Impact**:
- Reduce runtime from 6-10s to 3-4s per stock
The example explicitly tells users to store live X/Twitter authentication tokens in a .env file within the skill directory. Even though .env files are common, placing session credentials in the project tree without strong safeguards can lead to accidental exposure through source control, backups, logs, shared workspaces, or other tooling, potentially enabling account takeover or unauthorized API actions.
Create .env file in the skill directory:
# /path/to/stock-analysis/.env
AUTH_TOKEN=your_auth_token_here
CT0=your_ct0_token_here
Directly targeting a repository-local .env file is credential access behavior because such files commonly store API keys and tokens. In this skill, that access is broader than necessary and feeds into later subprocess inheritance, making the context more dangerous than routine configuration loading.
from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor, as_completed
# Load .env file if exists
ENV_FILE = Path(__file__).parent.parent / ".env"
if ENV_FILE.exists():
with open(ENV_FILE) as f:
The code conditionally opens and parses .env, which exposes local secrets to the process even before determining whether they are needed. Because the skill also launches an external program later, this credential access meaningfully increases risk of unintended disclosure.
from concurrent.futures import ThreadPoolExecutor, as_completed
# Load .env file if exists
ENV_FILE = Path(__file__).parent.parent / ".env"
if ENV_FILE.exists():
with open(ENV_FILE) as f:
for line in f:
The skill goes beyond passive data analysis by invoking an external CLI to access Twitter/X. That adds code execution and dependency trust risks not inherent to stock scanning, and in this file the subprocess also receives inherited environment variables, increasing the blast radius if the helper tool is compromised or misconfigured.
os.environ.copy() captures the full runtime environment, including secrets loaded from .env and any host-provided tokens, and passes them to the external bird process. This is classic overexposure of credentials across a trust boundary and can lead to secret theft if the binary is malicious, vulnerable, or simply logs its environment.
for category, query in searches:
try:
env = os.environ.copy()
result = subprocess.run(
[bird_bin, "search", query, "-n", "15", "--json"],
capture_output=True, text=True, timeout=30, env=env
Referencing a repository-adjacent .env for runtime credential loading is not automatically malicious, but in combination with external subprocess execution it becomes a genuine credential exposure concern. The pattern increases risk because secrets are centrally collected from a local file and then made available to the rest of the script and child processes.
# Bird CLI path
BIRD_CLI = "/home/clawdbot/.nvm/versions/node/v24.12.0/bin/bird"
BIRD_ENV = Path(__file__).parent.parent / ".env"
def load_env():
"""Load environment variables from .env file."""
The code actively reads and imports entries from a .env file into environment variables, which is a form of credential access. While that may be operationally convenient, it creates avoidable exposure because secrets are loaded into process-wide state and later inherited by external commands.
BIRD_ENV = Path(__file__).parent.parent / ".env"
def load_env():
"""Load environment variables from .env file."""
if BIRD_ENV.exists():
for line in BIRD_ENV.read_text().splitlines():
if '=' in line and not line.startswith('#'):
Copying the full parent environment and passing it into an external CLI can expose all available secrets, tokens, and infrastructure settings to that subprocess. In this skill, the danger is elevated because the script explicitly loads a local .env first, so credentials unrelated to rumor scanning may be handed to the Bird binary unnecessarily.
for query in queries[:4]: # Limit to avoid rate limits
try:
cmd = [BIRD_CLI, 'search', query, '-n', '10', '--json']
env = os.environ.copy()
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, env=env)
This second environment copy repeats the same risky pattern: all environment variables are inherited by an external command without minimization. If the child process, its dependencies, or logs are compromised, unrelated credentials from the host environment may be disclosed.
for query in queries[:3]:
try:
cmd = [BIRD_CLI, 'search', query, '-n', '15', '--json']
env = os.environ.copy()
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, env=env)
This markdown file describes product analytics tooling such as Mixpanel/Amplitude and error tracking with Sentry, which can collect usage and diagnostic data affecting user privacy. While the document includes a generic privacy-policy note elsewhere, it does not warn users in the feature description that app usage and telemetry may be collected.
The README instructs users to manually extract Twitter/X session cookies (AUTH_TOKEN and CT0) from browser DevTools and store them in a local .env file. These values are effectively session secrets, and exposing or mishandling them can allow account takeover or unauthorized access to the user's X account, especially because the guidance lacks strong warnings about scope, storage, rotation, and safer alternatives.
The skill advertises command execution, network access, and local file storage but does not declare any explicit tool scope or permission boundaries. In agent environments, missing scope declarations increase the chance the skill runs with broader privileges than users expect, enabling unintended shell, network, or filesystem actions.
The markdown instructs users to create a .env file containing authentication tokens for Twitter/X integration without clearly warning that these are sensitive credentials. In a skill that also uses shell, filesystem, and external tooling, encouraging local plaintext secret storage without handling guidance increases the risk of accidental exposure through logs, repository commits, backups, or other tooling.
The documentation instructs users to obtain browser-derived X/Twitter session credentials and place them into a local .env file, but it does not clearly warn that these values are effectively sensitive session tokens that can enable account access if leaked. Encouraging manual cookie extraction and local storage of auth material increases the chance of credential mishandling, accidental commit, token theft, or privacy compromise.
The script sends user-supplied tickers and derived market/news queries to third-party services including Yahoo Finance, Google News RSS, and SEC EDGAR without clear user-facing disclosure or consent. In a portfolio-analysis context, this can expose sensitive investment interests, watchlists, or positions to external providers, creating a privacy and data-handling risk.
The module docstring and CLI text describe Yahoo Finance-based stock analysis, but the code also fetches Google News RSS for crisis headlines and queries SEC EDGAR Form 4 filings to analyze insider activity. These are not obvious implementation details of a narrowly documented Yahoo Finance analyzer because they introduce additional external data sources and broader market-intelligence behavior.
The file is documented as 'Stock analysis using Yahoo Finance data' and its CLI description says 'Analyze stocks using Yahoo Finance data', but the code also loads named portfolios, reads holdings with quantities and cost basis, computes total portfolio value/P&L, concentration warnings, and period returns. Those are materially broader operations than per-ticker analysis and are not reflected in this file's own description/documentation.
No suspicious patterns detected.