Back to skill

Security audit

TradingView Screener

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed TradingView market screener with normal setup and market-data access, but users should be aware of unpinned Python dependencies and outbound screening queries.

Install only if you are comfortable with pip resolving current package versions and with your screening filters or strategy parameters being sent to the TradingView/tvscreener data path. For higher-assurance use, pin and hash dependencies and review custom YAML expressions before running them.

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
install.sh:47
Finding
Unbounded Third-Party Dependency Installation## Vulnerability Details **File Location**: `install.sh:47-49` and `scripts/requirements.txt:1-4` **Vulnerability Type**: Unpinned and unhashed third-party dependencies **Risk Level**: Medium ### Vulnerable Code `install.sh:47-49`: ```bash # Install dependencies echo "Installing dependencies..." "$PIP" install --no-user -q -r "$REQ_FILE" ``` `scripts/requirements.txt:1-4`: ```text tvscreener>=0.2.0 pandas>=2.0.0 pyyaml>=6.0 pytest>=7.0.0 ``` ### Technical Analysis The documented installation process installs packages directly from pip's configured package index. Every dependency uses an open-ended lower-bound constraint, and the project provides neither a lockfile nor cryptographic package hashes. Consequently, installation results can change over time without any change to the reviewed project. Pip may select any future release satisfying these constraints. If an allowed package release or configured package source is compromised, attacker-controlled package code could run during installation or when the installed module is subsequently imported. The runtime environment also installs `pytest`, although it is only required for testing. This unnecessarily increases the production dependency footprint and supply-chain attack surface. No evidence in the audited project indicates that its authors intentionally introduced a malicious dependency. The risk arises from the non-reproducible and unauthenticated-by-project dependency resolution policy. ### Attack Path 1. An attacker compromises the publisher account, distribution infrastructure, or package-index delivery path for one of the allowed dependencies. 2. The attacker publishes or serves a malicious version whose number satisfies the applicable `>=` constraint. 3. A user follows the documented setup procedure and executes `install.sh`. 4. Pip resolves the malicious version because no exact version or expected hash restricts package selection. 5. Attacker-controlled code executes during package instal ...[truncated 790 chars]
Remediation
## Remediation Suggestions 1. Replace lower-bound constraints with exact, reviewed versions for all runtime dependencies. 2. Generate and commit a reproducible lockfile appropriate to every supported platform and Python version. 3. Record cryptographic hashes for approved distributions and install with pip's `--require-hashes` option. 4. Separate runtime and development dependencies so `pytest` is not installed in production environments. 5. Use a controlled package index or repository mirror with provenance, access control, and package-retention policies. 6. Add automated dependency vulnerability scanning and require review before updating locked versions. 7. Consider using a constraints file and deployment command similar to: ```bash "$PIP" install --no-user --require-hashes -r requirements.lock ``` 8. Rebuild and test lockfiles regularly so security updates are adopted deliberately rather than through unrestricted version resolution.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared purpose describes a functional trading/market-screening skill, but the supplied code chunk does not implement any of that behavior. It only performs setup tasks: detecting Python, creating a virtual environment, and installing packages. While installation can be a supporting detail, this chunk alone does not match the declared operational behavior and instead has a materially different immediate purpose. Therefore this code chunk does not accurately represent the described skill functionality.

Credential Access

