go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/analysis/frontend/ui/src/components/sanitized_html/sanitize_html/sanitize_html.ts (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import createDomPurify from 'dompurify';
    16  
    17  const domPurify = createDomPurify(window);
    18  
    19  // Mitigate target="_blank" vulnerability.
    20  domPurify.addHook('afterSanitizeAttributes', (node) => {
    21    if (!['A', 'FORM', 'AREA'].includes(node.tagName)) {
    22      return;
    23    }
    24  
    25    // Note: rel="noopener" is added when the target is not set because <base> can
    26    // set the default target to _blank.
    27    if (
    28      ['_self', '_top', '_parent'].includes(node.getAttribute('target') || '')
    29    ) {
    30      return;
    31    }
    32  
    33    const existingRef = node.getAttribute('rel') || '';
    34    if (!/\bnoopener\b/i.test(existingRef)) {
    35      node.setAttribute('rel', (existingRef + ' noopener').trim());
    36    }
    37  });
    38  
    39  /**
    40   * Sanitizes the input HTML string.
    41   */
    42  export function sanitizeHTML(html: string): string;
    43  export function sanitizeHTML(
    44    html: string,
    45    opts: { RETURN_TRUSTED_TYPE: true },
    46  ): TrustedHTML;
    47  export function sanitizeHTML(
    48      html: string,
    49      opts?: { RETURN_TRUSTED_TYPE: true },
    50  ): string | TrustedHTML {
    51    return domPurify.sanitize(html, {
    52      ADD_ATTR: ['target', 'artifact-id', 'inv-level'],
    53      ADD_TAGS: ['text-artifact'],
    54      RETURN_TRUSTED_TYPE: opts?.RETURN_TRUSTED_TYPE,
    55    });
    56  }
    57  
    58  export default sanitizeHTML;