Back to skill

Security audit

0602-tosr2-01

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but its optional Twitter/X scanners ask for browser session credentials and pass the full local environment to a third-party CLI.

Install only if you are comfortable with a finance skill making external requests for tickers and portfolio holdings. Avoid the optional Twitter/X setup unless you use a dedicated low-risk account, do not store broad secrets in the skill .env, and review or modify the scanners so only AUTH_TOKEN and CT0 are passed to bird. Treat BUY/HOLD/SELL output as informational, not personalized investment advice.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/hot_scanner.py:22
Finding

Third-Party Twitter CLI Receives the Complete Process Environment

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/hot_scanner.py:22-30
  • scripts/hot_scanner.py:387-391
  • scripts/rumor_scanner.py:30-38
  • scripts/rumor_scanner.py:79-81
  • scripts/rumor_scanner.py:132-134

Vulnerability Type: Excessive exposure of environment variables to a third-party subprocess
Risk Level: Medium

Vulnerable Code

scripts/hot_scanner.py:22-30:

python
# 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:
            line = line.strip()
            if line and not line.startswith("#") and "=" in line:
                key, value = line.split("=", 1)
                os.environ[key] = value

scripts/hot_scanner.py:387-391:

python
env = os.environ.copy()
result = subprocess.run(
    [bird_bin, "search", query, "-n", "15", "--json"],
    capture_output=True, text=True, timeout=30, env=env
)

scripts/rumor_scanner.py:30-38:

python
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('#'):
                key, value = line.split('=', 1)
                os.environ[key.strip()] = value.strip().strip('"').strip("'")

scripts/rumor_scanner.py:79-81:

python
env = os.environ.copy()

result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, env=env)

scripts/rumor_scanner.py:132-134:

python
env = os.environ.copy()

result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, env=env)

Technical Analysis

Both scanners load every key found in the project-level .env file into the global process environment. They then copy the complete environment and provide it to ...[truncated 2004 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not load arbitrary .env entries into global os.environ.
  2. Parse only explicitly permitted keys, such as AUTH_TOKEN and CT0.
  3. Construct a minimal subprocess environment rather than copying the parent environment:
python
allowed_env = {
    "PATH": os.environ.get("PATH", ""),
    "HOME": os.environ.get("HOME", ""),
    "LANG": os.environ.get("LANG", "C.UTF-8"),
    "AUTH_TOKEN": auth_token,
    "CT0": ct0,
}

subprocess.run(
    [bird_bin, "search", query, "-n", "15", "--json"],
    capture_output=True,
    text=True,
    timeout=30,
    env=allowed_env,
    check=False,
)
  1. Validate .env key names and reject duplicate or unexpected entries.
  2. Keep Twitter credentials in a dedicated credential store or dedicated configuration file with owner-only permissions rather than a general-purpose project .env.
  3. Resolve bird from an explicitly configured, trusted project-local path and verify the expected version before execution.
  4. Run the social-media integration in a restricted subprocess or container with limited filesystem and network access.
  5. Document precisely which credentials are disclosed to the Twitter integration.

T08 · Insecure Dependencies

Warning
Location
README.md:142
Finding

Unpinned Runtime Dependencies Create a Mutable Supply-Chain Boundary

Content
View full analysis

Vulnerability Details

File Locations:

  • README.md:142-150
  • SKILL.md:152-154
  • scripts/analyze_stock.py:2-10
  • scripts/dividends.py:2-8
  • scripts/portfolio.py:2-5
  • scripts/watchlist.py:2-7

Vulnerability Type: Unpinned third-party packages installed or resolved at runtime
Risk Level: Medium

Vulnerable Code and Instructions

README.md:142-150:

markdown
### Twitter/X Setup (Optional)

1. Install bird CLI: `npm install -g @steipete/bird`
2. Login to x.com in Safari/Chrome
3. Create `.env` file:

AUTH_TOKEN=your_auth_token CT0=your_ct0_token

text

scripts/analyze_stock.py:2-10:

python
# /// script
# requires-python = ">=3.10"
# dependencies = [
#     "yfinance>=0.2.40",
#     "pandas>=2.0.0",
#     "fear-and-greed>=0.4",
#     "edgartools>=2.0.0",
#     "feedparser>=6.0.0",
# ]
# ///

The other executable scripts similarly declare open-ended lower-bound dependencies, including yfinance>=0.2.40, without an audited lockfile or package hashes.

Technical Analysis

The documented npm command installs the latest available version of @steipete/bird globally. The Python scripts use PEP 723 dependency declarations with minimum versions but no upper bounds, exact versions, lockfile, or integrity hashes.

Consequently, running the same documented command at different times can retrieve different code than the code considered during this audit. This is particularly sensitive for bird: it receives Twitter session credentials and, under the current scanner implementation, the complete process environment.

No evidence was found that the named dependencies are currently malicious. The vulnerability is the mutable and insufficiently constrained supply-chain trust boundary, not a confirmed malicious package.

Attack Path

  1. A dependency publisher account, package release process, or upstream distribution channel is compromised, or a f ...[truncated 1183 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin all dependencies to exact, reviewed versions.
  2. Commit and enforce a lockfile generated by the chosen package manager.
  3. Use package hashes or integrity metadata where supported.
  4. Replace the global npm installation with a project-local dependency:
bash
npm install --save-exact @steipete/bird@REVIEWED_VERSION
  1. Invoke the project-local executable through an explicit trusted path rather than searching global locations or relying on PATH.
  2. Pin Python dependencies to exact versions and use a locked uv environment.
  3. Run automated vulnerability and provenance checks before dependency upgrades.
  4. Require review and testing whenever the lockfile changes.
  5. Isolate the Twitter client with a minimal environment, restricted filesystem access, and only the network destinations required for its declared operation.
  6. Avoid granting third-party dependencies access to credentials unrelated to their specific function.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (58)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

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).

Content

Scanner excerpt · App-Plan.md (reported line 114)May include surrounding context.

md
GET  /portfolios
   POST /portfolios
   PUT  /portfolios/{id}
   DELETE /portfolios/{id}

   GET  /portfolios/{id}/assets
   POST /portfolios/{id}/assets

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

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).

