Back to skill

Security audit

singa- finance

Security checks for vulnerabilities and agentic risk

Overview

This finance skill mostly does what it claims, but one SEC filing command can fetch any URL rather than only SEC filing pages.

Install only if you are comfortable with a finance-data helper that runs Python and reaches Yahoo Finance and SEC services. Avoid using read-filing with URLs you did not get from the skill's own SEC filings output, and consider patching it to allow only SEC archive URLs before use.

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/sec_edgar.py:79
Finding

Unrestricted Filing URL Fetch Exposes the SEC Identity Header and Enables SSRF

Content
View full analysis
str: """Fetch raw text/HTML content from a URL.""" req = urllib.request.Request(url, headers={ "User-Agent": ua, "Accept": "text/html, application/xhtml+xml, text/plain, */*", }) try: with urllib.request.urlopen(req, timeout=60) as resp: return resp.read().decode("utf-8", errors="replace") except urllib.error.HTTPError as e: body = e.read().decode("utf-8", errors="replace")[:500] raise RuntimeError(f"EDGAR fetch error ({e.code}): {body}") from e ``` ```python def cmd_read_filing(url: str, section: str, max_chars: int, ua: str) -> dict: """Download a filing and return its text content.""" raw = _get_raw(url, ua) ``` ```python ap.add_argument("--url", default="", help="Direct filing document URL (for read-filing)") ``` ```python ua = args.user_agent or os.environ.get("SEC_EDGAR_USER_AGENT", DEFAULT_UA) ``` ### Technical Analysis The `read-filing` command accepts a caller-controlled URL and passes it directly to `urllib.request.urlopen`. The implementation does not validate the URL scheme, hostname, port, resolved IP address, path, or redirect destinations. Although sending an identifying User-Agent to SEC EDGAR is required and appropriate for requests to SEC services, `_get_raw` sends the same value to every supplied destination. The project documentation encourages users to configure this value with their real name and email address. Consequently, a request to an attacker-controlled host can disclose that identity. The unrestricted request also permits access to HTTP or HTTPS services reachable from the execution environment, ...[truncated 1936 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
scripts/requirements.txt:1
Finding

Unbounded Third-Party Dependency Prevents Reproducible and Reviewed Installation

Content
View full analysis
=0.2.36 ``` The documented installation command in `SKILL.md:14-18` is: ```bash pip install -r skills/finance-data/scripts/requirements.txt ``` ### Technical Analysis The lower-bound-only constraint allows the package installer to select any current or future `yfinance` version satisfying `>=0.2.36`, together with whatever transitive dependency versions are selected at installation time. The package name matches the implementation, and the reviewed project does not specify a suspicious alternate package source. However, the dependency set is not reproducible and can change without changes to the Skill itself. Future releases and newly resolved transitive dependencies therefore execute without having been covered by this audit. Python package installation can execute build backend and installation-related code with the privileges of the user performing the installation. Runtime behavior, including network access performed by `yfinance`, can also change between releases. ### Attack Path 1. A user follows the documented installation command. 2. The package resolver selects a newer, previously unaudited `yfinance` release or a changed transitive dependency. 3. The selected package is downloaded from the configured package index. 4. Package build or installation logic executes with the installing user's privileges. 5. The dependency subsequently executes when `yfinance_query.py` imports and uses it. 6. If a selected release or transitive component is compromised, its code can act with the privileges available to the Python process. ### Impact Assessment The concrete impact depends on the behavior of a future or compromised dependency. Such code could potentially access files, environment variables, credentials, and network resources avai ...[truncated 316 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This is a material description/behavior mismatch. The code’s primary purpose is narrowly focused on SEC EDGAR access: filings search, submissions, XBRL company facts/concepts, insider forms, and filing text extraction. That partially matches the SEC-related portion of the description, but the declared description prominently claims Yahoo Finance/yfinance-based market data and a wide range of equity research capabilities such as stock prices, options, dividends, analyst recommendations, and international ticker support. None of those capabilities appear in the code. The accessed resources are exclusively SEC endpoints, not Yahoo Finance. Therefore the declared description substantially overstates the implemented functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The implemented code substantially matches the Yahoo Finance portion of the description: it supports quotes, history, financials, profiles, holders, analyst data, dividends, options, earnings, news, and ticker symbols including examples like Chinese A-shares via Yahoo-format suffixes. However, the description explicitly states support for SEC EDGAR and use cases involving SEC filings and XBRL concepts, none of which appear in the code. There is no EDGAR client, no SEC API/network logic, no filing retrieval/parsing, and no XBRL handling. Therefore the description overstates the actual capabilities in a material way.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill invokes Python scripts that require network access and may read environment variables, but the manifest does not explicitly declare any tool scope or permissions. This creates an authorization/oversight gap where the agent may gain broader capabilities than reviewers or runtime policy expect, increasing the chance of unintended external access or data exposure.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description contains very broad routing language such as use for any stock, market-data, financials, filings, or equity-research task. Overly broad triggers can cause the agent to invoke this skill in loosely related contexts, unnecessarily granting networked code execution and external data access where a narrower tool or no tool would suffice.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/sec_edgar.py (reported line 125)May include surrounding context.

