Back to skill

Security audit

stock-screener

Security checks across malware telemetry and agentic risk

Overview

The skill is a disclosed stock research and AI4Trade integration with local records and confirmation-gated external actions; I found no artifact-backed deception or exfiltration.

Install only if you want this agent to access market data services, maintain local stock records, call optional local research backends, and use AI4Trade when you provide a token. Review any AI4Trade action carefully before allowing confirm=true, especially publishing, following, heartbeat/read-state changes, or point exchange.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (15)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def _run_research_backend(command: List[str], timeout_seconds: int) -> Dict[str, Any]:
    """Run a fixed local command without a shell and label its output untrusted."""
    try:
        completed = subprocess.run(
            command,
            capture_output=True,
            text=True,
Confidence
87% confidence
Finding
completed = subprocess.run( command, capture_output=True, text=True, timeout=timeout_seconds, env=_backend_env(), cwd=_e

subprocess module call

Medium
Category
Dangerous Code Execution
Content
env=environment, cwd=_ensure_quant_state_dir(), check=False,
                )
        else:
            completed = subprocess.run(
                [python, "-c", runner], capture_output=True, text=True, timeout=timeout_seconds,
                env=environment, cwd=_ensure_quant_state_dir(), check=False,
            )
Confidence
84% confidence
Finding
completed = subprocess.run( [python, "-c", runner], capture_output=True, text=True, timeout=timeout_seconds, env=environment, cwd=_ensure_quant_state_dir(),

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if bridge:
            with bridge:
                environment.update({"OPENAI_API_KEY": bridge.token, "OPENAI_BASE_URL": bridge.base_url})
                completed = subprocess.run(
                    [python, "-c", runner], capture_output=True, text=True, timeout=timeout_seconds,
                    env=environment, cwd=_ensure_quant_state_dir(), check=False,
                )
Confidence
84% confidence
Finding
completed = subprocess.run( [python, "-c", runner], capture_output=True, text=True, timeout=timeout_seconds, env=environment, cwd=_ensure_quant_

subprocess module call

Medium
Category
Dangerous Code Execution
Content
self._respond(400, {"error": {"message": f"invalid request: {exc}"}})
                    return
                try:
                    completed = subprocess.run(
                        [bridge.cli, "infer", "model", "run", "--gateway", "--json", "--prompt", prompt],
                        capture_output=True,
                        text=True,
Confidence
89% confidence
Finding
completed = subprocess.run( [bridge.cli, "infer", "model", "run", "--gateway", "--json", "--prompt", prompt], capture_output=True,

Tainted flow: 'req' from os.getenv (line 1841, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
url = f"{safe_base_url}/api/v1/auth/login"
        payload = json.dumps({"password": DSA_PASSWORD}).encode("utf-8")
        req = urllib.request.Request(url, data=payload, headers={"Content-Type": "application/json"})
        with urllib.request.urlopen(req, timeout=4) as res:
            cookie_header = res.headers.get("Set-Cookie", "")
            if "dsa_session=" in cookie_header:
                for part in cookie_header.split(";"):
Confidence
81% confidence
Finding
with urllib.request.urlopen(req, timeout=4) as res:

Direct flow: os.environ.get (credential/environment) → subprocess.run (code execution)

High
Category
Data Flow
Content
self._respond(400, {"error": {"message": f"invalid request: {exc}"}})
                    return
                try:
                    completed = subprocess.run(
                        [bridge.cli, "infer", "model", "run", "--gateway", "--json", "--prompt", prompt],
                        capture_output=True,
                        text=True,
Confidence
76% confidence
Finding
completed = subprocess.run( [bridge.cli, "infer", "model", "run", "--gateway", "--json", "--prompt", prompt], capture_output=True,

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises and documents capabilities that imply access to environment variables, local files, network services, and shell/CLI tooling, but it declares no permissions. This creates a confused-trust problem: users and hosting platforms cannot accurately assess or constrain what the skill may access, increasing the risk of unintended secret exposure, local state modification, or execution of external commands through the MCP tools it wraps.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The top-level description frames the skill primarily as stock analysis and restricted research, but the documented behavior includes local persistence, alert management, ML prediction, and multiple AI4Trade state-changing operations such as publishing content, follow/unfollow actions, heartbeat/read-state changes, and points exchange. This mismatch is dangerous because users may grant trust or invoke the skill expecting read-only research behavior while it can modify local and remote state, leading to unintended actions on third-party services and local records.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The advertised skill is a stock screener/research tool, but the code also exposes AI4Trade account access, social posting, following/unfollowing, point exchange, heartbeat state changes, and simulated signal publication. This hidden expansion of capabilities is dangerous because a caller or orchestrating agent may invoke side-effecting functions without realizing the skill can alter third-party platform state and influence followers.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
A stock screener is expected to fetch market data and compute analytics, but this code also runs external local research backends and agent frameworks as subprocesses. That materially changes the trust model by introducing execution of large dependency trees and toolchains that may access local files, network resources, and secrets.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
Portfolio and alert creation/deletion mutate persistent local state immediately with no confirmation barrier. In an agent setting, this enables accidental or prompt-injected writes, deletions, or watchlist/position tampering that can mislead users or corrupt local records.

Unvalidated Output Injection

High
Category
Output Handling
Content
self._respond(400, {"error": {"message": f"invalid request: {exc}"}})
                    return
                try:
                    completed = subprocess.run(
                        [bridge.cli, "infer", "model", "run", "--gateway", "--json", "--prompt", prompt],
                        capture_output=True,
                        text=True,
Confidence
86% confidence
Finding
subprocess.run( [bridge.cli, "infer", "model", "run", "--gateway", "--json", "--prompt", prompt], capture_output

Unvalidated Output Injection

High
Category
Output Handling
Content
def _run_research_backend(command: List[str], timeout_seconds: int) -> Dict[str, Any]:
    """Run a fixed local command without a shell and label its output untrusted."""
    try:
        completed = subprocess.run(
            command,
            capture_output=True,
            text=True,
Confidence
88% confidence
Finding
subprocess.run( command, capture_output

Unvalidated Output Injection

High
Category
Output Handling
Content
if bridge:
            with bridge:
                environment.update({"OPENAI_API_KEY": bridge.token, "OPENAI_BASE_URL": bridge.base_url})
                completed = subprocess.run(
                    [python, "-c", runner], capture_output=True, text=True, timeout=timeout_seconds,
                    env=environment, cwd=_ensure_quant_state_dir(), check=False,
                )
Confidence
88% confidence
Finding
subprocess.run( [python, "-c", runner], capture_output

Unvalidated Output Injection

High
Category
Output Handling
Content
env=environment, cwd=_ensure_quant_state_dir(), check=False,
                )
        else:
            completed = subprocess.run(
                [python, "-c", runner], capture_output=True, text=True, timeout=timeout_seconds,
                env=environment, cwd=_ensure_quant_state_dir(), check=False,
            )
Confidence
88% confidence
Finding
subprocess.run( [python, "-c", runner], capture_output

VirusTotal

65/65 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.