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

Content
View full analysis

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
View 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

Content
View full analysis

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

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.