Back to skill

Security audit

alphaear-signal-tracker

Security checks for vulnerabilities and agentic risk

Overview

The skill is finance-related, but it is under-scoped and bundles broader network, model-loading, and database behavior that needs review before use.

Treat this as a Review install: use it only in a constrained environment, do not pass private or signed URLs into its news tools, and only load model checkpoints or downloaded models from sources you already trust. Expect local SQLite state to be created or modified, and verify the broader AlphaEar helper code before enabling it in an agent with sensitive credentials or high-impact financial workflows.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (5)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/tools/toolkits.py:71
Finding
Unrestricted forwarding of user-controlled URLs to a third-party content extraction service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tools/toolkits.py:71-84`, with the network request implemented in `scripts/utils/content_extractor.py:65-103` **Vulnerability Type**: Unvalidated URL forwarding and sensitive URL disclosure **Risk Level**: Medium ### Vulnerable Code ```python def fetch_news_content(self, url: str) -> str: """ 使用 Jina Reader 抓取指定 URL 的网页正文内容。 Args: url: 需要抓取内容的完整网页 URL,必须以 http:// 或 https:// 开头。 Returns: 提取的网页正文内容,如果失败则返回错误信息。 """ content = self._news_tools.fetch_news_content(url) if content: return content[:5000] return "内容抓取失败" ``` The URL is subsequently forwarded by the content extractor: ```python @classmethod def extract_with_jina(cls, url: str, timeout: int = 30) -> Optional[str]: if not url or not url.startswith("http"): return None headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/131.0.0.0 Safari/537.36", "Accept": "application/json" } api_key = os.getenv("JINA_API_KEY") has_api_key = bool(api_key and api_key.strip()) if has_api_key: headers["Authorization"] = f"Bearer {api_key}" cls._wait_for_rate_limit(has_api_key) try: full_url = f"{cls.JINA_BASE_URL}{url}" response = requests.get(full_url, headers=headers, timeout=timeout) ``` ### Technical Analysis The exposed `fetch_news_content` tool accepts a URL that may be selected from agent or user-controlled input. Validation consists only of checking whether the string starts with `http`. It does not: - Require a properly parsed `https` URL. - Reject embedded usernames or passwords. - Reject signed URLs or sensitive query-string parameters. - Restrict destination domains to approved news sources. - Reject localhost, private, reserved, link-local, or metadata-service addresses. - Account ...[truncated 1998 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse URLs with `urllib.parse.urlsplit` instead of using a prefix check. 2. Permit only the exact `https` scheme. 3. Maintain an allowlist of approved public financial-news domains. 4. Reject URLs containing username or password components. 5. Remove or reject sensitive query parameters such as `token`, `key`, `signature`, `credential`, and `auth`. 6. Resolve destination hostnames and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges. 7. Revalidate every redirect destination or disable redirects. 8. Require explicit user confirmation before forwarding a URL outside the local environment. 9. Clearly disclose that Jina receives the complete URL. 10. Prefer direct requests to approved public sources where licensing and security policies allow them. 11. Add tests for malformed schemes, encoded hostnames, IPv6 literals, redirect chains, embedded credentials, and private addresses. ]]>

T01 · Skill Instruction Hijacking

