CodeQL과 yarn npm audit으로 보안 스캐너 보강하기

2026-05-20 hit count image

공급망 cooldown만으로는 막지 못하는 두 가지 — "이미 의존 트리에 들어와 있는 알려진 CVE"와 "우리 코드 자체의 취약점" — 을 각각 yarn npm audit과 GitHub CodeQL로 막는 방법을 실제 사고 예시와 함께 정리합니다.

web

들어가며

공급망 공격 시리즈에서 cooldown은 “갓 게시된 악성 버전”을 막는 시간 기반 게이트라고 다뤘습니다. 그러나 다음 두 가지는 cooldown 영역 밖입니다.

  1. 이미 의존 트리에 들어와 있는 패키지에서 새로 발견된 CVE — 게시 후 한참 지나 정상으로 인정받은 버전에서 뒤늦게 발견되는 취약점
  2. 우리 코드 자체의 취약점 — XSS, 프로토타입 오염, 인젝션 같은 own-code 결함

이 두 가지를 막는 데에 가장 효과적인 두 스캐너 — yarn npm audit과 GitHub CodeQL — 를 다룹니다.

어떤 위험이 있는가

위험 1. 이미 들어와 있는 의존성의 새 CVE

cooldown은 신규 게시 단계에서만 작동합니다. 그런데 보안 취약점은 게시 후 수개월·수년이 지난 뒤 발견되는 경우가 더 흔합니다. 다음 사례들이 대표적입니다.

  • Log4Shell (2021, CVE-2021-44228): 8년간 정상으로 알려졌던 Log4j에서 critical RCE 발견
  • lodash prototype pollution (CVE-2019-10744): 수년간 안정적으로 사용된 lodash에서 prototype pollution 발견
  • xmldom 등 수많은 XML 파서 취약점: 오래 사용된 라이브러리에서 주기적으로 발견되는 XXE/RCE

이 종류의 위험은 “우리가 지금 쓰고 있는 의존성에 알려진 CVE가 있는가?”라는 질문에 답해야 막을 수 있습니다.

위험 2. 우리 코드 자체의 취약점

공급망 방어가 잘 되어 있어도, 우리가 작성한 코드에 다음과 같은 결함이 있다면 그 자체가 공격 경로가 됩니다.

  • DOM 조작 시 innerHTML로 사용자 입력을 그대로 삽입 → XSS
  • 객체 병합 시 __proto__ 키 검증 누락 → prototype pollution
  • 정규식에서 catastrophic backtracking → ReDoS
  • 동적 import() 경로에 사용자 입력 → import injection

이런 결함은 의존성 cooldown으로는 절대 막을 수 없습니다. 자체 코드를 정적 분석해야 잡힙니다.

yarn npm audit: 의존성의 알려진 CVE 탐지

yarn npm audit은 lockfile의 의존성을 GitHub Advisory Database와 매칭해서 알려진 CVE를 찾아 줍니다. PR 단계에서 게이트로 추가하면, 새 CVE가 트리에 추가될 때마다 PR이 실패합니다.

CI 워크플로우에 추가

# .github/workflows/check_audit.yml
name: Dependency Audit
on:
  pull_request:
  schedule:
    - cron: '0 0 * * *'   # 매일 1회 점검

permissions:
  contents: read

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<SHA> # v6
      - uses: actions/setup-node@<SHA> # v6
      - run: corepack enable
      - run: yarn install --immutable
      - run: yarn npm audit --severity high --recursive

옵션 의미:

옵션설명
--severity highhigh 이상 심각도만 실패로 처리
--recursive모노레포 전체 워크스페이스 검사

효과

  • 새 CVE가 등록되면 다음 PR이나 다음날 cron에서 즉시 실패
  • “이 CVE가 우리에게 영향있는가?”라는 질문에 매일 자동으로 답이 나옴
  • false positive가 많으면 --severity critical로 한 단계 더 좁힐 수 있음

CodeQL: 우리 코드의 취약점 탐지

GitHub CodeQL은 public 리포지토리에 무료이며, private 리포지토리에서도 GitHub Code Scanning 기능으로 사용 가능합니다 (GitHub Advanced Security 라이선스).

