DEEP DIVE REPORT

GraphQL Tools mergeIncrementalResult 프로토타입 오염(CVE-2026-114604): 증분 응답 처리 경계 점검

SecurityDesk
• 2026.10.23 • 조회 3

@graphql-tools/utils의 mergeIncrementalResult 함수는 증분(incremental) GraphQL 응답의 경로(path) 세그먼트를 객체 키로 변환해 결과를 병합합니다. 이 변환 단계에 세그먼트 타입 검증이 빠져 __proto__를 막는 가드가 우회되는 프로토타입 오염(prototype pollution) 취약점 CVE-2026-114604가 보고되었습니다. GitHub 보안 자문 기준 취약 범위는 10.10.1 이상 12.0.1 이하이며, 12.0.2부터는 영향을 받지 않습니다. 아래에서는 자문과 수정 PR로 확인된 사실과, 제공된 근거만으로는 단정할 수 없는 부분을 나눠 정리합니다.

개요

개요 인포그래픽
GraphQL 증분 응답은 응답 조각이 경로를 따라 누적되는 형태입니다. mergeIncrementalResult는 각 경로 세그먼트를 객체 키로 바꿔 대상 객체에 씁니다. 결함은 속성을 쓰기 직전의 키 검증 단계에 있습니다.

  • 취약 함수: mergeIncrementalResult의 경로 워커 내부 setObjectKeyPath
  • 취약 패키지: @graphql-tools/utils
  • 취약 범위: 10.10.1 이상 12.0.1 이하
  • 영향받지 않는 버전: 12.0.2 이상 (12.0.2 자체가 수정·게시 버전이며 이 버전부터 영향을 받지 않습니다)
  • 식별자: CVE-2026-114604, GHSA-c4qx-w738-7hr3
  • 확인된 결과: 소비(consuming) Node.js 프로세스의 Object.prototype에 공격자가 고른 이름과 값의 속성 추가 가능

자문이 지정한 위험 지점은 GraphQL 서버 자체의 결함이 아니라, 외부에서 도착한 응답을 파싱·병합하는 Node.js 코드 쪽입니다. 즉 피해 지점은 응답을 소비하는 서비스입니다.

영향 범위

구분 버전
취약 범위 10.10.1 이상 12.0.1 이하
영향받지 않음 12.0.2 이상

제공된 자문은 버전 범위만 명시합니다. 실제 노출 여부는 다음 조건이 겹치는지 따라 달라집니다.

  • 취약 버전을 직접 또는 트랜지티브 의존성으로 가진 Node.js 서비스
  • 그 서비스에서 mergeIncrementalResult가 외부에서 도착한 증분 응답을 처리하는 경로가 존재하는 경우
  • 그 응답의 업스트림이 신뢰 경계 밖에 있는 경우(외부 GraphQL 서버, 게이트웨이, 프록시)

취약 버전을 쓰더라도 증분 응답 경로를 전혀 사용하지 않거나 병합 대상 응답이 항상 자체 통제 하에 있으면 노출 조건은 약해집니다. 이 조건부 판단은 자문의 영향 서술을 운영 관점으로 읽은 해석이며, 특정 배포의 실제 노출을 증명하는 자료는 제공되지 않았습니다.

오염의 크기는 개별 객체 수준이 아닙니다. 자문은 악의적으로 조작된 증분 응답이 소비 프로세스의 Object.prototype에 공격자가 선택한 임의 속성과 값을 추가할 수 있다고 명시합니다. 모든 일반 객체가 Object.prototype을 상속하므로, 인가(authorization)·설정(configuration) 검사처럼 취약 코드와 전혀 무관한 위치의 동작까지 바뀔 수 있습니다. 자문은 이를 프로세스 전반의 무결성 문제로 설명합니다.

기술적 분석

가드가 우회되는 지점

setObjectKeyPath는 위험한 세그먼트를 '__proto__', 'constructor', 'prototype'과 엄격한 문자열 동등 비교로 걸러냅니다. 자문은 이 비교가 50-52행과 60-62행에 있다고 명시합니다. 이 방어는 세그먼트가 문자열일 때만 성립합니다. 자문이 지적한 누락은 세그먼트가 원시(primitive) 문자열이나 숫자인지 자체를 확인하지 않는다는 점입니다.

그 결과 문자열이 아닌 세그먼트, 예를 들어 배열로 강제 변환(coerce)되는 __proto__ 키는 동등 비교를 통과해 실제 속성 접근에 도달할 수 있습니다. 우회 지점은 위험 키 목록이 아니라 입력 타입에 대한 가정의 차이입니다. 방어 코드가 문자열 입력만 존재한다고 전제하는 동안, 호출 경로는 비원시 값을 그대로 워커에 전달합니다.

오염이 프로세스 전체로 퍼지는 경로

