브라우저 확장 - 기능을 안전하게 통합

누구나 Github UI에서 Code Tours를 실행할 수 있도록 Chrome 및 Firefox에 새로운 확장 프로그램을 게시했습니다. 코드 둘러보기 및 확장에 대한 자세한 내용은 이 블로그 게시물을 참조하세요.




단계별로 정확히 똑같이 할 수 있는 방법에 대한 시리즈를 작성하는 것이 좋을 것이라고 생각했습니다.

이 다섯 번째 블로그 게시물은 기능을 웹사이트에 안전하게 통합하는 데 중점을 둘 것입니다.

촉박 한 통보



확장의 이 부분에서는 일부 외부 모듈을 가져올 수 있어야 합니다.

이 게시물에서는 웹팩 설정 방법을 설명하지 않겠지만, 관심이 있는 내용이 있다면 댓글을 남겨주세요. 이에 대한 시리즈의 다른 게시물을 작성할 수도 있습니다.

우리가 만들고 있는 것



다음은 이 게시물의 끝 부분에 있는 내용의 스크린샷입니다. 코드 둘러보기 단계에 대한 설명을 안전하게 표시합니다.



도전



사용자에게 코드 둘러보기를 표시하기 위해 구현한 여러 단계는 다음과 같습니다.
  • 투어 목록 찾기
  • 각 코드 둘러보기의 콘텐츠 가져오기
  • 오른쪽 페이지로 리디렉션

  • 이제 Code Tour의 콘텐츠가 있는 올바른 위치에 있으므로 이를 페이지에 로드해야 합니다.

    코드 투어의 콘텐츠는 Markdown 언어를 사용하여 작성됩니다. Markdown에서 html을 생성하는 방법이 있지만 안전한지 확인해야 합니다.

    하지만 먼저 기본 버전을 빌드해 봅시다!

    순진한 버전



    먼저 UI에 직접 텍스트를 추가해 보겠습니다. 지금까지 작성한 코드는 다음과 같습니다.

    function forwardRequest(message) {
      return new Promise((resolve, reject) => {
        chrome.runtime.sendMessage(message, (response) => {
          if (!response) return reject(chrome.runtime.lastError);
          return resolve(response);
        });
      });
    }
    
    document.addEventListener("DOMContentLoaded", async () => {
      const urlParams = new URLSearchParams(window.location.search);
      const title = urlParams.get("code-tour-title");
      if (!title) return;
    
      const tour = await forwardRequest({ title });
    
      const step = urlParams.get("step");
      console.log(tour.steps[step]);
    });
    

    이제 상태를 기록하는 대신 오른쪽 줄에 둘러보기에 대한 설명을 추가해 보겠습니다.

    document.addEventListener("DOMContentLoaded", async () => {
      const urlParams = new URLSearchParams(window.location.search);
      const title = urlParams.get("code-tour-title");
      if (!title) return;
    
      const tour = await forwardRequest({ title });
    
      const step = urlParams.get("step");
    
      // We'll add the description on the right line
      const parent = document.querySelector(
        `#LC${tour.steps[step].line}.blob-code`
      );
      const section = document.createElement("div");
    
      const span = document.createElement("span");
      span.innerHTML = tour.steps[step].description;
    
      section.append(span);
    
      // A bit of style
      section.setAttribute(
        "style",
        `
        padding: 14px;
        margin: 14px;
        border: 1px lightgrey solid;
        background-color: white;
        border-radius: 1em;
        font-family: sans-serif;
        `
      );
    
      parent.append(section);
    });
    

    마크다운을 HTML로 변환



    Markdown을 HTML로 변환하기 위해 showdown 과 같은 생성기를 사용할 수 있습니다. 사용하기 정말 쉽습니다.

    const showdown = require('showdown')
    const converter = new showdown.Converter()
    const htmlString = converter.makeHtml(yourMarkdownString)
    

    이제 이것을 섹션의 내부 HTML로 사용할 수 있습니다.

    span.innerHTML = converter.makeHtml(tour.steps[step].description);
    

    Markdown을 사용한 XSS 삽입



    Markdown 생성은 html을 작성할 수 있으므로 위험한 코드도 생성할 수 있습니다. 다음 Markdown 코드를 고려하십시오.

    [XSS injection](javascript:alert('xss'))
    

    이 코드와 함께 html 생성기(예: showdown )를 사용하면 다음 html을 얻을 수 있습니다.

    <p><a href="javascript:alert('xss')">XSS injection</a></p>
    

    브라우저에서 이것을 시도하십시오. 클릭하면 JavaScript가 실행됩니다. 물론 이것은 매우 기본적인 예이지만 이것을 악용하는 더 복잡한 방법이 많이 있습니다. 그리고 우리가 로드하는 코드 둘러보기는 신뢰할 수 없는 코드이므로 사용자를 더 잘 보호합니다!

    XSS로부터 보호



    xss로부터 보호하기 위해 사용할 수 있는 몇 가지 라이브러리가 있습니다. 예를 들어 npm의 xss 라이브러리입니다.

    이를 사용하여 HTML의 위험한 부분을 피할 수 있습니다. 다음과 같이 사용하십시오.

    filterXSS(converter.makeHtml(rawText))
    

    우리 코드에서 사용해봅시다:

    span.innerHTML = filterXSS(converter.makeHtml(tour.steps[step].description));
    

    이제 사용자가 보호됩니다.

    결론



    이 게시물에서 기억해야 할 한 가지 사항이 있다면 다음과 같습니다.

    don't trust external inputs, even if it's text



    제어할 수 없는 대상에 어떤 종류의 변환을 적용하는 즉시 악용될 위험이 있습니다. 그리고 저를 믿으세요. 코드가 브라우저의 모든 웹사이트에 로드될 수 있는 확장 프로그램에 있으면 훨씬 더 나빠집니다.

    다음 게시물에서는 이 확장을 다른 상점에 배포하는 방법을 살펴보겠습니다. 게시글이 나왔을 때 확인하고 싶다면 여기를 팔로우하세요.


    .ltag__user__id__462103 .follow-action-button {
    배경색: #ffffff !important;
    색상: #000000 !중요;
    테두리 색상: #000000 !중요;
    }



    캉탱 메노레



    Engineering Manager @Doctolib – Mostly writing about TypeScript / JavaScript





    사진 제공: Ricardo Gomez Angel on Unsplash

    좋은 웹페이지 즐겨찾기