apache/superset · warning · Error

security_error

security_error

Error message

Unsafe node type "${nodeType}" at path: ${path.join('.')}. Only static data structures are allowed.

What it means

The same /redirect/ route aborts 400 'Invalid URL scheme' when urlparse(target_url).scheme.lower() is in DANGEROUS_SCHEMES = {javascript, data, vbscript, file} (superset/views/redirect.py:39,67). This blocks script-execution and local-file schemes from being bounced through Superset's redirector — a defense against attackers crafting malicious links inside alert/report content. The block is logged at warning level with the first 80 chars of the URL.

Source

Thrown at superset-frontend/plugins/plugin-chart-echarts/src/utils/safeEChartOptionsParser.ts:220

  'require',
  'import',
  'module',
  'exports',
]);

/**
 * Recursively validates that an AST node contains only safe constructs.
 * Throws an error if any unsafe patterns are detected.
 */
function validateNode(node: Node, path: string[] = []): void {
  if (!node || typeof node !== 'object') {
    return;
  }

  const nodeType = node.type;

  if (!SAFE_NODE_TYPES.has(nodeType)) {
    throw new Error(
      `Unsafe node type "${nodeType}" at path: ${path.join('.')}. ` +
        `Only static data structures are allowed.`,
    );
  }

  switch (nodeType) {
    case 'Identifier': {
      const identNode = node as Node & { name: string };
      if (DANGEROUS_IDENTIFIERS.has(identNode.name)) {
        throw new Error(
          `Dangerous identifier "${identNode.name}" detected at path: ${path.join('.')}`,
        );
      }
      break;
    }

    case 'UnaryExpression': {
      const unaryNode = node as Node & { operator: string; argument: Node };

View on GitHub (pinned to f4587218dd)

Solutions

  1. Use only http:// or https:// (or relative/internal) URLs as redirect targets
  2. Sanitize user-supplied link fields at the point of storage (dashboard markdown, alert text) with an allowlist of schemes
  3. Treat occurrences in logs as hostile-content signals: trace which alert/report produced the link

Example fix

# before
link = user_provided_url  # may be 'javascript:...' -> 400 + security log

# after
from urllib.parse import urlparse
if urlparse(user_provided_url).scheme.lower() not in ("http", "https", ""):
    link = None  # drop or reject
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse
DANGEROUS = {"javascript", "data", "vbscript", "file"}

def scheme_allowed(url: str) -> bool:
    return urlparse(url).scheme.lower() not in DANGEROUS

Type guard

const DANGEROUS = new Set(["javascript", "data", "vbscript", "file"]);
const isSafeScheme = (u: string): boolean =>
  !DANGEROUS.has(new URL(u, "https://example.invalid").protocol.replace(":", "").toLowerCase());

Prevention

When it happens

Trigger: GET /redirect/?url=javascript:alert(1), url=data:text/html;base64,..., url=file:///etc/passwd, or url=vbscript:... — including mixed-case scheme variants (JAVASCRIPT:, Java​Script:) since the check lowercases the parsed scheme.

Common situations: User-controlled dashboard text or alert payloads being interpolated into redirect targets; security testing/pen-test scans of the email links; legitimate file:// links in internal tooling that must be removed because Superset will never allow them.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/b44bd66c01cd5418. Report an issue: GitHub.