추가되는 속성은 병합 대상 객체가 아니라 Object.prototype입니다. 따라서 오염은 그 요청의 객체 graph에 머물지 않고, 이후 생성되는 모든 일반 객체의 상속 결과에 영향을 줍니다. 자문이 인가·설정 검사와 관련 없는 코드의 동작 변경을 거론하는 이유가 이 상속 구조입니다. 증분 응답 병합이라는 국소 코드에서 시작해 프로세스 전역의 판단 로직으로 영향이 확장되는 형태입니다.

공개 PoC·익스플로잇 분석

  • 출처: 익스플로잇 형태를 직접 서술하는 근거는 GitHub 보안 자문 GHSA-c4qx-w738-7hr3, GitHub Advisory Database의 CVE-2026-114604 항목, 그리고 수정 PR #8467입니다. 자문은 setObjectKeyPath가 '__proto__', 'constructor', 'prototype'과 엄격한 문자열 동등 비교로 위험 세그먼트를 거부하려 하지만 세그먼트가 원시 문자열·숫자인지는 검증하지 않는다고 밝히고, 수정 PR은 배열로 강제 변환되는 __proto__ 키가 더 이상 가드를 통과하지 못하도록 하는 것을 목표로 밝힙니다. 즉 우회 기법의 윤곽은 벤더 자문과 벤더 자신의 수정 코드 설명이라는 두 출처에서 교차 확인됩니다.
  • 전제조건: 이 글이 읽는 익스플로잇 성립 조건은 다음이 겹치는 경우입니다. 첫째, @graphql-tools/utils 10.10.1 이상 12.0.1 이하를 로드한 Node.js 프로세스가 존재할 것. 둘째, 그 프로세스에서 mergeIncrementalResult의 경로 워커가 증분 응답의 path 세그먼트를 객체 키로 변환하는 실행 경로가 열려 있을 것. 셋째, 그 path 세그먼트에 문자열·숫자가 아닌 값, 즉 배열처럼 강제 변환되는 __proto__ 키가 공격자 제어 입력으로 도달할 것. 세 조건이 동시에 충족될 때 자문이 서술한 결과인 Object.prototype 속성 추가가 가능한 조건이 만들어집니다.
  • 입증 범위: 현재 근거는 벤더 자문이 확인한 우회 경로와 벤더의 수정 내용, 그리고 자문이 명시한 결과까지를 뒷받침합니다. 반대로 독립적으로 게시된 standalone PoC 스크립트의 코드 본문, 재현 실행 기록, 야생 악용 기록은 제공된 근거에 포함되어 있지 않습니다. 따라서 재현 형태는 자문과 PR이 지시하는 구조, 즉 비원시 path 세그먼트가 배열로 강제 변환되어 __proto__ 키 접근에 도달한다는 범위까지만 확인할 수 있고, 특정 공개 PoC 코드의 존재나 그 상세 구현을 이 글에서 단정하지 않습니다. 이 한계는 악용 가능성의 유무가 아니라 악용 상세의 검증 수준에 관한 한계입니다.
  • 운영 의미: 검증된 우회 지점이 위험 키 목록이 아니라 입력 타입 검증 부재라는 점은 점검 초점을 좁힙니다. __proto__ 문자열만 검색하는 점검은 배열 강제 변환 경로를 잡지 못하므로, mergeIncrementalResult에 도달하는 path 세그먼트의 타입 자체를 보는 점검이 더 직접적입니다. 또한 오염 대상이 Object.prototype이므로 익스플로잇의 영향은 병합 대상 객체를 넘어 프로세스 전체로 확장되며, 피해 신호가 취약 함수가 아닌 인가·설정 검사처럼 무관한 위치에서 나타날 수 있습니다.

수정 방식

수정 PR #8467은 속성 접근 전에 비원시 세그먼트를 거부하고, isSafeObjectKey / isDangerousObjectKey 헬퍼를 여러 호출 지점에서 공유하도록 변경했습니다. 배열로 강제 변환되는 __proto__ 키가 더 이상 가드를 통과하지 못하게 하는 것이 목표입니다.

이 수정 형태에서 읽을 수 있는 일반적 교훈은 위험 키를 문자열 목록으로 비교하는 것만으로는 부족하고, 입력이 허용된 타입인지 확인하는 단계가 선행되어야 한다는 점입니다. 다만 이 해석은 이번 수정 방식에서 도출한 관찰이며, 다른 코드베이스에 동일한 결함이 있다는 근거는 제공되지 않았습니다.

악용 현황과 확인되지 않은 부분

제공된 근거 기준 야생에서의 실제 악용 사례는 확인되지 않았습니다. 위 ### 공개 PoC·익스플로잇 분석에서 정리한 대로 standalone PoC 코드의 존재와 상세, 독립적인 제3자 검증, 추가 연구 보고도 제공된 근거에 없습니다. 심각도 관련 정보는 제공된 GitHub 보안 자문에 약점 분류 CWE-1321과 제보자(reporter) 기준 심각도 High로 기재되어 있고, CVSS 벡터와 점수는 함께 제공되지 않았습니다. 즉 자문에서 확인할 수 있는 심각도 자료는 제보자 평가라는 위치의 정보이며, 별도의 공식 심각도 등급이 존재하는지는 제공된 근거로 확인하지 않습니다.