CodeQL은 코드를 데이터베이스로 변환한 뒤, 보안 쿼리(미리 정의된 수백 개의 규칙)를 SQL처럼 실행해 취약점을 찾습니다. JavaScript/TypeScript의 경우 다음 종류의 결함을 매우 잘 잡습니다.

  • XSS (반영형, 저장형, DOM 기반)
  • Prototype pollution
  • ReDoS (정규식 거부 서비스)
  • 안전하지 않은 deserialization
  • 인젝션 (SQL, command, path traversal 등)

CI 워크플로우에 추가

# .github/workflows/codeql.yml
name: CodeQL
on:
  push:
    branches: [main]
  pull_request:
  schedule:
    - cron: '0 0 * * 1'   # 매주 월요일 전체 스캔

permissions:
  contents: read
  security-events: write

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<SHA> # v6
      - uses: github/codeql-action/init@<SHA>
        with:
          languages: javascript-typescript
      - uses: github/codeql-action/analyze@<SHA>

분석 결과는 GitHub Security 탭의 “Code scanning alerts”에 표시되며, PR에도 자동으로 인라인 댓글이 달립니다.

실제 사례

GitHub Security Lab은 Community CodeQL Bounty Program 을 운영하며 — 커뮤니티가 작성한 CodeQL 쿼리들이 — 실제 오픈소스 프로젝트들에서 다수의 CVE를 발견한 사례를 공식 블로그에서 정리하고 있습니다. JavaScript/TypeScript 영역에서는 prototype pollution, ReDoS, XSS, 안전하지 않은 deserialization 같은 패턴 클래스에 대해 사전 정의된 보안 쿼리가 일상적으로 새로운 결함을 잡아내고 있습니다.

자세한 발견 사례 모음은 GitHub Security Lab의 CodeQL Wall of Fame 에서 확인할 수 있습니다.

두 스캐너의 역할 분담

도구무엇을 보는가무엇을 막는가
yarn npm auditlockfile의 의존성알려진 CVE — 데이터베이스에 등록된 취약점
CodeQL자체 소스코드알려지지 않은 own-code 결함 — XSS·인젝션·프로토타입 오염
(참고) cooldown새로 게시되는 버전신규 악성 게시 — 막 npm에 올라온 백도어
(참고) Semgrep자체 소스코드 (보완)코드 스타일·시큐어 패턴 규칙

세 가지가 모두 다른 위협을 막습니다. 어느 하나로 다른 둘을 대체할 수 없습니다.

한계

  • yarn npm audit의 false positive: 의존성 트리에 있더라도 실제 사용 경로에서는 호출되지 않는 코드인 경우가 많습니다. 그런데도 PR을 실패시키면 노이즈가 됩니다. --severity 임계값을 조정하거나, 실제 영향 분석은 사람이 판단해야 합니다.
  • CodeQL의 분석 시간: 큰 모노레포에서는 CodeQL 분석에 수십 분이 걸릴 수 있습니다. PR마다 돌리기 부담스러우면 push와 주간 cron에만 적용하는 절충이 좋습니다.
  • 새로 발견되지 않은 CVE: 둘 다 “이미 알려진” 결함을 잡는 도구입니다. 0-day는 별도 영역입니다.

마무리

cooldown이 신규 게시를 거른다면, yarn npm audit과 CodeQL은 이미 들어와 있거나 우리가 직접 만든 위험을 잡습니다. 셋이 함께 운영되어야 공급망 보안이 비로소 다층 구조가 됩니다.

  • 우선 도입한다면 yarn npm audit을 PR 게이트에 추가하는 것이 가장 빠릅니다. 설정 한 번이면 끝
  • CodeQL은 시간이 들지만 own-code 취약점 발견에 매우 효과적입니다. 주간 cron부터 시작해서 점차 PR 게이트로 옮기는 점진적 도입을 권장합니다.

참고 자료

제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!

앱 홍보

책 홍보

블로그를 운영하면서 좋은 기회가 생겨 책을 출판하게 되었습니다.

아래 링크를 통해 제가 쓴 책을 구매하실 수 있습니다.
많은 분들에게 도움이 되면 좋겠네요.



SHARE
Twitter Facebook RSS