Content

Scanner excerpt · App-Plan.md (reported line 119)May include surrounding context.

md
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 Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

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).

Content

Scanner excerpt · App-Plan.md (reported line 126)May include surrounding context.

md
GET  /alerts
   POST /alerts
   DELETE /alerts/{id}

   GET  /user/subscription
   POST /user/subscription/upgrade

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

A second, distinct description-behavior mismatch indicates undeclared external data sources and subprocess invocation of the bird CLI for Twitter/X scraping, while core claimed features such as portfolio, watchlists, dividends, and 8-dimension scoring are reportedly absent. Hidden dependency on external scraping tools materially changes the risk profile by introducing extra code execution, authentication handling, and outbound access not clearly disclosed in the stated purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

A second, distinct description-behavior mismatch indicates undeclared external data sources and subprocess invocation of the bird CLI for Twitter/X scraping, while core claimed features such as portfolio, watchlists, dividends, and 8-dimension scoring are reportedly absent. Hidden dependency on external scraping tools materially changes the risk profile by introducing extra code execution, authentication handling, and outbound access not clearly disclosed in the stated purpose.

Content

No source excerpt is available for this finding.

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

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.

Content

Scanner excerpt · TODO.md (reported line 88)May include surrounding context.

md
- [ ] 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

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

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.

Content

Scanner excerpt · TODO.md (reported line 193)May include surrounding context.

md
- [ ] 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

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

The documentation recommends placing sensitive session credentials in a project .env file inside the skill directory. In agent-skill and automation contexts, local .env files are commonly exposed via accidental commits, artifact collection, backup sync, or broader workspace access, making this a practical credential exposure risk rather than a theoretical one.

Content

Scanner excerpt · docs/HOT_SCANNER.md (reported line 149)May include surrounding context.

Create .env file in the skill directory:

bash
# /path/to/stock-analysis/.env
AUTH_TOKEN=your_auth_token_here
CT0=your_ct0_token_here

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/hot_scanner.py (reported line 22)May include surrounding context.

python
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:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/hot_scanner.py (reported line 23)May include surrounding context.

python
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:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
98% confidence
Finding

Copying the full environment into a child process is a real credential-exposure risk because environment variables often contain tokens, API keys, proxy credentials, or cloud secrets. In this file the risk is amplified by passing them to an external CLI discovered from the filesystem/PATH rather than a tightly controlled internal component.

Content

Scanner excerpt · scripts/hot_scanner.py (reported line 387)May include surrounding context.

