Back to skill

Security audit

Polaris

Security checks for vulnerabilities and agentic risk

Overview

The skill is a cloud market-intelligence connector, but its documentation understates that user inputs like portfolio holdings, strategies, topics, and URLs are sent to the Polaris API.

Review before installing. Use it only if you are comfortable sending research queries, portfolio tickers and weights, strategy JSON, report requests, and submitted URLs to api.thepolarisreport.com. Avoid entering real portfolio allocations or URLs containing tokens, passwords, signed links, private document identifiers, or session material unless the publisher provides clearer privacy and retention guarantees.

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

Warning
Location
index.js:590
Finding

Undisclosed transmission of user queries and portfolio composition to a remote service

Content
View full analysis

Vulnerability Details

File Location: index.js:8, index.js:590-616, SKILL.md:93-97, README.md:36-40
Vulnerability Type: Misleading privacy disclosure and transmission of sensitive financial data
Risk Level: Medium

Vulnerable Code

index.js:8 states:

js
 * No credentials, tokens, or user data are sent or stored.

index.js:590-616 transmits portfolio holdings and allocation weights:

js
const input = (args || "").trim();
if (!input) {
  return "Usage: /portfolio [ticker:weight, ...]\nExample: /portfolio NVDA:0.30 AAPL:0.25 TSLA:0.20 MSFT:0.25\nWeights are optional (default 0 = equal).";
}

// Parse holdings: "NVDA:0.30 AAPL:0.25" or "NVDA AAPL TSLA"
const tokens = input.split(/[\s,]+/).filter(Boolean);
const holdings = tokens.map(tok => {
  const parts = tok.split(":");
  const ticker = parts[0].toUpperCase();
  const weight = parts[1] ? Math.min(1, Math.max(0, parseFloat(parts[1]) || 0)) : 0;
  return { ticker, weight };
}).filter(h => h.ticker);

// If no weights provided, distribute equally
const hasWeights = holdings.some(h => h.weight > 0);
if (!hasWeights) {
  const equal = Math.round((1 / holdings.length) * 100) / 100;
  for (const h of holdings) h.weight = equal;
}

if (holdings.length === 0) {
  return "No valid tickers provided. Usage: /portfolio NVDA:0.30 AAPL:0.25";
}

const res = await fetch(`${API_BASE}/api/v1/portfolio/feed`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ holdings }),
});

SKILL.md:93-97 makes the following claims:

md
- **Read-only**: Only fetches public data. Does not write, modify, or delete anything.
- **No credentials**: No API keys or tokens required.
- **No user data**: Queries are not stored or shared.
- **Single domain**: All requests go to `api.thepolarisreport.com` only.

Technical Analysis

The Skill necessarily transmits us ...[truncated 2022 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the statement that no user data is sent with an explicit explanation that command inputs are transmitted to api.thepolarisreport.com for processing.
  2. Identify the exact data fields transmitted by each command, especially portfolio holdings, allocation weights, strategies, queries, topics, and URLs.
  3. Require explicit confirmation before the first submission of portfolio data or trading strategies.
  4. Provide an option to omit allocation weights or reduce their precision before transmission.
  5. Document the remote service's retention period, access controls, deletion process, subprocessors, and sharing policy.
  6. Avoid claiming that data is not stored unless that property is technically enforced and independently verifiable.
  7. Add a clear privacy notice directly to sensitive command usage messages rather than relying only on external documentation.

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:771
Finding

Unvalidated crawl URLs may disclose embedded secrets to the remote crawler

Content
View full analysis

Vulnerability Details

File Location: index.js:771-783
Vulnerability Type: Unsafe forwarding of arbitrary URLs to a third-party service
Risk Level: Medium

Vulnerable Code

js
// ── /crawl [url] ────────────────────────────────────────────────────────────

async function handleCrawl(args) {
  const url = (args || "").trim();
  if (!url) {
    return "Usage: /crawl [url]\nExample: /crawl https://example.com/article";
  }

  const res = await fetch(`${API_BASE}/api/v1/crawl`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ url, depth: 1, max_pages: 1, include_links: false }),
  });

Technical Analysis

The /crawl handler accepts an arbitrary string and forwards it in full to api.thepolarisreport.com. It does not parse the value as a URL, restrict the protocol, reject embedded credentials, detect secret-bearing query parameters, or warn that crawling is performed by remote infrastructure.

URLs can contain sensitive information such as:

  • HTTP basic-auth usernames and passwords
  • Password-reset or account-verification tokens
  • Signed cloud-storage query parameters
  • Temporary download credentials
  • Private document identifiers
  • Session or API tokens embedded in query strings

Even if the destination page is public, forwarding the complete URL exposes all embedded components to the Polaris API. The code also performs no client-side restriction against localhost, loopback, link-local, or private-network destinations. Whether such targets are reachable depends on server-side crawler protections, which are not present in the audited repository and therefore cannot be verified.

Attack Path

  1. An attacker, webpage, or untrusted instruction persuades the user or Agent to crawl a URL containing a temporary token or embedded credential.
  2. The /crawl handler accepts the URL without validation or redaction.
  3. The co ...[truncated 885 chars]
Remediation
View remediation

Remediation Suggestions

  1. Parse inputs with the standard URL constructor and reject malformed values.
  2. Permit only https: URLs unless another protocol is explicitly required.
  3. Reject URLs containing username or password components.
  4. Warn users that the URL will be transmitted to and fetched by remote Polaris infrastructure.
  5. Detect common secret-bearing query parameters such as token, key, signature, password, and session; require explicit confirmation or reject them.
  6. Block loopback, localhost, link-local, private-network, metadata-service, and non-routable destinations.
  7. Apply the same validation after every redirect on the remote crawler.
  8. Configure the remote crawler with DNS rebinding defenses, strict egress filtering, response-size limits, timeouts, and disabled access to cloud metadata endpoints.
  9. Avoid logging complete submitted URLs; redact credentials and sensitive query values in telemetry and error messages.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest explicitly markets the skill as "read-only, no credentials required," but the documented /alerts create capability implies state-changing behavior and outbound webhook delivery. This mismatch can mislead users and host systems about the skill’s trust boundary, causing them to invoke it in contexts where write actions or external data transmission would not be expected.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The header explicitly tells users that all requests are read-only and that no user data is sent or stored, but the implementation makes multiple POST requests carrying user-supplied inputs such as topics, URLs, holdings, strategies, and tickers to a remote service. This is dangerous because it creates a misleading privacy and data-flow guarantee; users may submit sensitive research queries, portfolio composition, or URLs under false assumptions about how their data is handled.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The /portfolio command sends the user's holdings and weights to a third-party API without an inline warning or explicit consent at the point of use. Portfolio composition is often sensitive financial information, so silent transmission to a remote service can expose private investment positions and strategies to logging, retention, or secondary processing by the provider.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The alert feature references webhook delivery but provides no warning that user-supplied parameters may cause data to be transmitted to external destinations. In a skill that otherwise presents itself as safe and read-only, this increases the risk of inadvertent data exfiltration, SSRF-style misuse, or users authorizing outbound notifications without understanding where information will be sent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.