Back to skill

Security audit

Stock Price Checker Pro

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent stock-information checker that runs a local Python script using yfinance, with supply-chain and temporary-lock-file cautions but no evidence of hidden, destructive, or unrelated behavior.

Install only if you are comfortable with the skill running Python code that auto-installs yfinance and queries Yahoo Finance for requested tickers. Prefer a pinned dependency or lockfile in higher-trust environments, and avoid running it with unnecessary secrets or broad filesystem access in the environment.

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)

T08 · Insecure Dependencies

Warning
Location
src/main.py:3
Finding
Unpinned Dependency Is Automatically Resolved and Executed## Vulnerability Details **File Location**: `src/main.py`, lines 3-7 **Vulnerability Type**: Unpinned third-party dependency and unsafe dynamic resolution **Risk Level**: Medium ### Vulnerable Code ```python # /// script # requires-python = ">=3.12" # dependencies = [ # "yfinance", # ] # /// ``` The documented execution workflow in `SKILL.md` instructs the Agent to run this script through `uv run`, which automatically resolves and installs `yfinance`. ### Technical Analysis The dependency declaration specifies only the package name and does not constrain it to an audited version. The project also contains no reviewed lockfile or package hash. Consequently, the effective code executed by the Skill can change between invocations even when the Skill's own source files remain unchanged. Importing `yfinance` executes Python code from the resolved package and its transitive dependencies with the same operating-system privileges as the Skill process. A compromised package release, compromised package-distribution account, or malicious transitive dependency could therefore introduce arbitrary behavior after this project has been reviewed. This is a supply-chain weakness rather than evidence that the currently published `yfinance` package is malicious. ### Attack Path 1. An attacker compromises a dependency release channel, maintainer account, or transitive dependency used by `yfinance`. 2. The attacker publishes a version containing malicious initialization or import-time code. 3. A user or Agent invokes the documented `uv run src/main.py <TICKER>` command. 4. Because no exact version or reviewed lockfile is enforced, `uv` may resolve and install the compromised release. 5. `src/main.py` imports `service.py`, which imports `yfinance`. 6. The malicious package code executes with the privileges and accessible environment of the Skill process. ### Impact Assessment Successful exploitation could provide ...[truncated 377 chars]
Remediation
## Remediation Suggestions - Pin `yfinance` and every transitive dependency to reviewed, exact versions. - Commit and enforce a generated lockfile rather than resolving unconstrained versions during normal Skill execution. - Use package hashes or another integrity-verification mechanism where supported. - Download dependencies only from an explicitly trusted package index over authenticated TLS. - Build and scan the dependency environment in a controlled release process instead of automatically installing new versions at invocation time. - Run the Skill in a sandbox with minimal filesystem access, no unnecessary credentials in its environment, and network access restricted to the market-data endpoints required for its declared functionality. - Establish a reviewed dependency-update process with vulnerability and provenance checks.

T09 · Insecure Skill Coding Practices

