Back to skill

Security audit

Daily Stock Analysis

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed stock-report generator, but its file-handling scripts can be tricked into writing or moving reports outside the intended workspace.

Review before installing in any workspace that may contain untrusted files or symlinks. Use only trusted ticker/date inputs, avoid migration on untrusted paths, and prefer a fixed version that validates filename components and rejects symlinked report directories. Expect the skill to create local markdown reports and to use web sources for stock data.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/report_manager.py:36
Finding

Path Traversal Through Unvalidated Report Filename Components

Content
View full analysis
Dict[str, object]: root = os.path.abspath(workdir) ticker_upper = ticker.upper() reports_dir = canonical_reports_dir(root) os.makedirs(reports_dir, exist_ok=True) reports = discover_reports(root, ticker_upper) history_files = [r.path for r in reports[:history_limit]] legacy_files = [r.path for r in reports if not r.in_canonical_dir] base_name = f"{run_date}-{ticker_upper}-analysis.md" base_path = os.path.join(reports_dir, base_name) base_exists = os.path.exists(base_path) requires_user_choice = False selected_mode = "new_file" selected_path = base_path if base_exists: if versioning == "overwrite": selected_mode = "overwrite" elif versioning == "new_version": selected_mode = "new_version" else: if unattended: selected_mode = "new_version" else: selected_mode = "new_version" requires_user_choice = True if selected_mode == "new_version": versions = _same_day_versions_in_canonical( reports, reports_dir, run_date, ticker_upper ) next_version = max(versions or [1]) + 1 selected_path = os.path.join( reports_dir, f"{run_date}-{ticker_upper}-analysis-v{next_version}.md" ) return { "ticker": ticker_upper, "workdir": root, "reports_dir": reports_dir, "base_output_file": base_path, "selected_output_file": selected_path, "selected_versioning_mode": selected_mode, "requires_user_choice": requires_user_choice ...[truncated 2510 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/report_manager.py:101
Finding

Canonical Reports Directory Symlink Can Redirect Writes and Migrations

Content
View full analysis
str: return os.path.join(os.path.abspath(workdir), "daily-stock-analysis", "reports") ``` ```python def migrate_files(workdir: str, files: List[str]) -> Dict[str, object]: root = os.path.abspath(workdir) reports_dir = canonical_reports_dir(root) os.makedirs(reports_dir, exist_ok=True) moved = [] skipped = [] for raw_path in files: src = os.path.abspath(raw_path) if not is_within_workdir(src, root): skipped.append({"file": src, "reason": "outside_workdir"}) continue if not os.path.isfile(src): skipped.append({"file": src, "reason": "not_file"}) continue if os.path.islink(src): skipped.append({"file": src, "reason": "symlink_not_allowed"}) continue if not FILENAME_RE.match(os.path.basename(src)): skipped.append({"file": src, "reason": "filename_not_supported"}) continue dst = os.path.join(reports_dir, os.path.basename(src)) if os.path.abspath(src) == os.path.abspath(dst): skipped.append({"file": src, "reason": "already_in_reports_dir"}) continue if os.path.exists(dst): # Keep migration deterministic and non-destructive. skipped.append({"file": src, "reason": "target_exists"}) continue try: shutil.move(src, dst) except OSError as exc: skipped.append({"file": src, "reason": f"move_failed:{exc}"}) continue moved.append({"from": src, "to": dst}) ``` The same unsafe canonical-directory construction is used by report planning: ```python reports_dir = canonical_repo ...[truncated 2503 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill is presented as a stock-analysis workflow, but the actual content heavily emphasizes filesystem orchestration and script-driven path planning/migration, including handling absolute paths for migration. This description-behavior mismatch can mislead reviewers and users about the real operational surface area, causing them to approve a skill with more powerful file-management behavior than expected.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill instructs the agent to read and write files and invoke local scripts, but it does not declare any explicit tool scope such as permissions or allowed-tools. That mismatch weakens policy enforcement and user visibility, making it easier for the skill to access filesystem capabilities implicitly and increasing the chance of unintended file access or misuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The workflow explicitly instructs the agent to save a report file to a selected output path, but it does not require any user-facing notice or confirmation that local filesystem writes will occur. In an agent environment, silent persistence can surprise users, overwrite expected artifacts, or create unwanted local data retention even if the path is constrained by prior workflow steps.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.