따라서 이 글의 우선순위 판단은 자문이 밝힌 영향 메커니즘을 중심으로 CWE-1321 분류와 제보자 심각도 High를 참고 정보로 함께 놓은 조건부 판단이며, 알려진 악용 사실에 근거한 판단은 아닙니다. CVSS 벡터·점수가 제공되지 않았으므로 다른 취약점과의 정량 비교는 이 글에서 할 수 없습니다. 노출 조건, 즉 취약 버전 사용 여부와 신뢰 경계 밖 증분 응답의 병합 경로 존재 여부가 우선순위를 결정하는 주요 입력으로 남습니다. 알려진 악용 여부와 공식 점수는 대응 우선순위를 재평가할 중요한 정보이므로, 이후 공개되는 CVE 레코드와 공식 등급 자료를 통해 확인할 필요가 있습니다.

대응 방안

우선순위: 버전 확인과 경로 특정

  • 프로젝트와 서버 이미지에서 @graphql-tools/utils 버전을 확인해 10.10.1 이상 12.0.1 이하 범위 사용 여부를 점검하세요.
  • mergeIncrementalResult를 호출하는 지점과, 그 지점으로 유입되는 증분 응답의 출처를 특정하세요.
  • 취약 버전 사용 서비스 중 신뢰할 수 없는 업스트림(외부 GraphQL 서버, 게이트웨이, 프록시) 응답이 그대로 병합으로 전달되는 경로를 최우선 점검·격리 대상으로 지정하세요.

버전만 확인하고 끝내면 노출 조건이 빠집니다. 이 취약점은 버전과 응답 출처가 동시에 충족될 때 발동하므로, 두 조건의 교집합을 찾는 것이 점검의 핵심입니다.

자문에 기재된 CWE-1321 분류와 제보자 심각도 High는, 위 교집합이 성립하는 서비스에서 업그레이드를 후순위로 미루지 말라는 참고 정보로 읽을 수 있습니다. 다만 CVSS 벡터·점수가 제공되지 않았으므로 이 값을 다른 취약점과의 정량 비교나 등급 산정에 전용하지 않는 것이 안전합니다.

패치 전 임시 완화

패치 적용 전에는 신뢰할 수 없는 소스의 증분 응답 처리를 중단하거나 해당 업스트림 접근을 제한하는 것이 임시 완화책이 될 수 있습니다. 이는 제공된 분석의 권고를 그대로 옮긴 것으로, 서비스 가용성과의 트레이드오프는 각 운영 환경 판단에 맡겨야 합니다.

항구 조치

  • @graphql-tools/utils를 12.0.2 이상으로 업그레이드하세요. 자문 기준 12.0.2부터 영향을 받지 않으며, 수정 버전은 이미 게시(published)되었습니다.
  • 업그레이드 후에도 잠금 파일(lockfile)과 종속성 감사로 의존성 트리에 취약 버전이 남아 있는지 확인하세요. 간접 의존성으로 남아 있으면 버전 표기와 실제 로드 버전이 어긋날 수 있습니다.

점검 관점

제공된 분석은 다음 방향을 제안합니다. 확정된 표준 절차가 아니라 현재 조건에서 검토할 만한 방향입니다.

  • mergeIncrementalResult가 처리하는 증분 응답의 path 세그먼트에 문자열·숫자가 아닌 값이 들어오는지 확인하는 검증·로깅 지점
  • Node.js 프로세스의 Object.prototype에 예상치 못한 속성이 추가되는지 보는 무결성 점검
  • 신뢰할 수 없는 업스트림 응답 중 비정상적인 path 구조를 가진 응답의 출현 여부

구체적인 탐지 규칙 형식, 로그 필드 설계, 도구별 시그니처는 제공된 근거에 포함되어 있지 않아 이 글에서는 다루지 않습니다.

참고자료

함께 읽으면 좋은 글

본 콘텐츠는 AI 기술로 작성된 분석 리포트를 포함하고 있습니다. 내용 중 사실과 다르거나 보완이 필요한 정보를 발견하셨으면 댓글을 통해 의견을 부탁드립니다. 여러분의 피드백은 더 정확한 보안 정보 공유에 큰 도움이 됩니다.

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

로그인

아직 댓글이 없습니다.

첫 번째 댓글을 작성해보세요!

IT 도구 서랍

→ Unix: 2025-01-15T09:30:00
→ 날짜: 1736934600

→ ASCII: ABC
→ 문자: 65 66 67

ASCII 코드표 — 클릭하면 입력란에 추가

DecHex약어설명
DecHex문자
DecHex문자

→ 유니코드: 홍길동
→ 문자: \ud64d\uae38\ub3d9