High
Category
Privilege Escalation
Content
import os  # No imports
eval("malicious code")  # No eval/exec
PRICE.apply(lambda x: x * 2)  # No lambda
open("/etc/passwd")  # No file operations
```

## Common Patterns
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Intent-Code Divergence

Medium
Confidence
89% confidence
Finding
The guide states that expression signals use pandas eval() with whitelist validation and explicitly limits allowed syntax to column names, basic operators, logical operators, and only `.mean()`/`.std()` methods. However, elsewhere the document presents threshold and expression examples that rely on computed references like `1.5 * AVERAGE_VOLUME_10_DAY` and method-style capabilities without clearly fitting the stated constraints, creating active ambiguity about what the implementation actually accepts.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The code accepts a user-controlled expression, performs only a regex and keyword blacklist check, and then passes it to pandas df.eval(). The accompanying docstring overstates safety by calling this 'sandboxed', which can lead developers to trust untrusted expressions more than they should; even if this does not obviously permit arbitrary code execution here, it still enables risky dynamic evaluation and may expose the application to expression-injection, denial-of-service, or future bypasses as syntax/features change.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The skill states 'Zero auth required' and describes market screening against TradingView data, but it does not warn users that their screening parameters and queries may be transmitted to an external service. This can lead to unintentional disclosure of proprietary watchlists, strategies, or research interests, especially in enterprise or sensitive trading contexts.

Unpinned Dependencies

Low
Category
Supply Chain
Content
tvscreener>=0.2.0
pandas>=2.0.0
pyyaml>=6.0
pytest>=7.0.0
Confidence
94% confidence
Finding
The dependency specification for tvscreener uses a lower-bound version constraint instead of pinning an exact version, which makes builds non-reproducible and allows future installs to pull in unexpected or compromised releases. While this file alone does not prove exploitation, unpinned dependencies increase supply-chain risk and make security review of the installed package set difficult.

Unpinned Dependencies

Low
Category
Supply Chain
Content
tvscreener>=0.2.0
pandas>=2.0.0
pyyaml>=6.0
pytest>=7.0.0
Confidence
97% confidence
Finding
pandas is specified as >=2.0.0 rather than an exact version, so installations may resolve to different releases over time. This weakens reproducibility and can expose deployments to newly introduced vulnerabilities or behavior changes without any code change in the skill itself.

Unverifiable Dependency: pandas has 1 known advisory(ies) (CVE-2020-13091 (** DISPUTED ** pandas through 1.0.3 can unserialize and execute commands from an)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding
The manifest does not pin pandas, so it is impossible to verify from this file whether the installed version is affected by known advisories. Although the cited pandas advisory is disputed and may not apply, the inability to determine the actual installed version is itself a supply-chain assurance gap.

Unpinned Dependencies

Low
Category
Supply Chain
Content
tvscreener>=0.2.0
pandas>=2.0.0
pyyaml>=6.0
pytest>=7.0.0
Confidence
98% confidence
Finding
PyYAML is unpinned, which is more concerning in this skill context because the skill description indicates YAML-driven strategies, making YAML parsing a core feature. If an unsafe or newly vulnerable PyYAML release is installed, the application could be exposed to parsing or deserialization risks depending on how the library is used elsewhere in the codebase.

Unverifiable Dependency: pyyaml has 8 known advisory(ies) (CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
96% confidence
Finding
PyYAML has multiple historical security advisories, and this requirements file does not pin a specific version, so reviewers cannot determine whether an affected release may be installed. Given that the skill is explicitly YAML-driven, this uncertainty is more dangerous because YAML parsing is likely a central code path and could amplify the effect of an unsafe dependency version.

Unpinned Dependencies

Low
Category
Supply Chain
Content
tvscreener>=0.2.0
pandas>=2.0.0
pyyaml>=6.0
pytest>=7.0.0
Confidence
91% confidence
Finding
pytest is unpinned, which can lead to non-deterministic test environments and accidental inclusion of vulnerable or incompatible versions. Because pytest is typically a development/test dependency, the direct runtime impact is usually lower, but it still contributes to supply-chain and CI risk.

Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
81% confidence
Finding
Because pytest is not pinned, the file does not allow verification of whether the resolved version is affected by known advisories. This is primarily a test/CI supply-chain concern rather than a direct production runtime issue, but it can still affect build integrity and developer environments.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This Python code file performs a likely network operation via `screener.get()` to fetch TradingView market data, but the file provides no visible user-facing warning at the call site beyond a generic module docstring. Under the code-file criteria, network calls that transmit user or system data should have some disclosure such as a prompt, log, comment, or clear documentation in the skill description.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Content
"""
    name_upper = field_name.strip().upper()
    try:
        return getattr(field_enum, name_upper)
    except AttributeError:
        # Try search as fallback
        results = field_enum.search(field_name)
Confidence
50% confidence
Finding
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/signal_types.py:92