/**
 * CSS attack vectors: (please add if you find more)
 *
 * - IE 5, 6, and 7 support computed properties via injecting JS with expression().
 * - JS can be executed in place of a url():
 *   - backround-color: "javascript:alert(1)"
 * - CSRF is possible using the url() function.
 * - The -moz-binding property for attaching XBL requires a URL.
 * - The url/expression/javascript/etc exploits can also be accessed by using hexadecimal notation, ie `\\75\\72\\6C` is the hexadecimal representation of `url`.
 *
 * Resources:
 * - https://code.google.com/p/google-caja/wiki/CssAllowsArbitraryCodeExecution
 * - https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#RULE_.234_-_CSS_Escape_And_Strictly_Validate_Before_Inserting_Untrusted_Data_into_HTML_Style_Property_Values
 */
import { Style } from "./types";

const valueFilters = [
  // prevent injecting additional rules
  /;/,
  // prevent injecting script tags
  /[<>]/,
  // prevent hexadecimal characters
  // (could allow an exploiter to get around the url/expression/javascript rules)
  /\\/,
  // block all other @-rules, to be extra safe
  /@[a-z-]+/i,
  /expression/i,
  /url/i,
  /javascript/i,
];

export function filterStyleValues(dirty: Style = {}): Style {
  const clean = {} as Style;

  Object.keys(dirty).forEach((key) => {
    const value = String(dirty[key]);
    const unsanitary = valueFilters.some((regex) => regex.test(String(value)));

    if (unsanitary) return;

    clean[key] = value;
  });

  return clean;
}
