    onIgnoreTagAttr(tag, name, value) {
      const forTag = allowList.attrList[tag];
      if (forTag) {
        const forAttr = forTag[name];
        if (
          (forAttr &&
            (forAttr.indexOf("*") !== -1 || forAttr.indexOf(value) !== -1)) ||
          (name.indexOf("data-") === 0 && forTag["data-*"]) ||
          (tag === "a" &&
            name === "href" &&
            hrefAllowed(value, extraHrefMatchers)) ||
          (tag === "img" &&
            name === "src" &&
            (/^data:image.*$/i.test(value) ||
              hrefAllowed(value, extraHrefMatchers))) ||
          (tag === "iframe" &&
            name === "src" &&
            allowedIframes.some((i) => {
              return value.toLowerCase().indexOf((i || "").toLowerCase()) === 0;
            }))
        ) {
          return attr(name, value);
        }

        if (tag === "iframe" && name === "src") {
          return "-STRIP-";
        }

        if (tag === "video" && name === "autoplay") {
          // This might give us duplicate 'muted' attributes
          // but they will be deduped by later processing
          return "autoplay muted";
        }

        // Heading ids must begin with `heading--`
        if (
          ["h1", "h2", "h3", "h4", "h5", "h6"].indexOf(tag) !== -1 &&
          value.match(/^heading\-\-[a-zA-Z0-9\-\_]+$/)
        ) {
          return attr(name, value);
        }

        const custom = allowLister.getCustom();
        for (let i = 0; i < custom.length; i++) {
          const fn = custom[i];
          if (fn(tag, name, value)) {
            return attr(name, value);
          }
        }
      }
    },
The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.