Skip to content

Security: mitigate multiple DOM-based XSS via unsanitized properties and insecure resolveUrl bypass #5752

@JoshuaProvoste

Description

@JoshuaProvoste

Technical Analysis: DOM-Based XSS Vulnerabilities in Polymer (v3.5.2)

This document provides a consolidated technical analysis of two security issues identified within the Polymer framework during recent audits. These findings are documented for further review and remediation planning.


1. Issue: Unsanitized Data Binding to inner-h-t-m-l

Description

Polymer's template system allows direct binding to the inner-h-t-m-l property without automatic sanitization. This architectural decision can lead to XSS vulnerabilities if untrusted data is bound directly to the DOM.

Technical Details

  • Sink: inner-h-t-m-l attribute in Polymer templates.
  • Pattern: <div inner-h-t-m-l="[[untrustedData]]"></div>
  • Root Cause: Absence of a default security interceptor for sensitive DOM properties in the framework's core data-binding logic.

Impact

Arbitrary HTML/JS injection in the context of the user's session.

Remediation Proposals

A. Developer-Level: Contextual Binding

Always prefer standard data binding to textContent or non-sensitive attributes.

<div>[[untrustedData]]</div> <!-- Safe: Polymer uses textContent -->

B. Framework-Level: Global Sanitizer Registration

Implement a global interceptor using Polymer.sanitizeDOMValue. This function can be defined to sanitize or block sensitive property bindings.

import { sanitizeDOMValue } from '@polymer/polymer/lib/utils/settings.js';

// Global interceptor that could be integrated into the framework's core
Polymer.sanitizeDOMValue = function(value, name, type, node) {
  if (name === 'inner-h-t-m-l') {
    // Implement robust sanitization (e.g., using DOMPurify)
    return MySanitizer.sanitize(value);
  }
  return value;
};

2. Issue: Insecure URL Resolution (ABS_URL Bypass)

Description

The resolveUrl utility in Polymer relies on a flawed regular expression to identify "Absolute URLs". This allows malicious protocol schemes (e.g., javascript:, data:, vbscript:) to be returned without sanitization, bypassing basic path normalization.

Technical Details

  • Vulnerable Regex: /(^\/[^\/])|(^#)|(^[\w-\d]*:)/
  • Pattern: this.resolveUrl(urlInput)
  • Root Cause: The regex incorrectly assumes that any scheme (word followed by a colon) is a safe absolute URL, failing to implement a protocol whitelist.

Impact

Arbitrary JavaScript execution upon user interaction with a resolved link (e.g., clicking an <a> tag).

Remediation Proposals

A. Protocol Whitelist in ABS_URL Regex

The primary defense is to restrict the ABS_URL regex to a known-safe whitelist of protocols (e.g., http, https, mailto).

- const ABS_URL = /(^\/[^\/])|(^#)|(^[\w-\d]*:)/;
+ const ABS_URL = /(^\/[^\/])|(^#)|(^(https?|mailto|tel):)/i;

B. Protocol Sanitization Logic

Add an explicit check for executable protocol schemes (like javascript:) within the resolveUrl function to ensure they are never returned as-is.

function resolveUrl(url, base) {
  if (ABS_URL.test(url)) {
    // Robust check: prevent bypasses if the regex fails for any reason
    const protocol = (url.split(':')[0] || '').toLowerCase();
    const unsafeProtocols = ['javascript', 'data', 'vbscript'];
    if (unsafeProtocols.includes(protocol)) {
      return 'about:blank'; // Or a safe fallback
    }
    return url;
  }
  // ... rest of resolution logic
}

🛠️ Automated Detection: eslint-plugin-polymer-security

A specialized ESLint plugin has been developed to help detect these patterns during development:

  • Plugin: eslint-plugin-polymer-security
  • Rules:
    • no-inner-h-t-m-l-binding: Identifies unsafe bindings to inner-h-t-m-l.
    • no-insecure-url-resolution: Identifies dynamic (non-literal) inputs to resolveUrl.

Conclusion

Both issues highlight the need for careful input validation and sanitization when working with Polymer templates and URL resolution utilities. These findings are intended to support the hardening of Polymer-based applications.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions