FlawOpen

flawopen.com/Teardowns/cve-2026-102422-shell-quote-comment-line-terminator-injection

● CVE-2026-102422 · CVSS 8.1 · 높음
보안 연구 · FlawOpen

CVE-2026-102422: shell-quote 주석 토큰 인젝션

shell-quote 1.11.0 이전에는 주석 토큰 뒤에 줄 종료 문자가 든 문자열이 오면, 인용된 출력을 POSIX 셸에 전달할 때 의미가 바뀔 수 있었습니다. 공격자가 토큰에 영향을 주고, quote()를 호출하며, 출력을 셸에서 실행해야 합니다. 1.11.0 이상으로 업데이트하세요.

💡 알기 쉬운 설명 (ELI5)

라벨의 주석은 그 줄의 나머지 내용을 숨길 수 있습니다. 다음 부분에 줄바꿈이 있으면 주석이 일찍 끝나고 뒤의 내용이 다시 드러납니다. 이 결함은 후속 토큰이 셸용 인용 출력에서 이런 상황을 만들 수 있게 했습니다.

핵심 개념 및 용어

shell-quote
셸 형태 토큰을 파싱하고 인용하는 JavaScript 패키지입니다. 출력은 셸 문법용이며 범용 안전 문자열 형식이 아닙니다.
주석 토큰
셸 주석 문법을 나타내며 줄 종료 문자가 나올 때까지 뒤의 텍스트에 영향을 줄 수 있는 토큰입니다.
줄 종료 문자
CR, LF, U+2028, U+2029 같은 줄 경계이며 셸은 이를 주석의 끝으로 처리할 수 있습니다.
CWE-78
운영체제 명령의 특수 요소를 적절히 무력화하지 못한 취약점입니다.

프레임워크 매핑

  • 이 가이드에서 설명하는 약점의 CWE 참조: CWE-78

근본 원인 분석 (Root Cause)

영향받는 quote() 경로는 주석 토큰 안의 줄 종료 문자는 거부했지만, 주석을 이미 출력했는지 기록하지 않았습니다. 따라서 뒤따르는 문자열 토큰에 줄 종료 문자가 들어갈 수 있었습니다. 공격자가 영향을 준 토큰이 quote()를 거치고 반환된 텍스트가 POSIX 셸에서 실행되면, 줄 경계가 주석을 끝내고 셸은 뒤의 텍스트를 문법으로 해석합니다. 업스트림 수정은 주석 상태를 기록하고 이후 모든 문자열 토큰의 줄 종료 문자를 거부합니다. 이는 주석 토큰 자체의 줄 종료 문자를 거부한 CVE-2026-9277 수정과 다른 문제입니다. 관리자는 High, CVSS 3.1 8.1로 평가하고 Ubuntu는 별도로 CVSS 4.0 9.2 Critical을 게시했습니다. 서로 다른 CVSS 버전이므로 점수를 같은 기준으로 취급하면 안 됩니다.

단계별 공격 실행 흐름

단계 1

토큰이 인용 함수에 전달됨

앱이 주석과 뒤따르는 문자열이 있는 토큰을 구성하며 공격자가 그 순서에 영향을 줄 수 있어야 합니다.

단계 2

함수가 주석 문법을 출력함

1.11.0 이전 quote()는 주석 텍스트를 검사했지만 그 뒤에 문자열이 오는지는 기억하지 않았습니다.

단계 3

후속 토큰에 줄 경계가 있음

CR, LF, U+2028, U+2029가 셸 주석을 끝낼 수 있습니다.

단계 4

앱이 셸에서 출력을 실행함

문서화된 셸 해석은 출력을 POSIX 셸에 전달하는 호출자에게 해당합니다.

단계 5

업데이트가 위험한 순서를 거부함

1.11.0은 주석 상태를 기록하고 후속 문자열에 줄 종료 문자가 있으면 오류를 발생시킵니다.

소스 코드 비교: 취약한 구현 vs 보안 패치

취약한 코드 발췌는 주석 토큰의 줄 종료 문자를 검사하지만 후속 문자열의 상태를 기록하지 않습니다. 업스트림 변경은 주석이 출력된 상태를 저장하고 줄 종료 문자가 든 후속 문자열을 거부합니다. 이 발췌는 파싱과 인용의 경계를 설명하며 익스플로잇이나 셸 명령이 아닙니다.

소스 코드 발췌: quote.js — focused upstream diff hunks

취약한 구현
// 커밋 6002b2e 이전 quote.js — 주석 토큰 관련 부분
if ('comment' in s && typeof s.comment === 'string') {
  if (LINE_TERMINATORS.test(s.comment)) {
    throw new TypeError('`comment` must not contain line terminators');
  }
  return '#' + s.comment;
}
보안 강화 패치
// 커밋 6002b2e 이후 quote.js — 추가된 가드와 주석 상태의 정확한 부분
var sawComment = false;
return xs.map(function (s) {
  if (sawComment && typeof s === 'string' && LINE_TERMINATORS.test(s)) {
    throw new TypeError('a token after a `comment` must not contain line terminators');
  }
  if ('comment' in s && typeof s.comment === 'string') {
    if (LINE_TERMINATORS.test(s.comment)) {
      throw new TypeError('`comment` must not contain line terminators');
    }
    sawComment = true;
    return '#' + s.comment;
  }
});

엔지니어링 및 시스템 보안 강화 체크리스트

출처