Note
Location
src/mutex.py:14
Finding
Predictable Shared Lock File in a Globally Writable Temporary Directory## Vulnerability Details **File Location**: `src/mutex.py`, lines 14-15 and 29-30 **Vulnerability Type**: Unsafe temporary-file handling and local denial of service **Risk Level**: Low ### Vulnerable Code ```python LOCK_FILE = os.environ.get("SKILL_MUTEX_LOCK", "/tmp/openclaw-skill.lock") LOCK_TIMEOUT = int(os.environ.get("SKILL_MUTEX_TIMEOUT", "300")) ``` ```python deadline = time.monotonic() + timeout lock_fd = os.open(LOCK_FILE, os.O_CREAT | os.O_WRONLY, 0o644) ``` ### Technical Analysis The mutex uses a fixed, generic pathname under `/tmp`, a directory normally writable by all local users. The file is opened without exclusive creation, ownership validation, or protections against symbolic-link traversal such as `O_NOFOLLOW`. A local process able to prepare or access the same lock file can contend for its advisory `flock`. Because the default timeout is 300 seconds, a process that continually holds the lock can delay Skill execution and cause it to terminate with a timeout. The generic filename also creates unnecessary interference between unrelated Skill instances that use the same implementation. The practical exploitability depends on local account permissions, ownership of a pre-existing file, and whether the Skill executes as a user permitted to open that file. This issue does not independently grant privilege escalation, and `os.open` does not use `O_TRUNC`, so the shown operation does not itself overwrite the target's contents. ### Attack Path 1. A local attacker or another process running under a compatible account creates or opens `/tmp/openclaw-skill.lock`. 2. That process obtains and continuously holds an exclusive advisory lock on the file. 3. The Skill invokes `acquire_lock()` before requesting stock data. 4. The Skill repeatedly fails to obtain the nonblocking lock and waits in one-second intervals. 5. After the configured 300-second timeout, the Skill raises `TimeoutError`, preventing the req ...[truncated 628 chars]
Remediation
## Remediation Suggestions - Place the lock in a private per-user runtime directory, such as a securely permissioned directory under `$XDG_RUNTIME_DIR`, rather than directly under `/tmp`. - Create the parent directory with mode `0700` and verify that it is owned by the expected account. - Use a unique, Skill-specific filename to prevent unrelated applications from sharing the same mutex. - Open the file with `O_NOFOLLOW` where supported and validate the opened file with `fstat` to confirm its type and ownership. - Create the lock securely during controlled initialization, using exclusive creation where appropriate. - Apply restrictive file permissions such as `0600`. - Consider reducing the default timeout and returning a controlled error so lock contention cannot tie up execution for five minutes.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The declared description emphasizes fetching current stock prices by running a local script. However, the supplied code chunk contains only configuration constants for historical windows and news/event limits. While these constants may support a broader stock-analysis feature, the visible code does not implement or directly reflect the declared primary behavior of executing a local script to obtain current prices. Based on the provided chunk alone, the description is not accurately represented.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The primary functional purpose mostly aligns: the code is for retrieving current stock prices. However, the declared description materially misrepresents how the skill operates. It says to use the read tool to load SKILL.md and then execute a uv run command, while the supplied code is a standalone Python CLI entrypoint that takes a ticker symbol as argv and uses internal service functions plus yfinance. That is a description-to-behavior mismatch in execution method and interface. Additionally, the metadata shows empty triggers even though the prose lists stock-related triggers. There is no evidence of unrelated or dangerous undeclared capabilities in this chunk; the mismatch is about the declared workflow/interface rather than the core stock-price purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says the skill fetches current stock prices by running a local script, implying market-data retrieval behavior. The supplied code does not fetch stock prices, invoke uv, read SKILL.md, perform I/O related to financial data, or implement any stock-query logic. Instead, it provides a synchronization primitive for locking across concurrent jobs. This is a materially different primary purpose, not merely a supporting detail for stock-price retrieval within the provided chunk. Therefore the description does not accurately represent what this code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description does not accurately represent the supplied code. While both relate to stock prices, the code's actual behavior is materially broader than 'fetch current stock prices.' It gathers extensive market data, historical ranges, relevant news, and upcoming events, and formats a detailed report. In addition, the description emphasizes operational instructions about reading SKILL.md and executing a uv run command, but the provided code chunk is a Python service implementation and not just a thin wrapper for a local script. The core domain is related, but the declared purpose omits significant capabilities present in the code, so this should be flagged as a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description says this skill runs a local script to obtain current stock prices. The actual code shown is only a formatting helper module with presentation utilities for numbers, ranges, dates, market cap, and volume. These helpers could support a stock tool, but by themselves they do not implement the declared primary purpose of fetching current stock prices or executing a local script. That is a material description-to-behavior mismatch, not merely an omitted implementation detail, because the code chunk lacks the core capability the skill claims to provide.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest describes a narrowly scoped skill to fetch current stock prices, but this function also retrieves historical data, recent news, earnings/calendar events, market capitalization, and volume metrics. Those extra outputs materially expand the skill's behavior beyond a simple current-price lookup.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
For a skill presented as a stock price checker, downloading and filtering company news is a separate analytical capability rather than an obvious requirement for returning the current price. The manifest does not mention news enrichment, so this capability is contextually broader than advertised.

Context-Inappropriate Capability

Low
Confidence
87% confidence
Finding
The code parses earnings dates, dividend dates, and EPS estimate information from calendar data. These event-oriented features are useful financial context, but they are not a direct or necessary part of a skill whose stated purpose is to fetch current stock prices.

Missing User Warnings

Low
Confidence
82% confidence
Finding
This Python file performs external data retrieval through yfinance by instantiating a ticker and accessing remote-backed properties such as info, history, and news. While the function docstring describes the feature, there is no explicit user-facing warning, logging, or comment disclosing that the skill sends the requested stock symbol to an external service.

Static analysis

No suspicious patterns detected.