python
def cmd_filings(identifier: str, form_type: str, limit: int, ua: str) -> dict:
    """Get recent filings for a company via the submissions endpoint."""
    cik = _resolve_cik(identifier, ua)
    url = f"https://data.sec.gov/submissions/CIK{cik}.json"
    data = _get(url, ua)
    recent = data.get("filings", {}).get("recent", {})
    if not recent:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/sec_edgar.py (reported line 246)May include surrounding context.

python
def cmd_filings(identifier: str, form_type: str, limit: int, ua: str) -> dict:
    """Get recent filings for a company via the submissions endpoint."""
    cik = _resolve_cik(identifier, ua)
    url = f"https://data.sec.gov/submissions/CIK{cik}.json"
    data = _get(url, ua)
    recent = data.get("filings", {}).get("recent", {})
    if not recent:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/sec_edgar.py (reported line 264)May include surrounding context.

python
def cmd_filings(identifier: str, form_type: str, limit: int, ua: str) -> dict:
    """Get recent filings for a company via the submissions endpoint."""
    cik = _resolve_cik(identifier, ua)
    url = f"https://data.sec.gov/submissions/CIK{cik}.json"
    data = _get(url, ua)
    recent = data.get("filings", {}).get("recent", {})
    if not recent:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/sec_edgar.py (reported line 277)May include surrounding context.

python
def cmd_filings(identifier: str, form_type: str, limit: int, ua: str) -> dict:
    """Get recent filings for a company via the submissions endpoint."""
    cik = _resolve_cik(identifier, ua)
    url = f"https://data.sec.gov/submissions/CIK{cik}.json"
    data = _get(url, ua)
    recent = data.get("filings", {}).get("recent", {})
    if not recent:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/sec_edgar.py (reported line 299)May include surrounding context.

python
def cmd_filings(identifier: str, form_type: str, limit: int, ua: str) -> dict:
    """Get recent filings for a company via the submissions endpoint."""
    cik = _resolve_cik(identifier, ua)
    url = f"https://data.sec.gov/submissions/CIK{cik}.json"
    data = _get(url, ua)
    recent = data.get("filings", {}).get("recent", {})
    if not recent:

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The read-filing command accepts a user-supplied --url and passes it directly to urllib without validating that it points to an SEC EDGAR domain. This enables server-side request forgery behavior: an attacker could cause the agent to fetch arbitrary remote resources, including internal network services or cloud metadata endpoints if the skill runs in a privileged environment. In this finance/EDGAR skill, arbitrary URL fetching is more dangerous because the feature is presented as reading SEC filings, so callers may assume the network access is constrained when it is not.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
91% confidence
Finding

The dependency is only lower-bounded (yfinance>=0.2.36), so installs may resolve to any newer release, including versions with breaking changes or a compromised upstream package. This weakens build reproducibility and increases supply-chain risk, especially for a finance-oriented skill that consumes third-party market data libraries.

Content

Scanner excerpt · scripts/requirements.txt (reported line 1)May include surrounding context.

text
yfinance>=0.2.36

Static analysis

No suspicious patterns detected.