Skip to content

보안: inspect watermark — 숨은 마크(제로폭 비트열·호모글리프·공백 스테가노) 탐지 + 정화 코어 - #4862

Closed
kevin9327 wants to merge 1 commit into
edwardkim:develfrom
kevin9327:gym_stego_detect_clean
Closed

보안: inspect watermark — 숨은 마크(제로폭 비트열·호모글리프·공백 스테가노) 탐지 + 정화 코어#4862
kevin9327 wants to merge 1 commit into
edwardkim:develfrom
kevin9327:gym_stego_detect_clean

Conversation

@kevin9327

Copy link
Copy Markdown
Contributor

무엇을

받은 문서에 심어진 숨은 마크(은닉 추적·워터마크)를 찾는 읽기 전용 검사
rhwp inspect watermark 와, 그것을 지우는 순수 정화 코어 stego_scan::sanitize_stego 를 더한다.
방어·탐지 전용이며 검사 회피용이 아니다. Closes #4859

탐지 3축 — 신규 모듈 src/document_core/queries/stego_scan.rs

  • hidden_char — 제로폭·비가시 문자 열(U+200B/200C/200D·FEFF·2060·180E·2061–2064·태그 문자
    U+E0000–E007F). 연속 열을 묶고, 서로 다른 두 종이면 비트열로, 8비트 배수면 ASCII
    복호해 보여 준다(태그 문자는 태그 ASCII 로 복원). 이 payload 복호가 inspect unicode 와의
    핵심 차별점.
  • homoglyph — 라틴 낱말에 섞인 키릴·그리스 동형자(Тotal 의 키릴 Т 등).
    text_security::confusable_to_latin 단일 표를 공유(pub(crate) 공개)해 드리프트를 막는다.
    순수 비라틴 낱말(러시아어 인용 등)은 통과.
  • whitespace — 문단 끝의 8자+ 공백/탭 열, 탭·공백이 섞인 내부 열. 실측(samples 45건 스윕)에서
    정렬용 4–7자 공백을 통과시키도록 임계를 잡았고, 약한 신호라 등급을 낮게 둔다.

--json 봉투: schemaVersion·source·kindFilter·scannedChars·findings[]·findingCount·
clean·severityCounts·kindCounts + 출처 표지(untrustedContent/untrustedFields). 탐지 건수는
실행 실패가 아니므로 종료 코드는 0(판정은 봉투 데이터).

정화 코어 (이번 PR: 순수 함수 + 테스트)

sanitize_stego(&str) -> StegoClean탐지가 신고하는 마크만 제거/정규화하고, 정당한 쓰임
(맨 앞 BOM·옛한글 PUA 조판 제로폭·이모지 ZWJ·순수 비라틴 낱말·정렬 공백)은 남긴다. 탐지와 같은
판정 헬퍼를 공유하므로 "정화 후 재검사 = 0" 이 구조적으로 성립하고 멱등이다.

inspect 는 저장소 규약상 읽기 전용이라, 문서를 실제로 재저장하는 CLI 는 검증된 본문 치환
경로(delete/insert_text_native, 표/글상자 중첩 포함)에 얹는 edit 계열 후속 PR 로 분리한다.
이번 PR 은 그 정화의 핵심 변환을 순수 함수로 완결·검증한다.

배선

inspect watermark 하위 명령 + MCP 도구 hwp_inspect_watermark(아카이브검색 프로필·암호 문서
지원 화이트리스트 등재) + INSPECT_SUBCOMMANDS + 도움말. 형제 작업 파일(injection_scan.rs·
security_trailer.rs·agent_seal.rs)은 건드리지 않았다.

검증

  • cargo build --bin rhwp OK · cargo test --lib 3715 통과, 0 실패(신규 13 케이스 포함).
  • 계약 테스트: 프로필 커버리지(8)·암호 패리티(2) 통과 · clippy 청정 · cargo fmt --check 청정.
  • 실측 픽스처(HWPX 본문에 제로폭 "Hi" 비트열 + 키릴 Т 동형자 삽입): 탐지가 위치·개수·복호
    ("Hi")·정규화(Т→T)까지 정확. 정화 코어 재검사 → 0(단위 테스트).
  • 원본 샘플 45건 스윕: hidden/homoglyph 오탐 0, whitespace 는 낮은 신뢰 신호로 대부분 low.

받은 문서에 심어진 은닉 추적·워터마크를 찾는 읽기 전용 검사 `rhwp inspect watermark` 와
그것을 지우는 순수 정화 코어 `stego_scan::sanitize_stego` 를 더한다. 방어·탐지 전용이며
검사 회피용이 아니다.

- 탐지 3축(신규 모듈 src/document_core/queries/stego_scan.rs):
  hidden_char(제로폭·비가시 문자 열을 비트/ASCII 로 복호), homoglyph(라틴 낱말에 섞인
  키릴·그리스 동형자, text_security::confusable_to_latin 단일 표 공유), whitespace(뒤따르는
  긴 공백/탭·혼합 열 — 약한 신호라 등급 낮음).
- --json 봉투(schemaVersion·source·findings·clean·severityCounts·kindCounts) + 출처 표지.
- 정화 코어: 탐지가 신고하는 마크만 제거/정규화하고 정당한 쓰임(맨 앞 BOM·옛한글 PUA 조판
  제로폭·이모지 ZWJ·순수 비라틴 낱말·정렬 공백)은 불변. 멱등이며 정화 후 재검사 = 0.
  inspect 는 읽기 전용 규약이라 문서 재저장 CLI 는 검증된 본문 치환에 얹는 edit 후속으로 분리.
- 배선: inspect watermark 하위 명령 + MCP hwp_inspect_watermark(아카이브검색 프로필·암호
  문서 지원 화이트리스트 등재). 형제 작업 파일(injection_scan.rs 등) 무수정.
- 검증: cargo test --lib 3715 통과(신규 13 포함), 프로필 커버리지·암호 패리티 계약 통과,
  clippy·fmt 청정. 실측 픽스처(제로폭 "Hi" 비트 + 키릴 Т)로 탐지·복호·정규화 확인,
  원본 45건 스윕에서 hidden/homoglyph 오탐 0.

Closes edwardkim#4859

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@jangster77

Copy link
Copy Markdown
Collaborator

통합 PR #4883(4412546)로 병합 완료했습니다.

원 head와 CI를 다시 확인해 누적 반영했고, 상세 검토·메인터너 보정·검증 근거는 archive 검토 기록에 남겼습니다.

중복 병합을 막기 위해 이 원 PR을 닫습니다. 감사합니다.

@jangster77 jangster77 closed this Aug 15, 2026
@jangster77

Copy link
Copy Markdown
Collaborator

통합 PR #4883(4412546)로 병합 완료했습니다.

원 head와 CI를 다시 확인해 누적 반영했고, 상세 검토·메인터너 보정·검증 근거는 archive 검토 기록에 남겼습니다.

중복 병합을 막기 위해 이 원 PR을 닫습니다. 감사합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants