Back to skill

Security audit

Yahoo Fantasy Baseball

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to read Yahoo Fantasy Baseball data and make roster suggestions as advertised, but it stores Yahoo OAuth tokens locally and installs a Python dependency during setup.

Install only if you are comfortable giving the skill Yahoo Fantasy API access and storing OAuth tokens under ~/.openclaw/credentials/yahoo-fantasy/. Run --setup in a normal unprivileged account, and treat the dependency install like any other Python package installation because transitive packages are not hash-verified.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T08 · Insecure Dependencies

Warning
Location
yahoo-fantasy-baseball.py:27
Finding
Dependency installation without artifact integrity verification## Vulnerability Details **File Location**: `yahoo-fantasy-baseball.py:27-35`; `requirements.txt:1` **Vulnerability Type**: Unverified third-party dependency installation **Risk Level**: Medium The explicit `--setup` operation creates a virtual environment and installs a third-party package from the configured Python package index: ```python def _bootstrap_venv(): """Create a local venv and install requirements.""" print("Installing dependencies...", file=sys.stderr) # Create venv subprocess.check_call( [sys.executable, "-m", "venv", _VENV_DIR], stdout=sys.stderr, stderr=sys.stderr, ) # Install requirements into the venv pip_cmd = [_VENV_PYTHON, "-m", "pip", "install", "-q", "-r", _REQUIREMENTS] subprocess.check_call(pip_cmd, stdout=sys.stderr, stderr=sys.stderr) ``` The dependency manifest contains: ```text yahoo_fantasy_api==2.12.2 ``` ### Technical Analysis The direct dependency is version-pinned, which prevents unintended version upgrades, but neither the package artifact nor its transitive dependencies are protected by cryptographic hashes. The installation therefore trusts the configured pip index, its resolved artifacts, and the complete transitive dependency graph. Python package installation can execute package build logic, while imported dependency code subsequently executes with the same operating-system privileges as the Skill. In this project, the installed Yahoo API and OAuth libraries also receive access to the Yahoo OAuth session and the credential file under `~/.openclaw/credentials/yahoo-fantasy/`. No evidence establishes that `yahoo_fantasy_api==2.12.2` is currently malicious. The confirmed issue is the absence of artifact integrity verification and a fully locked transitive dependency set, leaving a supply-chain compromise capable of changing the code that executes during setup or runtime. ### Attack Path 1. An attacker ...[truncated 1382 chars]
Remediation
## Remediation Suggestions 1. Generate a fully resolved lock file containing exact versions and SHA-256 hashes for the direct package and every transitive dependency. 2. Install with hash enforcement, for example: ```python pip_cmd = [ _VENV_PYTHON, "-m", "pip", "install", "--require-hashes", "-r", _REQUIREMENTS, ] ``` 3. Resolve and review dependencies in a controlled build process rather than dynamically resolving transitive versions on end-user systems. 4. Use an explicitly configured, trusted package index and disable unintended additional indexes. 5. Audit the dependency tree and monitor pinned packages for security advisories and ownership or release anomalies. 6. Consider distributing a signed, reproducibly built environment or verified wheel bundle instead of downloading executable package artifacts during setup. 7. Run setup and normal Skill execution as an unprivileged user, and avoid exposing unrelated credentials in the process environment.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

Credential Access

High
Category
Privilege Escalation
Content
CLAUDE.md                   — This file
  yahoo-fantasy-baseball.py   — Entry point (--setup for deps, fail-fast if missing)
  requirements.txt            — yahoo_fantasy_api dependency
  .gitignore                  — .deps/, __pycache__, .env
  scripts/
    fantasy.py                — Main CLI (argparse subcommands)
    yahoo_api.py              — yahoo-fantasy-api wrapper: auth, config, league/team construction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
CLAUDE.md                   — This file
  yahoo-fantasy-baseball.py   — Entry point (--setup for deps, fail-fast if missing)
  requirements.txt            — yahoo_fantasy_api dependency
  .gitignore                  — .deps/, __pycache__, .env
  scripts/
    fantasy.py                — Main CLI (argparse subcommands)
    yahoo_api.py              — yahoo-fantasy-api wrapper: auth, config, league/team construction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
