flawopen.com/디렉터리/226
Marimo GHSL-2026-226: 테스트 릴리스 워크플로의 TOCTOU
같은 초에 발생하는 타임스탬프 경쟁으로 Pull Request 변경이 maintainer의 테스트 릴리스 승인을 통과해 TestPyPI와 npm 게시 작업까지 도달할 수 있었습니다. 취약한 워크플로는 삭제되었고 CVE는 할당되지 않았습니다.
실험실 책임자는 특정 샘플을 승인하지만 실험실은 시계의 초만 확인합니다. 같은 초에 샘플을 바꾸면 교체된 샘플도 승인된 것처럼 보입니다. Marimo 워크플로는 Pull Request 커밋에서 같은 실수를 했고 빌드한 패키지를 게시 작업으로 전달했습니다.
핵심 개념 및 용어
TOCTOU- Time-of-check to time-of-use: 보안 검사 후 실제 사용 전에 리소스가 바뀌는 문제입니다.
OIDC 게시- CI 작업이 GitHub Actions ID를 패키지 레지스트리의 단기 자격 증명과 교환하므로 장기 비밀번호를 저장하지 않습니다.
워크플로 아티팩트- GitHub Actions 작업 간 전달되는 파일 묶음입니다. 후속 작업은 신뢰할 수 없는 워크플로에서 나온 아티팩트를 신뢰할 수 없는 입력으로 취급해야 합니다.
GHSL-2026-226- Marimo 워크플로 결함에 대한 GitHub Security Lab 권고 식별자입니다. 권고에서 CVE는 할당되지 않았습니다.
CWE-367 / CWE-829- 권고는 검사-사용 시간 경쟁과 신뢰할 수 없는 제어 영역의 기능 실행을 지적합니다.
프레임워크 매핑
단계별 공격 실행 흐름
Maintainer가 테스트 릴리스를 승인
Maintainer가 Pull Request에 댓글을 달아 Marimo 테스트 릴리스 워크플로를 시작합니다. 승인은 검토한 Pull Request 상태에 묶여야 합니다.
같은 초에 Pull Request head가 변경
워크플로는 pushed_at과 댓글의 created_at을 정수 초로 변환한 뒤 비교합니다. 같은 초의 push는 같은 값을 만듭니다.
취약한 검사가 같은 값을 허용
삭제된 워크플로는 댓글 시간보다 엄격히 늦은 pushed_at만 거부했습니다. 같은 값은 통과했고 업데이트된 커밋이 기록되었습니다.
신뢰할 수 없는 코드가 패키지 아티팩트를 빌드
작업은 해당 커밋을 checkout하고 저장소가 제어하는 action과 빌드 스크립트를 실행했습니다. 결과는 아티팩트로 업로드된 뒤 신뢰할 수 있는 커밋에서 재빌드되지 않은 채 게시 작업에서 사용되었습니다.
게시 권한이 신뢰할 수 없는 출력에 도달
TestPyPI와 npm 작업은 OIDC 게시 권한을 사용했습니다. 권고는 아티팩트가 게시 경로에 도달할 수 있음을 설명하지만 실제 패키지 침해를 보고하지는 않습니다.
소스 코드 비교: 취약한 구현 vs 보안 패치
GHSL-2026-226은 취약한 workflow가 PR #10765에서 삭제됐다고 설명합니다. 이는 프로젝트가 여기에 표시된 비교 연산자 변경을 적용했다는 뜻이 아닙니다. 이전 검사는 -gt를 사용해 초 단위로 같은 값이 통과했습니다. 예시의 -ge는 같은 값을 거부하지만 승인을 정확히 검토한 커밋에 묶는 편이 더 강합니다. 신뢰할 수 없는 빌드와 OIDC 작업을 분리하고 승인된 SHA에서 재빌드한 뒤 게시 전에 출처를 확인하세요. exploit payload는 포함하지 않습니다.
# 삭제된 marimo-bot workflow: 정수 초 비교
if [[ $(date -d "$pushed_at" +%s) -gt $(date -d "$COMMENT_AT" +%s) ]]; then
exit 1
fi
# 기록한 head_sha를 checkout하고 아티팩트를 별도
# 게시 작업으로 전달했습니다.
# 설명용 통제입니다. GHSL은 취약한 workflow가
# 제자리에서 수정된 것이 아니라 삭제됐다고 설명합니다.
if [[ $(date -d "$pushed_at" +%s) -ge $(date -d "$COMMENT_AT" +%s) ]]; then
exit 1
fi
# 더 강한 설계: 검토된 불변 SHA를 승인하고 신뢰된 작업에서
# 해당 SHA를 다시 빌드한 뒤 검증된 출력만 게시합니다.
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓삭제된 marimo bot workflow의 영향을 받는 복사본을 제거하거나 교체하고 현재 저장소에서 취약한 게시 경로가 활성화되지 않았는지 확인하세요.
- ✓Maintainer 승인을 정확한 불변 Pull Request SHA에 묶고 checkout 전에 head가 바뀌면 실패 처리하세요.
- ✓초 단위 timestamp만으로 변경 가능한 브랜치가 승인된 버전임을 증명하지 마세요.
- ✓신뢰할 수 없는 Pull Request는 게시 자격 증명 없이 빌드하고 id-token: write는 별도 신뢰된 게시 작업에만 부여하세요.
- ✓신뢰할 수 없는 코드가 만든 아티팩트를 승격하지 말고 신뢰된 릴리스 경로에서 승인된 커밋으로 패키지를 재빌드하세요.
- ✓TestPyPI 또는 npm 게시 전에 아티팩트 출처, 소스 리비전, 패키지 내용과 대상을 검증하세요.
- ✓GHSL 권고는 취약 경로의 증거로 다루고 실제 패키지 침해나 악용의 증거로 단정하지 마세요.