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
- Use only http:// or https:// (or relative/internal) URLs as redirect targets
- Sanitize user-supplied link fields at the point of storage (dashboard markdown, alert text) with an allowlist of schemes
- 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
- Allowlist schemes (http/https/relative) on any user-supplied link stored in Superset content
- Never put user-controlled values directly into redirect targets; log occurrences — they usually indicate injected content
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:, JavaScript:) 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
- validation_error
- Please provide both time bounds (Since and Until)
- All values must be numeric
- Data URI is not allowed.
- Error loading data from cache
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/b44bd66c01cd5418.
Report an issue: GitHub.