Error
Location
scripts/tools/toolkits.py:71
Finding
Untrusted web content is introduced into the agent workflow without prompt-injection isolation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tools/toolkits.py:71-84`, `scripts/utils/content_extractor.py:91-103`, and workflow declaration in `SKILL.md:20-35` **Vulnerability Type**: Indirect prompt injection through external research content **Risk Level**: High ### Vulnerable Code The agent-facing tool returns fetched page content directly: ```python def fetch_news_content(self, url: str) -> str: content = self._news_tools.fetch_news_content(url) if content: return content[:5000] return "内容抓取失败" ``` The extractor returns third-party-controlled content without trust metadata or instruction filtering: ```python response = requests.get(full_url, headers=headers, timeout=timeout) if response.status_code == 200: try: data = response.json() if isinstance(data, dict) and "data" in data: return data["data"].get("content", "") return data.get("content", response.text) except (json.JSONDecodeError, TypeError): return response.text ``` The declared workflow feeds research material into later analysis: ```markdown 1. **Research**: Use **FinResearcher Prompt** to gather facts/price for a signal. 2. **Analyze**: Use **FinAnalyst Prompt** to generate the initial `InvestmentSignal`. 3. **Track**: For existing signals, use **Signal Tracking Prompt** to assess evolution based on new info. ``` ### Technical Analysis External web pages are attacker-controlled input. A page can contain text addressed to an AI agent, such as instructions to ignore the research task, invoke additional tools, fabricate ticker data, suppress risk information, or produce manipulated investment conclusions. The content extractor returns the page body as an ordinary string. The tool does not attach provenance or an untrusted-content marker, remove instruction-like constructs, or enforce a separation between page data and agent instructions. The Skill workflow explicitly relies on fetched research in ...[truncated 1641 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Mark all fetched page content as untrusted external data. 2. Place content inside explicit delimiters and include a fixed instruction that text inside the delimiters must never be treated as commands. 3. Keep tool authorization outside model control; validate each requested tool call against an allowlist and the current task. 4. Restrict fetching to vetted financial and news domains. 5. Extract factual fields through a constrained parser rather than placing entire pages into prompts. 6. Remove scripts, invisible text, metadata instructions, and common prompt-injection patterns before model processing. 7. Require independent corroboration from multiple sources before changing signal confidence or status. 8. Validate ticker codes, cited sources, confidence changes, and numerical claims after model generation. 9. Prevent fetched content from directly changing system prompts, persistent memory, tool definitions, or execution policy. 10. Log source provenance and retain a clear distinction between instructions, user input, and external evidence. 11. Add adversarial tests containing indirect prompt injections in article titles, body text, metadata, and search snippets. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/utils/predictor/evaluation.py:37
Finding
Unsafe deserialization of potentially attacker-controlled PyTorch checkpoints<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/predictor/evaluation.py:37-40` **Vulnerability Type**: Unsafe model checkpoint deserialization **Risk Level**: High ### Vulnerable Code ```python def load_weights(self, path): logger.info(f"🔄 Loading model weights from {path}...") checkpoint = torch.load(path, map_location=self.device) self.trainer.model.news_proj.load_state_dict( checkpoint['news_proj_state_dict'] ) logger.success("✅ News projection layer loaded.") ``` The default selection logic also automatically chooses the newest checkpoint: ```python if model_path is None: model_files = glob.glob( os.path.join(SRC_DIR, "exports/models/*.pt") ) if not model_files: logger.warning( "⚠️ No trained models found in exports/models/. " "Using base model (zero-init proj)." ) else: model_path = max(model_files, key=os.path.getctime) if model_path: self.load_weights(model_path) ``` ### Technical Analysis Traditional `torch.load` behavior relies on Python pickle-compatible deserialization. Pickle is not a safe data format for untrusted input because specially constructed objects can execute Python code during deserialization. The evaluator accepts a caller-supplied path. If no path is supplied, it selects the newest `.pt` file under `exports/models`. No path confinement, ownership check, signature, hash verification, or safe weights-only loading is applied. The subsequent use of `load_state_dict` does not mitigate this issue because unsafe deserialization has already occurred when `torch.load` returns. ### Attack Path 1. An attacker gains the ability to supply `model_path` or write a `.pt` file into `exports/models`. 2. The attacker creates a checkpoint containing a malicious pickle reduction payload. 3. The crafted file is passed explicitly or made the newest file in the model directory. 4. `NewsModelEvaluator` calls `load_weights`. 5. ...[truncated 669 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use `torch.load(path, map_location=self.device, weights_only=True)` on a PyTorch release that supports the option. 2. Prefer a non-executable format such as `safetensors`. 3. Restrict model paths to a dedicated trusted directory using canonical-path validation. 4. Reject symbolic links and files not owned by the expected account. 5. Verify checkpoints against pinned SHA-256 hashes or trusted digital signatures. 6. Do not automatically select files merely because they are the newest. 7. Validate that the deserialized object is a dictionary containing only expected tensor keys and tensor types. 8. Run model conversion or validation in a sandbox without secrets, network access, or write access to sensitive files. 9. Document that checkpoints are executable-equivalent artifacts and must never be accepted from untrusted sources. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/utils/predictor/kline_generate.py:25
Finding
SQL injection in predictor ticker lookup<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/predictor/kline_generate.py:25-29` **Vulnerability Type**: SQL injection through string interpolation **Risk Level**: Medium ### Vulnerable Code ```python def load_data( ticker="002111", db_path="AlphaEar/data/signal_flux.db" ): with sqlite3.connect(db_path) as conn: df = pd.read_sql_query( f"SELECT * FROM stock_prices WHERE ticker = '{ticker}'", conn ) df['date'] = pd.to_datetime(df['date']) df = df.sort_values('date').reset_index(drop=True) return df ``` ### Technical Analysis The `ticker` argument is inserted directly into the SQL statement through an f-string. No format validation or parameterized binding is used. Although the current script entry point supplies a hardcoded ticker, `load_data` is a reusable function and may be invoked by another component with externally controlled input. A malicious value can terminate the quoted string and alter the query. Depending on the SQLite and pandas execution behavior, practical exploitation may include predicate bypass or `UNION SELECT` extraction. Some stacked-statement payloads may be rejected by the driver, but that does not prevent single-statement SQL injection. ### Attack Path 1. A caller exposes `load_data` to a user-controlled or agent-generated ticker. 2. The attacker supplies a value containing SQL syntax, such as a quote followed by a modified predicate or compatible `UNION SELECT`. 3. The function interpolates the value into the SQL statement. 4. SQLite parses the injected syntax as part of the query. 5. The returned DataFrame may contain rows outside the requested ticker or data from other compatible tables. 6. The resulting data can then influence forecasts or be disclosed through output and charts. ### Impact Assessment The primary confirmed risk is unauthorized reading of data available through the selected SQLite connection and corruption of forecast integri ...[truncated 349 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use parameterized SQL: ```python def load_data( ticker="002111", db_path="AlphaEar/data/signal_flux.db" ): if not re.fullmatch(r"\d{5,6}", ticker): raise ValueError("Invalid ticker format") with sqlite3.connect(db_path) as conn: df = pd.read_sql_query( "SELECT * FROM stock_prices WHERE ticker = ?", conn, params=(ticker,) ) df["date"] = pd.to_datetime(df["date"]) return df.sort_values("date").reset_index(drop=True) ``` Additional hardening: 1. Validate ticker values against the exact supported exchange format. 2. Restrict `db_path` to an approved application data directory. 3. Open the database in read-only mode for forecasting operations. 4. Do not expose raw database errors to untrusted users. 5. Add tests using quotes, comments, Boolean expressions, and `UNION` payloads. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/utils/predictor/kline_generate.py:15
Finding
Runtime model downloads are not pinned to immutable revisions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/predictor/kline_generate.py:15-22`, with additional fallback behavior in `scripts/utils/sentiment_tools.py:52-78` **Vulnerability Type**: Unpinned remote machine-learning model dependency **Risk Level**: Medium ### Vulnerable Code ```python def load_predictor(): tokenizer = KronosTokenizer.from_pretrained( "NeoQuasar/Kronos-Tokenizer-base" ) model = Kronos.from_pretrained( "NeoQuasar/Kronos-base" ) device = get_device() tokenizer = tokenizer.to(device) model = model.to(device) return KronosPredictor( model, tokenizer, device=device, max_context=512 ) ``` The sentiment component first attempts local loading and then downloads the configured model without an immutable revision: ```python bert_model = os.getenv( "BERT_SENTIMENT_MODEL", "uer/roberta-base-finetuned-chinanews-chinese" ) try: tokenizer = AutoTokenizer.from_pretrained( bert_model, local_files_only=True ) model = AutoModelForSequenceClassification.from_pretrained( bert_model, local_files_only=True ) except (OSError, ValueError, ImportError): logger.info(f"📡 Downloading BERT model: {bert_model}...") tokenizer = AutoTokenizer.from_pretrained(bert_model) model = AutoModelForSequenceClassification.from_pretrained( bert_model ) ``` ### Technical Analysis Model repositories are referenced by mutable names rather than immutable commit revisions or verified artifact hashes. A repository owner, compromised account, upstream service incident, or unsafe environment configuration could cause different artifacts to be downloaded after the Skill has been reviewed. The `BERT_SENTIMENT_MODEL` environment variable additionally controls the repository identifier. This does not by itself constitute a remote-code execution path in the displayed calls, and the reviewed code does not expl ...[truncated 1349 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin each model and tokenizer to an immutable repository commit using the `revision` argument. 2. Record and verify cryptographic hashes of all downloaded files. 3. Prefer pre-reviewed local artifacts and use `local_files_only=True` in production. 4. Restrict `BERT_SENTIMENT_MODEL` to an explicit allowlist of approved repositories and revisions. 5. Prefer `safetensors` model files and disable pickle-based formats where possible. 6. Keep `trust_remote_code=False` explicit. 7. Download and validate models during a controlled build or deployment phase instead of during normal Skill execution. 8. Use a dedicated cache with restricted permissions and reject symbolic links. 9. Generate a software and model bill of materials containing repository, revision, file hashes, and license information. 10. Fail closed when an approved pinned model is unavailable rather than silently downloading a mutable replacement. ]]>
Vulnerability Patterns
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (98)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the primary behavior is test/import scaffolding with no actual signal tracking, the skill is mislabeled in a way that defeats effective security review. Misrepresentation of purpose is itself a meaningful vulnerability in agent ecosystems because trust and permissions are granted based on manifest semantics.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/utils/predictor/evaluation.py:59

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/utils/predictor/training.py:308