CLAUDE.md                   — This file
  yahoo-fantasy-baseball.py   — Entry point (--setup for deps, fail-fast if missing)
  requirements.txt            — yahoo_fantasy_api dependency
  .gitignore                  — .deps/, __pycache__, .env
  scripts/
    fantasy.py                — Main CLI (argparse subcommands)
    yahoo_api.py              — yahoo-fantasy-api wrapper: auth, config, league/team construction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
CLAUDE.md                   — This file
  yahoo-fantasy-baseball.py   — Entry point (--setup for deps, fail-fast if missing)
  requirements.txt            — yahoo_fantasy_api dependency
  .gitignore                  — .deps/, __pycache__, .env
  scripts/
    fantasy.py                — Main CLI (argparse subcommands)
    yahoo_api.py              — yahoo-fantasy-api wrapper: auth, config, league/team construction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
CLAUDE.md                   — This file
  yahoo-fantasy-baseball.py   — Entry point (--setup for deps, fail-fast if missing)
  requirements.txt            — yahoo_fantasy_api dependency
  .gitignore                  — .deps/, __pycache__, .env
  scripts/
    fantasy.py                — Main CLI (argparse subcommands)
    yahoo_api.py              — yahoo-fantasy-api wrapper: auth, config, league/team construction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
CLAUDE.md                   — This file
  yahoo-fantasy-baseball.py   — Entry point (--setup for deps, fail-fast if missing)
  requirements.txt            — yahoo_fantasy_api dependency
  .gitignore                  — .deps/, __pycache__, .env
  scripts/
    fantasy.py                — Main CLI (argparse subcommands)
    yahoo_api.py              — yahoo-fantasy-api wrapper: auth, config, league/team construction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
A documented read-only fantasy assistant that materially misrepresents what the implementation actually does creates a trust and transparency failure. Users may authorize Yahoo credentials or run setup commands under false assumptions, and agents may invoke the skill for sensitive account tasks even though the described league-access and optimization behavior is not actually implemented as claimed.

Memory Manipulation

High
Category
Memory Poisoning
Content
```

Three analysis categories:
1. **Lineup changes** — optimal batter assignment via constraint solver (position-aware, fills restrictive slots before UTIL). Outputs grouped swap instructions showing who starts (from bench), who gets benched, and any intermediate position reshuffles needed within that chain (e.g., a UTIL player sliding to 1B to make room). Pure position shuffles among active slots (without bench involvement) are omitted. Also checks confirmed MLB batting lineups — players confirmed not in their team's lineup are treated as unavailable (score 0) and will be moved to bench. Players whose games have already started are locked in place (Yahoo locks roster slots at first pitch) and excluded from the solver.
2. **Pitcher rotation** — priority-based pitcher slot optimization with swap suggestions. Relief pitchers whose teams are playing today are prioritized over non-starting SPs or pitchers whose teams are off. Probable starters get highest priority. Outputs grouped swap instructions (same format as batter swaps). Locked games are excluded.
3. **IL management** — players with IL designations (IL, IL10, IL15, IL60) not in IL slots, cleared players still in IL. DTD players are excluded since Yahoo does not allow moving them to IL.
Confidence
85% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Memory Manipulation

High
Category
Memory Poisoning
Content
```

Three analysis categories:
1. **Lineup changes** — optimal batter assignment via constraint solver (position-aware, fills restrictive slots before UTIL). Outputs grouped swap instructions showing who starts (from bench), who gets benched, and any intermediate position reshuffles needed within that chain (e.g., a UTIL player sliding to 1B to make room). Pure position shuffles among active slots (without bench involvement) are omitted. Also checks confirmed MLB batting lineups — players confirmed not in their team's lineup are treated as unavailable (score 0) and will be moved to bench. Players whose games have already started are locked in place (Yahoo locks roster slots at first pitch) and excluded from the solver.
2. **Pitcher rotation** — priority-based pitcher slot optimization with swap suggestions. Relief pitchers whose teams are playing today are prioritized over non-starting SPs or pitchers whose teams are off. Probable starters get highest priority. Outputs grouped swap instructions (same format as batter swaps). Locked games are excluded.
3. **IL management** — players with IL designations (IL, IL10, IL15, IL60) not in IL slots, cleared players still in IL. DTD players are excluded since Yahoo does not allow moving them to IL.
Confidence
85% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Credential Access

High
Category
Privilege Escalation
Content
CRED_DIR = Path.home() / ".openclaw" / "credentials" / "yahoo-fantasy"
CONFIG_FILE = CRED_DIR / "yahoo-fantasy.json"
OAUTH_FILE = CRED_DIR / "oauth2.json"
LEGACY_ENV_FILE = CRED_DIR / ".env"

GAME_CODE = "mlb"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
# running. Use subprocess instead so stdin/stdout are properly inherited.
        sys.exit(subprocess.call([_VENV_PYTHON, __file__] + sys.argv[1:]))
    else:
        os.execv(_VENV_PYTHON, [_VENV_PYTHON, __file__] + sys.argv[1:])


# Handle --setup: explicitly install dependencies
Confidence
85% confidence
Finding
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Session Persistence

Medium
Category
Rogue Agent
Content
### Entry Point

`yahoo-fantasy-baseball.py` is the entry point. Run `--setup` to create the `.deps/` venv and install pinned dependencies from `requirements.txt`. On normal runs, it fails fast if deps are missing, then re-execs into the venv and calls `scripts/fantasy.py:main()`.

### Module Responsibilities
Confidence
60% confidence
Finding
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.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documentation declares broad operational behavior that requires environment access, file writes, network access, and shell execution, but it does not declare any explicit tool scope or permissions boundaries. That omission weakens least-privilege controls and makes it easier for an agent runtime to grant more capability than users expect, especially given the skill handles OAuth credentials and local dependency installation.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The manifest states 'Read-only — no roster modifications,' which suggests the skill does not persist changes. While the code does not modify Yahoo rosters, it does write local configuration via save_config, so the actual behavior is not purely read-only in the broader sense claimed by the description.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print("Installing dependencies...", file=sys.stderr)

    # Create venv
    subprocess.check_call(
        [sys.executable, "-m", "venv", _VENV_DIR],
        stdout=sys.stderr,
        stderr=sys.stderr,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Install requirements into the venv
    pip_cmd = [_VENV_PYTHON, "-m", "pip", "install", "-q", "-r", _REQUIREMENTS]
    subprocess.check_call(pip_cmd, stdout=sys.stderr, stderr=sys.stderr)

    print("Dependencies installed.", file=sys.stderr)
Confidence
88% confidence
Finding
The setup path installs Python packages from requirements.txt, which can execute arbitrary code during package installation or via malicious dependencies. Even though installation is gated behind --setup, this still introduces a supply-chain execution risk if requirements.txt or package sources are tampered with.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# On Windows, os.execv spawns a new process and exits the current one,
        # which causes the shell to print its prompt while the child is still
        # running. Use subprocess instead so stdin/stdout are properly inherited.
        sys.exit(subprocess.call([_VENV_PYTHON, __file__] + sys.argv[1:]))
    else:
        os.execv(_VENV_PYTHON, [_VENV_PYTHON, __file__] + sys.argv[1:])
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Low
Confidence
95% confidence
Finding
The skill manifest says it is for querying the user's Yahoo fantasy baseball team, but the `standouts` command iterates over `league.teams()` and fetches rosters and stats for every team in the league. That creates a scope mismatch and can expose other managers' roster usage and performance details beyond the user-centric behavior described in the manifest.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Content
if isinstance(obj, dict):
        val = obj.get(key, default)
    else:
        val = getattr(obj, key, default)
    if val is None:
        return default
    return val
Confidence
50% confidence
Finding
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Static analysis

No suspicious patterns detected.