<commit_before>import * as React from 'react'
import * as FSE from 'fs-extra'
import * as Path from 'path'
import crypto from 'crypto'

interface ISandboxedMarkdownProps {
  /** A string of unparsed markdownm to display */
  readonly markdown: string
}

/**
 * Parses markdown into html and outputs it inside a sandboxed iframe.
 **/
export class SandboxedMarkdown extends React.PureComponent<
  ISandboxedMarkdownProps
> {
  private frameRef: HTMLIFrameElement | null = null

  private onFrameRef = (frameRef: HTMLIFrameElement | null) => {
    this.frameRef = frameRef
  }

  public async componentDidMount() {
    this.mountIframeContents()
  }

  public async componentDidUpdate(prevProps: ISandboxedMarkdownProps) {
    // rerender iframe contents if provided markdown changes
    if (prevProps.markdown !== this.props.markdown) {
      this.mountIframeContents()
    }
  }

  private mountIframeContents = async (): Promise<void> => {
    if (this.frameRef === null || this.frameRef.contentDocument === null) {
      return
    }

    const markedJS = await FSE.readFile(
      Path.join(__dirname, 'static', 'marked.min.js'),
      'utf8'
    )

    const css = await FSE.readFile(
      Path.join(__dirname, 'static', 'markdown.css'),
      'utf8'
    )

    // Prevents any script without the generated nonce (number used once)
    const nonce = crypto.randomBytes(16).toString('base64')
    const contentSecurityPolicy = `script-src 'nonce-${nonce}'`

    // get colors
    const textColor = 'black'
    const backgroundColor = 'white'
    const codeBackgroundColor = 'rgb(110 118 129 / 40%)'
    const boxBorderColor = 'grey'

    const testEvilScript = `<script>
    console.log("this one fails.. not csp")
  </script>
   `

    this.frameRef.srcdoc = `
    <meta http-equiv="Content-Security-Policy"
      content="${contentSecurityPolicy}">

    <style>
      :root {
        --text-color: ${textColor};
        --background-color: ${backgroundColor};
        --code-background-color: ${codeBackgroundColor};
        --box-border-color: ${boxBorderColor};
      }

      ${css}
    </style>

    <div id="content">

    </div>

    <script nonce="${nonce}">
      ${markedJS}

      var md = atob('${btoa(this.props.markdown)}');
      marked.use({
        gfm: true
      });
      var parsed = marked(md);
      document.getElementById('content').innerHTML = parsed;

      document.querySelector('a').addEventListener('click', e => {
        e.preventDefault();
        window.parent.postMessage(e.toString());
      })
    </script>

    ${testEvilScript}
    `

    window.addEventListener(
      'message',
      event => {
        console.log(event)
      },
      false
    )
  }

  public render() {
    return (
      <iframe
        className="markdown-iframe"
        sandbox="allow-scripts allow-same-origin"
        ref={this.onFrameRef}
      />
    )
  }
}
<commit_msg>Remove use of allow-same-origins for link interception<commit_after>import * as React from 'react'
import * as FSE from 'fs-extra'
import * as Path from 'path'
import crypto from 'crypto'

interface ISandboxedMarkdownProps {
  /** A string of unparsed markdownm to display */
  readonly markdown: string
}

/**
 * Parses markdown into html and outputs it inside a sandboxed iframe.
 **/
export class SandboxedMarkdown extends React.PureComponent<
  ISandboxedMarkdownProps
> {
  private frameRef: HTMLIFrameElement | null = null

  private onFrameRef = (frameRef: HTMLIFrameElement | null) => {
    this.frameRef = frameRef
  }

  public async componentDidMount() {
    this.mountIframeContents()
  }

  public async componentDidUpdate(prevProps: ISandboxedMarkdownProps) {
    // rerender iframe contents if provided markdown changes
    if (prevProps.markdown !== this.props.markdown) {
      this.mountIframeContents()
    }
  }

  private setupLinkInterceptor(frameRef: HTMLIFrameElement): void {
    frameRef.onload = () => {
      if (frameRef.contentDocument === null) {
        return
      }
      const linkTags = frameRef.contentDocument.querySelector('a')
      if (linkTags === null) {
        return
      }

      linkTags.addEventListener('click', (e: MouseEvent) => {
        e.preventDefault()
        const linkPath =
          e.target !== null ? (e.target as HTMLAnchorElement).href : null
        console.log(linkPath)
      })
    }
  }

  private mountIframeContents = async (): Promise<void> => {
    if (this.frameRef === null) {
      return
    }

    const markedJS = await FSE.readFile(
      Path.join(__dirname, 'static', 'marked.min.js'),
      'utf8'
    )

    const css = await FSE.readFile(
      Path.join(__dirname, 'static', 'markdown.css'),
      'utf8'
    )

    // Prevents any script without the generated nonce (number used once)
    const nonce = crypto.randomBytes(16).toString('base64')
    const contentSecurityPolicy = `script-src 'nonce-${nonce}'`

    // get colors
    const textColor = 'black'
    const backgroundColor = 'white'
    const codeBackgroundColor = 'rgb(110 118 129 / 40%)'
    const boxBorderColor = 'grey'

    const testEvilScript = `<script>
    console.log("this one fails.. not csp")
  </script>
   `

    this.frameRef.srcdoc = `
    <meta http-equiv="Content-Security-Policy"
      content="${contentSecurityPolicy}">

    <style>
      :root {
        --text-color: ${textColor};
        --background-color: ${backgroundColor};
        --code-background-color: ${codeBackgroundColor};
        --box-border-color: ${boxBorderColor};
      }

      ${css}
    </style>

    <div id="content">

    </div>

    <script nonce="${nonce}">
      ${markedJS}

      var md = atob('${btoa(this.props.markdown)}');
      marked.use({
        gfm: true
      });
      var parsed = marked(md);
      document.getElementById('content').innerHTML = parsed;
    </script>

    ${testEvilScript}
    `

    this.setupLinkInterceptor(this.frameRef)
  }

  public render() {
    return (
      <iframe
        className="markdown-iframe"
        sandbox="allow-scripts"
        ref={this.onFrameRef}
      />
    )
  }
}

{'fraction_non_alphanumeric': 0.1279394836375596, 'fraction_numerical': 0.005591185660253248, 'mean_word_length': 2.6950182260024302, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6523795', 'n_tokens_mistral': 1906, 'n_tokens_neox': 1820, 'n_words': 424}