fix(hwpx): cap ZIP entry decompression to defeat zip bombs#153
Merged
edwardkim merged 1 commit intoApr 16, 2026
Conversation
Problem ------- HwpxReader::read_file and read_file_bytes called read_to_string / read_to_end directly on zip::ZipFile readers with no size ceiling. ZIP allows extreme compression ratios, so a few-KB .hwpx can claim a single section.xml entry that expands to multi-GB — OOMing the host. Any downstream (CLI, WASM, browser extension, VS Code) inherits the risk since all of them funnel through parse_hwpx → HwpxReader. Fix --- Introduce a small read_limited(reader, max) helper using Read::take so we never allocate past max+1 bytes. Apply: - MAX_XML_SIZE = 32 MB for text entries (section/header/hpf) - MAX_BINDATA_SIZE = 64 MB for binary entries (images, fonts) Real-world Korean government HWPX (보도자료·법령·판례) stays well under these, so legitimate files are unaffected. Over-limit entries surface as HwpxError::ZipError with "decompression bomb" in the message — callers see a clean parse error instead of a crash. Rationale for thresholds ------------------------ MDM (https://github.com/seunghan91/markdown-media) has been running the same 32/64 MB caps in production across ~500 real HWPX fixtures with zero false positives; see MDM commit a94b459 for the original application of this pattern across HWP/HWPX/PDF parser paths. Tests ----- Five unit tests in parser::hwpx::reader: - under / at / over cap boundary for read_limited - a synthetic zip-bomb entry (MAX_XML_SIZE + 1 bytes of 'A', compressed to <1 MB) is rejected with ZipError Full suite: 789 passed, 0 failed (baseline + 5 new). No public API change: HwpxError variants unchanged, method signatures unchanged. MAX_XML_SIZE / MAX_BINDATA_SIZE are exposed as pub const so integrators can read the current caps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
edwardkim
approved these changes
Apr 16, 2026
edwardkim
left a comment
Owner
There was a problem hiding this comment.
로컬 검증 완료 ✅
cargo test789개 전체 통과 (ZIP bomb 테스트 4개 포함)read_limited()함수로 XML(32MB)/BinData(64MB) 엔트리별 압축 해제 크기 제한- zip bomb 탐지 테스트가 실제 deflate 압축으로 검증 — 신뢰성 높음
- 보안 문서화도 잘 되어 있습니다
중요한 보안 기여 감사합니다! 🛡️
This was referenced Apr 16, 2026
edwardkim
added a commit
that referenced
this pull request
Apr 19, 2026
본 v0.5.0 → v0.7.3 (라이브러리) / 0.2.0 (확장) 배포 주기에 머지된 외부 기여자 6명을 README 3개 변경 이력에 추가: - @ahnbu — Ctrl+S file handle (PR #189, 기명시) - @bapdodi — 회전 도형 리사이즈 + Flip (PR #192) - @dreamworker0 — Windows CFB 경로 (PR #152) - @marsimon — HWP 그림 효과 SVG (PR #149) - @postmelee — 썸네일 + options CSP (PR #168) - @seunghan91 — HWPX Serializer + 다수 (PR #170, #161, #163, #153, #154) 각 README 끝에 "기여자 감사" 섹션 추가 — 6명 일괄 인정. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Apr 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
요약
HWPX 파서의
HwpxReader가 ZIP 엔트리를 읽을 때 크기 제한 없이read_to_string/read_to_end를 호출합니다. ZIP은 압축률이 매우 높을 수 있어 수 KB짜리 악성 HWPX가 단일section.xml엔트리만으로 수 GB까지 팽창 — 호스트 프로세스를 OOM으로 몰 수 있습니다 (decompression bomb).영향 경로:
parse_hwpx→HwpxReader::read_file*영향 범위: CLI (
rhwp export-svg등), WASM, Chrome/Safari 확장, VS Code 확장, rhwp-studio 모두.변경
src/parser/hwpx/reader.rs에 작은 유틸read_limited(reader, max)를 추가하고,read_file/read_file_bytes가 이를 통해 읽도록 전환했습니다.MAX_XML_SIZEMAX_BINDATA_SIZERead::take(max + 1)을 사용해 오버플로를 감지하되, 버퍼는 실제 읽은 크기 + 1 이상으로 자라지 않습니다. 상한 초과 시HwpxError::ZipError("... decompression bomb ...")로 surface.임계값 근거
실제 정부 보도자료·판례·법령 HWPX에서 section.xml이 32 MB를 넘는 사례를 본 적 없습니다. 이미지도 64 MB 단일 파일을 넘는 경우는 없습니다 (대부분 개별 이미지는 수 MB 이하).
저희 쪽 MDM (markdown-media) 파서는 이 32/64 MB 임계값을 ~500개 실제 HWPX 픽스처 (MOIS 보도자료 전량 + 법원 판결문 샘플) 에서 돌려왔고 false positive는 0건입니다. 원본 패턴은 MDM commit
a94b459에서 HWP/HWPX/PDF 세 파서 경로에 함께 적용했습니다.공개 API 영향
HwpxError변형 추가 없음 — 초과는 기존ZipError에 실림MAX_XML_SIZE/MAX_BINDATA_SIZE는pub const로 노출 (통합자가 현재 상한을 읽을 수 있음). 필요하면 후속 PR에서open_with_limits()생성자도 추가 가능.테스트
parser::hwpx::reader5개 유닛 테스트 추가:test_read_limited_under_cap— 상한 미만test_read_limited_at_cap— 상한과 정확히 같은 크기test_read_limited_over_cap— 1 바이트 초과 →InvalidDatatest_zip_bomb_xml_entry_rejected—MAX_XML_SIZE + 1바이트의 반복 패턴을 deflate 압축하면 결과물이 1 MB 미만이지만, 실제 해제 시도는 상한에 걸려ZipError로 거부됨test_open_invalid_zip(기존)전체:
cargo test --lib→ 789 passed, 0 failed (기존 784 + 신규 5).관련 맥락
shape="3D"strikeout 화이트리스트 PR도 보낼 예정입니다.cfb_lenient.rs가 rhwpsrc/parser/cfb_reader.rs::LenientCfbReader에서 MDM으로 포팅된 것이어서, 이번에는 반대 방향으로 기여합니다.🙇 감사합니다!