
@sigstore/oci의 CVE-2026-59891을 위한 격리된 회귀 및 보안 통제 실험실
@sigstore/oci의 실제 취약 버전과 수정 버전을 같은 입력으로 비교하고,
환경별 노출 조건을 점검하는 격리형 실습 및 read-only 감사
프로젝트입니다.
이 프로젝트의 CVE Reporter는 gyubin02입니다.
채용·면접용 요약: CVE-2026-59891 취약점 관리 자동화 사례
CVE-2026-59891의 핵심은 Registry 인증정보를 고를 때 발생하는 hostname 혼동입니다.
0.7.0: cr.io가 ghcr.io 문자열 안에 있다는 이유로
ghcr.io 인증정보를 선택할 수 있습니다.0.7.1: hostname을 정규화한 뒤 정확히 일치하는 인증정보만
선택합니다.이 저장소는 먼저 두 가지 credential 선택 시나리오를 자동 검증합니다.
ghcr.io 인증정보만 있는데 대상은 cr.iocr.io 인증정보가 있음취약 버전은 첫 번째 시나리오에서 인증정보를 잘못 선택하고, 수정 버전은 거부해야 합니다. 두 버전 모두 두 번째 정상 시나리오는 성공해야 합니다.
여기에 실제 외부 Registry 대신 127.0.0.1의 일회성 mock
Registry를 사용한 동적 비교를 추가했습니다. 취약 버전 0.7.0은
로컬로 2건을 요청하고 인증 challenge 뒤 두 번째 요청에서 합성
Authorization header가 관찰됩니다. 수정 버전 0.7.1은 credential
선택 단계에서 거부되어 요청이 0건입니다. 결과에는 header 값 대신
관찰 여부와 요청 수만 남깁니다.
cve-2026-59891-audit는 대상 프로젝트의 package-lock.json과
명시적으로 지정한 Docker config의 metadata만 읽어 다음을
구분합니다.
@sigstore/oci 설치 위치와 버전합성 fixture로 바로 실행:
npm run audit:demo
다른 Node.js 프로젝트 점검:
npm run audit:project -- \
--project ../target-project \
--docker-config ../review-copy/config.json \
--image cr.io/example/demo \
--destination-trust unknown \
--format markdown \
--output reports/cve-2026-59891.md
--destination-trust는 다음 중 하나를 반드시 명시합니다.
trusted: 코드와 allowlist로 destination이 제한됨을 확인untrusted: 외부입력이나 workflow 입력이 destination에 영향unknown: 아직 확인하지 못함판정은 exposure_conditions_met, potential_exposure,
affected_component_only, not_detected, indeterminate로
나뉩니다. not_detected도 기록된 입력 범위에 대한 결과일 뿐
“안전”이나 “규정 준수”를 뜻하지 않습니다.
~/.docker/config.json을 읽거나 수정하지 않습니다.HOME과 무가치한
lab-user / LAB_ONLY_FAKE_TOKEN만 사용합니다.HOME, 랩 표식, 가짜 값이 모두 정확할 때만 패키지를 호출합니다.fetch
호출을 tripwire로 막습니다.127.0.0.1 포트의 HTTP 요청만 허용합니다. 외부·다른
포트 HTTP, DNS resolver, TLS, UDP, 전역 fetch·WebSocket은
차단합니다.--docker-config를 생략할 수 없으며 HOME이나
DOCKER_CONFIG에서 파일을 추론하지 않습니다.npm-shrinkwrap.json이 발견되면 안전하다고 단정하지 않고
실패합니다.취약 패키지를 의도적으로 설치하므로 npm package 배포는
"private": true로 막았습니다. 제품 코드의 의존성으로 사용하면
안 됩니다.
이 때문에 npm audit가 0.7.0을 보고하는 것은 예상된 결과이며,
예외의 범위와 이유는 SECURITY.md에 기록했습니다.
요구 사항: Node.js 22.22.2+, 24.15.0+ 또는 26 이상. 권장 버전은
.nvmrc에 고정했습니다.
npm ci --ignore-scripts
npm test
npm run demo
npm run dynamic:demo
npm run audit:fixture
npm run audit:demo
npm run evidence
npm run demo의 핵심 예상 결과:
0.7.0 collision credential-selected
0.7.1 collision credential-rejected
0.7.0 exact credential-selected
0.7.1 exact credential-selected
Regression result: PASS
npm run dynamic:demo의 핵심 예상 결과:
{
"vulnerable": {
"packageVersion": "0.7.0",
"credentialSelection": "credential-selected",
"requestCount": 2,
"authorizationObserved": true,
"digestVerified": true,
"networkPolicy": "exact-loopback-only"
},
"fixed": {
"packageVersion": "0.7.1",
"credentialSelection": "credential-rejected",
"requestCount": 0,
"authorizationObserved": false,
"digestVerified": false,
"networkPolicy": "exact-loopback-only"
},
"regressionResult": "PASS"
}
전체 자동화 테스트는 34개입니다. npm run evidence는 검사 대상
산출물 6개와 그 무결성을 검증하는 SHA256SUMS를 합쳐 총 7개
파일을 생성합니다.
이 프로젝트는 제한된 교육용 통제 평가입니다. loopback 결과는 합성 환경의 동작 차이만 입증하며, 실제 기업 환경의 credential 노출·침해나 통제 효과를 입증하지 않습니다. CISA 자격, ISMS-P 인증 또는 특정 조직의 규정 준수를 뜻하지 않습니다. Node API guard는 잠근 dependency의 관찰된 실행경로를 위한 방어층이지, OS 수준 network namespace나 방화벽은 아닙니다.
상세한 범위, 테스트, 위험 및 통제 문서는 docs/에 있으며,
npm run evidence는 재현 가능한 실행 증적과 SHA-256 manifest를
생성합니다.