python
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

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

Referencing and loading a repository-adjacent .env file for credentials is not inherently malicious, but in this context it contributes to credential access and later exposure to an external process. The danger comes from treating the .env as a bulk source of secrets without scoping or safeguards.

Content

Scanner excerpt · scripts/rumor_scanner.py (reported line 30)May include surrounding context.

python
# 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."""

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The code path that reads all lines from .env and imports key-value pairs into the environment is a concrete credential-access mechanism. In isolation this can be normal configuration handling, but combined with subprocess environment forwarding it creates a meaningful risk of credential overexposure.

Content

Scanner excerpt · scripts/rumor_scanner.py (reported line 33)May include surrounding context.

python
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('#'):

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
93% confidence
Finding

Copying the full process environment after loading .env secrets and handing it to a subprocess is a real secret-exposure pattern. Even if the Bird CLI is intended to use one token, the child receives every environment variable available, which can leak unrelated credentials to third-party code or logs.

Content

Scanner excerpt · scripts/rumor_scanner.py (reported line 79)May include surrounding context.

python
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)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
93% confidence
Finding

This repeats the same broad environment propagation issue in the second Bird CLI invocation path. The pattern is dangerous because it unnecessarily expands credential exposure across every CLI execution, increasing blast radius if the binary or its ecosystem is untrusted.

Content

Scanner excerpt · scripts/rumor_scanner.py (reported line 132)May include surrounding context.

python
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)

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes a stock/crypto analysis skill with portfolio tracking, alerts, and related market features. This document explicitly repositions it as a commercial mobile product with user authentication, monetization, cloud hosting, and app distribution, which materially broadens the intended behavior beyond a skill focused on financial analysis.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest mentions analysis, watchlists, alerts, and portfolio features, but does not mention handling payments or subscription lifecycle events. Adding Stripe integration and webhook-driven account tier changes introduces a separate commerce function not implied by the skill description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The document proposes product analytics and error tracking but does not mention user-facing notice, consent, or disclosure around telemetry collection. In a financial-analysis app that may process portfolio and behavioral data, undisclosed analytics can expose sensitive user information, create compliance risk, and undermine user trust.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly instructs users to obtain AUTH_TOKEN and CT0 session cookies from browser developer tools and store them in a .env file. These are sensitive authentication artifacts; encouraging manual extraction and local storage without strong warnings, scoping guidance, or safer alternatives increases the risk of account takeover, unintended disclosure, and misuse of personal social media sessions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The manifest documents commands that invoke Python and shell tooling, access the network, and persist data locally, yet it does not declare any explicit tool scope or permissions. This weakens security review and user consent because the skill's effective capabilities are broader than what the manifest transparently communicates.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill instructs users to install a third-party CLI and place Twitter/X authentication secrets in a local .env file for social scraping, even though that capability is not essential to a Yahoo-Finance-centered stock analysis skill. This expands the attack surface by encouraging credential handling and external-tool execution, creating risk of secret exposure, account misuse, or overcollection from social platforms.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation presents the tool as producing clear BUY / HOLD / SELL signals, which are plainly actionable trading recommendations, while later disclaiming that it is not providing trading signals. This contradiction can mislead users about the nature of the output, reduce appropriate caution, and create unsafe reliance on automated financial recommendations in a high-risk domain.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation instructs users to obtain live Twitter/X session credentials from browser cookies and store them locally, but provides no warning about the sensitivity of those tokens or the risks of account takeover if they are exposed. Session cookies like auth_token and ct0 can grant direct access to the user's X account, so normalizing their manual extraction and reuse increases the chance of credential leakage or unsafe handling.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file explicitly tells users to copy live X/Twitter authentication cookies from browser developer tools and store them in a .env file or environment variables. This is dangerous because those values are effectively reusable session secrets; if leaked through shell history, logs, backups, repo commits, or local compromise, an attacker may hijack the user's account without needing a password or MFA.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script performs multiple network lookups to third-party services, including Yahoo Finance, Google News RSS, and SEC/EDGAR tooling, without a clear upfront disclosure that user-supplied tickers and portfolio contents may be transmitted externally. In a portfolio-analysis context, this can expose sensitive investment interests or holdings metadata to outside providers, creating a privacy and data-governance risk even if no malicious behavior is present.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.