Skip to content

feat/firefox extension#169

Draft
postmelee wants to merge 29 commits intoedwardkim:develfrom
postmelee:feat/firefox-extension
Draft

feat/firefox extension#169
postmelee wants to merge 29 commits intoedwardkim:develfrom
postmelee:feat/firefox-extension

Conversation

@postmelee
Copy link
Copy Markdown

@postmelee postmelee commented Apr 16, 2026

변경 요약

rhwp-chrome 기반으로 Firefox 확장 프로그램 rhwp-firefox/를 신규 추가합니다. 포팅과 함께 확장 보안 기준선(발신자 검증, SSRF 방어, fetch 안전화, 접근성, 리소스 노출 축소)까지 같은 PR에서 정립합니다. 기존 Rust/WASM/rhwp-studio 코드 및 rhwp-chrome/은 수정하지 않습니다.

커밋 구성

Firefox 전용으로 재작성이 필요한 포팅 커밋(#16)과 Copilot 리뷰 대응·보안 기준선 커밋(#710)으로 구성됩니다.

# 커밋 범주 범위
1 feat(rhwp-firefox): rhwp-chrome 포팅 — 공통 파일 (as-is + trivial rename) 포팅 _locales/, icons/, content-script.css, dev-tools-inject.js, sw/thumbnail-extractor.js, test/, .gitignore + 메타데이터 리네임 5종
2 feat(rhwp-firefox): manifest — Firefox MV3 + gecko settings 포팅 manifest.json
3 feat(rhwp-firefox): browser.* API 네임스페이스 전환 포팅 background.js, content-script.js, sw/{context-menus,message-router,viewer-launcher}.js
4 feat(rhwp-firefox): download-interceptor — onCreated + onChanged 기반 재구현 포팅 sw/download-interceptor.js
5 feat(rhwp-firefox): options 페이지 — CSP 호환 외부 스크립트 분리 포팅 options.html, options.js
6 docs(rhwp-firefox): README — Firefox 설치/빌드 가이드 재작성 포팅 README.md
7 feat(rhwp-firefox): message-router — sender/URL 검증 및 fetch 안전화 보안 sw/message-router.js, build.mjs
8 feat(rhwp-firefox): content-script — 프리페치/호버 URL 필터 적용 (SSRF 방어) 보안 content-script.js, test/06-security.html
9 fix(rhwp-firefox): build 스크립트 shell 실행 제거 보안 build.mjs (execSyncexecFileSync)
10 fix(rhwp-firefox): resolve Copilot review comments on PR #169 보안·a11y content-script.{js,css}, manifest.json, sw/{message-router,thumbnail-extractor,viewer-launcher}.js

리뷰 라운드에서 수집된 9건의 소규모 수정 커밋(버전 단일 소스화, 미사용 Set 제거, Promise 오류 로깅, 문서 표기 정정 등)은 본문에서 생략합니다. git log feat/firefox-extension -- rhwp-firefox/로 확인할 수 있습니다.

Firefox 전용 수정 근거

1. manifest.json — Firefox MV3 + gecko settings (커밋 2)

  • Firefox MV3는 Service Worker 미지원 (Event Page 기반) → background.service_workerbackground.scripts 배열
  • AMO 제출용 browser_specific_settings.gecko 추가 — id, strict_min_version: "112.0", data_collection_permissions: {"required":["none"]}
  • options_ui.browser_style: false

2. browser.* API 네임스페이스 전환 (커밋 3)

Firefox 네이티브 browser.*콜백을 지원하지 않고 Promise만 반환합니다. 단순 문자열 치환만으로는 콜백 기반 코드가 동작하지 않아 아래 파일을 Promise 체인/async-await로 재작성했습니다.

  • content-script.js: runtime.sendMessage 3곳(get-settings, 호버 썸네일, 프리페치 썸네일) — .catch() 오류 처리 포함
  • sw/context-menus.js, sw/viewer-launcher.js, sw/message-router.js

3. sw/download-interceptor.js — 알고리즘 재설계 (커밋 4)

Firefox는 Chrome 전용 downloads.onDeterminingFilename을 지원하지 않아 재구현.

  • 1차: onCreated에서 URL 기반 즉시 감지
  • 2차: onChanged(filename 확정) 시 browser.downloads.search로 최신 DownloadItem 재조회
  • handled Set으로 중복 처리 방지 (완료/에러 30초 후 cleanup)

4. options.html + options.js — CSP 인라인 스크립트 분리 (커밋 5)

Firefox MV3의 CSP(script-src 'self')가 인라인 <script>를 차단하므로 외부 파일로 분리. browser.storage.sync Promise 기반 재작성.

확장 보안 기준선

커밋 #7~10에서 확립한 최종 기준선입니다. 웹 확장이 공격자 페이지의 링크를 신뢰할 수 없다는 전제 아래, 프리페치·호버·뷰어 fetch 전 구간에서 방어를 적용합니다.

발신자 검증 (sw/message-router.js)

  • fetch-file: isViewerPageviewer.html(쿼리/해시 포함) 정확 매칭 — 다른 확장 내부 페이지(options 등)의 임의 URL fetch 권한 차단
  • open-hwp, extract-thumbnail: isContentScript로 content-script 발신자만 허용

URL 검증 (SSRF 방어)

프리페치 큐 투입 전(content-script) / fetch 실행 전(message-router) 동일 로직 적용:

  • 프로토콜 화이트리스트(http:, https:)
  • userinfo(user:pass@host) 차단
  • isPrivateHost — IPv4(127/10/192.168/172.16-31/169.254/0) + IPv6 loopback(::1, 완전형, ::ffff:127.* IPv4-mapped) + ULA(fc00::/7) + link-local(fe80::/10) + localhost/.local
  • URL().hostname[::1]::1로 반환하는 점을 반영해 normalizeHostname으로 대괄호 제거 후 매칭

fetch 안전화

  • credentials: 'omit' — 쿠키·인증 누출 차단
  • redirect: 'manual' + response.type === 'opaqueredirect'와 3xx status 거부 — 검증 통과 URL이 내부망으로 30x 우회되는 SSRF 차단
  • HTTP 차단 사유 메시지를 실제 동작과 일치시킴 ('HTTP 차단 (HTTPS만 허용)')

CFB DIFAT 체인 순회 (sw/thumbnail-extractor.js)

buildFatTable을 CFB 스펙에 맞춰 확장. 헤더 내 109개 DIFAT 엔트리 + firstDIFATSector/numDIFATSectors(header offset 68/72) 체인 순회 + FREESECT/ENDOFCHAIN/버퍼 경계 방어 체크. 대용량 HWP(CFB) 파일에서 PrvImage 추출이 실패하던 문제 해소.

접근성 (content-script.{js,css})

HWP 링크 배지를 <span>(마우스 전용)에서 <button type="button"> + aria-label + :focus-visible 아웃라인으로 교체. 키보드·스크린리더 접근이 가능해지며, CSS 리셋(padding:0, border:0, appearance:none)으로 기존 외형을 유지.

공격 표면 축소

  • web_accessible_resources: wasm/*, fonts/*, icons/* 제거하고 dev-tools-inject.js만 노출. UUID 기반 핑거프린팅·대역폭 남용 표면 축소 (runtime.getURL로 해당 리소스를 사용하는 content-script 없음을 확인).
  • build.mjs: execSync 문자열 실행을 execFileSync 인자 배열 실행으로 전환 — 경로 기반 셸 해석 리스크 제거. viewer.html 존재 확인 후 주입.
  • openViewerOrReuse: tabs.query/update 실패 시 unhandled rejection을 내던 경로를 try/catch + openViewer() 폴백으로 처리.

관련 이슈

테스트

  • cargo test 통과 — 기존 Rust 코드 무수정이라 영향 없음 (rhwp-firefox/는 Rust 빌드 대상 밖)
  • cargo clippy -- -D warnings 통과 — 기존 코드 무수정
  • 관련 샘플 파일로 SVG 내보내기 확인 — N/A (Rust 렌더러 변경 없음)
  • 웹(WASM) 렌더링 확인 — Firefox 확장 빌드 후 about:debugging로 임시 부가 기능 로드, HWP 파일 뷰어 탭 렌더링 확인

Firefox 확장 자체 검증

  • web-ext lint: errors 0
    • warnings 2건은 KEY_FIREFOX_UNSUPPORTED_BY_MIN_VERSION (strict_min_version 112.0 정책적 유지로 인한 안내성 경고)

rhwp-firefox/test/ 6종 — 전체 통과

Chrome 확장의 수동 테스트 페이지를 그대로 복사한 rhwp-firefox/test/를 Firefox 임시 부가 기능으로 로드해 실행한 결과, 모든 검증 항목이 Chrome과 동일하게 동작함을 확인했습니다.

테스트 페이지 검증 포인트 결과
01-auto-detect.html HWP/HWPX 링크 자동 감지 + 파란 H 배지 삽입
02-data-hwp-protocol.html data-hwp-* 메타데이터 속성(제목/쪽수/용량/작성자/썸네일 등) 반영
03-dynamic-content.html MutationObserver로 동적 DOM에 추가된 HWP 링크에도 배지 부착
04-devtools.html 페이지 컨텍스트에 rhwpDev 개발자 API 노출 및 호출 가능
05-gov-site-sim.html 공공사이트 유사 환경에서 배지/호버/다운로드 통합 동작
06-security.html XSS 페이로드 / 비안전 URL(javascript:) / SSRF(http://127.0.0.1, http://[::1], userinfo URL) 차단

스크린샷

스크린샷 2026-04-17 02 20 18 스크린샷 2026-04-17 02 21 57 스크린샷 2026-04-17 02 25 54

범위 외 (참고)

  • AMO 등록: 메인테이너 권한 필요 (Firefox Add-ons 개발자 계정)
  • gecko.id: 현재 rhwp@edwardkim.github.io — 변경 가능하도록 manifest에 주석 명시
  • DEVELOPER_GUIDE.md: 중복 생성 없이 ../rhwp-chrome/DEVELOPER_GUIDE.mdREADME.md에서 참조
  • 확장 테스트 자동화 프레임워크: rhwp-firefox/test/*.html을 headless 실행하는 single-log verdict 하니스는 본 PR 범위 외로 분리 예정 (별도 PR)

postmelee and others added 6 commits April 16, 2026 22:13
rhwp-chrome 기반으로 변경 없이 그대로 옮긴 파일들 + 메타데이터
리네임 수준의 사소한 조정만 들어간 파일들.

공통 자원 (as-is):
- _locales/ko,en/: i18n 메시지
- icons/: 16/32/48/128 PNG
- content-script.css: 배지/호버 카드 스타일
- dev-tools-inject.js: rhwpDev 페이지 컨텍스트 주입
- sw/thumbnail-extractor.js: HWP 썸네일 Worker 추출
- test/: 수동 smoke test 페이지 6종 + 인덱스
- .gitignore: node_modules/ + dist/

메타데이터 리네임:
- package.json / package-lock.json: 이름/설명 rhwp-chrome → rhwp-firefox
- vite.config.ts: 설명 + dev 포트 7701 → 7702
- build.mjs: 설명 + options.js 복사 한 줄 추가
- PRIVACY.md: chrome.storage.sync → browser.storage.sync (한 줄)

Refs edwardkim#156

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rhwp-chrome/manifest.json 대비 Firefox/AMO 규격 반영:
- browser_specific_settings.gecko: id, strict_min_version (112.0),
  data_collection_permissions (object 타입, AMO 권장 필드)
- background.service_worker → background.scripts (Firefox MV3는
  Event Page 기반, Service Worker 미지원)
- options_ui.browser_style: false (Firefox 전용 기본 스타일 비활성)

Refs edwardkim#156

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rhwp-chrome의 chrome.* 콜백 API를 Firefox 네이티브 browser.* Promise
API로 전환. Firefox의 browser.*는 콜백을 받지 않으므로 단순 치환이
아닌 Promise 체인/async-await 패턴 전환이 필요하다.

- background.js: runtime/storage/action 리스너 browser.* 치환
- sw/context-menus.js: contextMenus.removeAll().then(...) 체인
- sw/message-router.js: onMessage + storage.sync.get Promise
- sw/viewer-launcher.js: tabs.create/query/update Promise + 에러 핸들링
- content-script.js: runtime.sendMessage 3곳 Promise 체인 전환
  (get-settings, extract-thumbnail 호버/프리페치) — 콜백 미지원 대응

Refs edwardkim#156

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Firefox는 Chrome 전용 downloads.onDeterminingFilename을 지원하지 않아
알고리즘을 재설계했다.

- 1차 판정: onCreated 시점에 URL 기반 즉시 감지
- 2차 판정: onChanged(filename 확정) 시 browser.downloads.search로
  최신 DownloadItem을 재조회하여 확장자 재확인
- candidates Set: 1차 미판정 downloadId 추적
- handled Set: 동일 다운로드 중복 처리 방지 (30초 후 정리)
- HWP_EXTENSIONS 정규식에 쿼리스트링 허용 추가: /\.(hwp|hwpx)(\?.*)?$/i

Refs edwardkim#156

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Firefox MV3의 CSP(script-src 'self')는 인라인 <script>를 차단하므로
rhwp-chrome/options.html의 인라인 스크립트를 외부 파일로 분리.

- options.html: 인라인 <script> 제거 → <script src="options.js">
- options.js: 신규 — i18n 적용 + browser.storage.sync Promise 기반
  로드/저장 (autoOpen / showBadges / hoverPreview 토글 3종)

Refs edwardkim#156

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 제목/설치처: Chrome/Edge → Firefox Add-ons (AMO)
- 개발 모드 설치: about:debugging#/runtime/this-firefox +
  임시 부가 기능으로 manifest.json 선택
- 개발자 가이드: 중복 생성 없이 ../rhwp-chrome/DEVELOPER_GUIDE.md 참조
- "Chrome 확장과의 차이" 섹션 신설 — manifest/background/
  download-interceptor 3개 핵심 차이점 요약

Refs edwardkim#156

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 16, 2026 17:26
@postmelee postmelee changed the title Feat/firefox extension feat/firefox extension Apr 16, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new rhwp-firefox/ Firefox WebExtension (ported from rhwp-chrome) plus build tooling to package rhwp-studio output as the extension’s viewer.

Changes:

  • Introduces Firefox MV3 manifest/background entrypoint and browser.*-based scripts (content script, SW helpers, message routing, download interception, context menus).
  • Adds Vite/build scripts + npm tooling to build and assemble dist/ as the Firefox extension bundle.
  • Ports locales, icons, options page, docs, and a set of manual HTML test pages.

Reviewed changes

Copilot reviewed 27 out of 32 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
rhwp-firefox/vite.config.ts Vite config to build rhwp-studio into Firefox extension dist/.
rhwp-firefox/package.json Firefox extension build/dev scripts and devDependencies.
rhwp-firefox/package-lock.json Lockfile for the Firefox build toolchain.
rhwp-firefox/build.mjs Build pipeline: Vite build + copy extension assets/WASM/fonts into dist/.
rhwp-firefox/manifest.json Firefox MV3 manifest (gecko settings, background scripts, CSP, permissions).
rhwp-firefox/background.js Background entrypoint wiring context menus, downloads, and message router.
rhwp-firefox/content-script.js Link detection, badge injection, hover preview, thumbnail prefetch using browser.*.
rhwp-firefox/content-script.css Styling for badges and hover preview cards.
rhwp-firefox/dev-tools-inject.js Injected page-context DevTools helper (rhwpDev.*).
rhwp-firefox/options.html Options UI (external script to satisfy MV3 CSP).
rhwp-firefox/options.js Options logic using browser.storage.sync promise API.
rhwp-firefox/sw/context-menus.js Context menu registration and click handling (Promise-based).
rhwp-firefox/sw/download-interceptor.js Firefox-specific download interception using onCreated + onChanged.
rhwp-firefox/sw/message-router.js Message routing for open/fetch/thumbnail/settings requests.
rhwp-firefox/sw/thumbnail-extractor.js Lightweight thumbnail extraction from HWP/HWPX without WASM.
rhwp-firefox/sw/viewer-launcher.js Viewer tab creation/reuse and URL parameter passing.
rhwp-firefox/_locales/ko/messages.json Korean i18n strings for Firefox extension UI.
rhwp-firefox/_locales/en/messages.json English i18n strings for Firefox extension UI.
rhwp-firefox/README.md Firefox install/build instructions and usage overview.
rhwp-firefox/PRIVACY.md Privacy policy for AMO submission (KR/EN).
rhwp-firefox/.gitignore Ignore node_modules and dist artifacts.
rhwp-firefox/test/index.html Manual test index page for extension behavior verification.
rhwp-firefox/test/01-auto-detect.html Manual test: extension-based HWP link detection.
rhwp-firefox/test/02-data-hwp-protocol.html Manual test: data-hwp-* metadata parsing/tooltip/thumbnail cases.
rhwp-firefox/test/03-dynamic-content.html Manual test: MutationObserver + dynamically added links.
rhwp-firefox/test/04-devtools.html Manual test: rhwpDev DevTools API behavior.
rhwp-firefox/test/05-gov-site-sim.html Manual test: “gov site” simulation with mixed link types.
rhwp-firefox/test/06-security.html Manual test: XSS payloads via data-hwp-* attributes.
rhwp-firefox/icons/icon-16.png Extension icon asset.
rhwp-firefox/icons/icon-32.png Extension icon asset.
rhwp-firefox/icons/icon-48.png Extension icon asset.
rhwp-firefox/icons/icon-128.png Extension icon asset.
Files not reviewed (1)
  • rhwp-firefox/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rhwp-firefox/sw/thumbnail-extractor.js
Comment thread rhwp-firefox/sw/download-interceptor.js
Comment thread rhwp-firefox/test/index.html Outdated
Comment thread rhwp-firefox/options.html Outdated
Comment thread rhwp-firefox/dev-tools-inject.js Outdated
Comment thread rhwp-firefox/test/index.html Outdated
Comment thread rhwp-firefox/dev-tools-inject.js Outdated
Comment thread rhwp-firefox/PRIVACY.md Outdated
Comment thread rhwp-firefox/content-script.js Outdated
postmelee and others added 6 commits April 17, 2026 02:34
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot 리뷰 (PR edwardkim#169) 반영:
- content-script.js: data-hwp-extension-version 속성과 ready 이벤트
  detail.version을 browser.runtime.getManifest().version으로 대체
- dev-tools-inject.js: VERSION 하드코딩 제거,
  document.documentElement[data-hwp-extension-version] 읽어 사용
  (content-script가 주입 전에 세팅함)
- options.html / options.js: 하단 푸터 'rhwp v0.1.0'를
  span#version + browser.runtime.getManifest().version으로 동적 표시

이전: manifest 0.1.1과 코드 노출 값 0.1.0이 어긋남.
Copilot 리뷰 (PR edwardkim#169) 반영: Firefox 확장 폴더의 테스트 인덱스에
"rhwp Chrome 확장" / "Chrome 또는 Edge에서 실행" 표기가 남아 있어
사용자 혼동 가능. Firefox로 통일.
Copilot 리뷰 (PR edwardkim#169) 반영: rhwpDev.help() 출력의
data-hwp-thumbnail 예시가 상대경로("/thumbs/preview.webp")라
content-script.isSafeImageUrl()의 절대 http/https 검증을
통과하지 못해 실제로는 표시되지 않음.
사용자가 따라할 때 동작하도록 https://example.com/... 절대 URL로 변경.
Copilot 리뷰 (PR edwardkim#169) 반영: Firefox 확장 PRIVACY.md 영문 섹션이
chrome.storage.sync로 표기되어 있어 실제 구현(browser.* API) 및
AMO 제출 문맥과 불일치. browser.storage.sync로 정정.
Copilot 리뷰 (PR edwardkim#169) 반영: candidates Set은 add/delete만 하고
has() 분기 판정에 쓰이지 않아 동작에 영향 없음. handled Set만으로
중복 처리 방지가 성립하므로 candidates 제거 + 관련 주석 정리.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • rhwp-firefox/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rhwp-firefox/background.js
Comment thread rhwp-firefox/sw/download-interceptor.js Outdated
Comment thread rhwp-firefox/sw/thumbnail-extractor.js
Copilot 리뷰 (PR edwardkim#169) 반영.

원작자(rhwp-chrome) 의도: onInstalled에서 기본값을 fire-and-forget
저장하고 실패는 무시 (get 지점에 기본값 복구 존재). 콜백 없는
chrome.storage.sync.set() 관용구.

Firefox 차이: browser.* 는 Promise 네이티브 → unhandled rejection이
콘솔에 surface됨. 동작은 동일하나 경고 노이즈 발생.

해결: fire-and-forget 의미를 보존하기 위해 async 변환 대신
.catch()만 추가하여 로깅. 호출자(onInstalled 리스너)는 여전히
동기 반환.
…락 수정

Copilot 리뷰 (PR edwardkim#169) 반영. 이 핸들러는 Firefox 전용 재작성이라
원작자 의도와 무관하며, 두 가지 버그 수정:

1) browser.downloads.search() reject 처리 부재:
   - handled.add 이후 search throw 시 리스너 전체가 unhandled rejection
   - try/catch로 감싸 로깅 후 이어서 cleanup 조건 평가 가능하도록 수정

2) onCreated 경로로 handled에 등록된 id의 cleanup 미발동:
   - 기존: onChanged 최상단 `if (handled.has(id)) return;` early-return
     때문에 onCreated-handled id는 이후 state:complete 이벤트가 와도
     cleanup 블록에 도달하지 못함 → 메모리 잔존
   - 수정: early-return 제거, 첫 처리 블록을 조건 복합으로 전환
     cleanup 블록은 항상 평가 + handled.has 가드로 대상 한정
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 5 comments.

Files not reviewed (1)
  • rhwp-firefox/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rhwp-firefox/content-script.js Outdated
Comment thread rhwp-firefox/content-script.js Outdated
Comment thread rhwp-firefox/content-script.js
Comment thread rhwp-firefox/manifest.json Outdated
Comment thread rhwp-firefox/build.mjs Outdated
…ch() 추가

Copilot 리뷰 (PR edwardkim#169) 반영.

Firefox browser.* API는 Promise를 반환하므로, 배지 클릭 및 호버 카드 클릭의
fire-and-forget sendMessage()에 .catch()를 추가하여 unhandled rejection 방지.
Chrome 원본은 콜백 기반이라 불필요했지만 Firefox 전환에 따른 필수 보완.

Refs edwardkim#156
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • rhwp-firefox/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rhwp-firefox/sw/message-router.js Outdated
Comment thread rhwp-firefox/sw/message-router.js Outdated
Comment thread rhwp-firefox/content-script.js
Comment thread rhwp-firefox/build.mjs Outdated
@postmelee postmelee marked this pull request as draft April 16, 2026 19:10
- content-script에 isPrivateHost 로컬 유틸 추가
- 프리페치 큐 투입 전 내부망/userinfo URL 차단
- 호버 썸네일 추출 요청 전 동일 필터 적용
- test/06-security.html에 SSRF 케이스 추가

Refs edwardkim#84
Refs edwardkim#156

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread rhwp-firefox/build.mjs Fixed
postmelee and others added 2 commits April 18, 2026 01:17
- execSync 문자열 실행을 execFileSync 인자 배열 실행으로 변경
- Vite 빌드 호출을 shell=false 경로로 고정해 경로 기반 셸 해석 리스크 제거

Refs edwardkim#84
Refs edwardkim#156

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 8 comments.

Files not reviewed (1)
  • rhwp-firefox/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rhwp-firefox/sw/message-router.js Outdated
Comment thread rhwp-firefox/sw/message-router.js Outdated
Comment thread rhwp-firefox/sw/message-router.js Outdated
Comment thread rhwp-firefox/sw/thumbnail-extractor.js Outdated
Comment thread rhwp-firefox/content-script.js Outdated
Comment thread rhwp-firefox/sw/viewer-launcher.js Outdated
Comment thread rhwp-firefox/PRIVACY.md
Comment thread rhwp-firefox/PRIVACY.md
- content-script.js/sw/message-router.js: isPrivateHost가 IPv6
  loopback(::1), IPv4-mapped(::ffff:127.*), link-local(fe80::/10),
  ULA(fc00::/7)까지 차단하도록 패턴 보강. URL().hostname은 대괄호
  없이 반환되므로 normalizeHostname으로 정규화 후 매칭.
- sw/message-router.js: fetch-file sender 검증을 viewer.html로 정확히
  한정(기존에는 모든 확장 내부 페이지 허용). HTTP 차단 사유 메시지를
  실제 동작과 맞게 '설정에서 비허용' → 'HTTPS만 허용'으로 수정.
- sw/thumbnail-extractor.js: fetch 기본 follow로 인해 내부망으로의
  30x 우회가 가능하던 문제를 redirect:'manual' + opaqueredirect/3xx
  차단으로 해결. buildFatTable이 헤더 내 109개 DIFAT 엔트리만 읽어
  대용량 CFB에서 PrvImage 추출이 실패하던 문제를 DIFAT 체인
  (firstDIFATSector/numDIFATSectors) 순회로 보완.
- sw/viewer-launcher.js: openViewerOrReuse에서 tabs.query/update 실패
  시 unhandled rejection을 내던 문제를 try/catch + openViewer 폴백
  으로 처리.
- content-script.js/content-script.css: HWP 배지를 <span>에서
  <button type="button">으로 교체하고 aria-label/focus-visible
  아웃라인을 추가해 키보드·스크린리더 접근성을 확보. button 기본
  스타일을 리셋해 기존 외형 유지.
- manifest.json: web_accessible_resources에서 실제로 웹 페이지가
  필요로 하지 않는 wasm/fonts/icons를 제거하고 dev-tools-inject.js만
  노출. 확장 UUID를 통한 핑거프린팅/대역폭 남용 표면 축소.

Refs: edwardkim#169
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • rhwp-firefox/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rhwp-firefox/sw/thumbnail-extractor.js
Comment thread rhwp-firefox/sw/thumbnail-extractor.js Outdated
Comment thread rhwp-firefox/content-script.js Outdated
Comment thread rhwp-firefox/content-script.js Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • rhwp-firefox/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rhwp-firefox/content-script.js
Comment thread rhwp-firefox/sw/thumbnail-extractor.js Outdated
Comment thread rhwp-firefox/sw/message-router.js Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • rhwp-firefox/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rhwp-firefox/content-script.js
Comment thread rhwp-firefox/sw/message-router.js Outdated
Comment thread rhwp-firefox/content-script.js Outdated
postmelee and others added 4 commits April 18, 2026 19:44
- Add Firefox security-policy adapter over rhwp-shared modules
- Enforce openViewer URL validation and filename sanitization
- Export shared security helpers as ESM and tighten sender validation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Match options hierarchy to remediation plan categories
- Wire allSites permission toggle to dynamic content-script sync
- Apply allowHttp/autoOpen/domain defaults consistently in content script

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Restrict default host/content-script scope to core public domains
- Remove dev-tools script from web_accessible_resources
- Stop unconditional viewer dev-tools injection in build output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add manual redirect chain validation with re-check per hop
- Enforce streamed size limits before buffering response bodies
- Implement HTTPS-first with guarded HTTP fallback warning and stricter URL sanitization

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
postmelee added a commit to postmelee/rhwp that referenced this pull request Apr 18, 2026
- Add URL validator boundary unit tests from remediation plan cases
- Update Firefox security manual test matrix for HTTP/redirect policy
- Add viewer-side file size and parse time guards with warning propagation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
postmelee added a commit to postmelee/rhwp that referenced this pull request Apr 18, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@postmelee postmelee force-pushed the feat/firefox-extension branch from af2f977 to 1045006 Compare April 18, 2026 11:29
- Add URL validator boundary unit tests from remediation plan cases
- Update Firefox security manual test matrix for HTTP/redirect policy
- Add open redirect revalidation test

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@postmelee postmelee force-pushed the feat/firefox-extension branch from 1045006 to a8cb1ae Compare April 18, 2026 11:37
postmelee and others added 3 commits April 18, 2026 20:51
A. 매직 넘버 완화 범위 제한
   - fetch-file: pathname에 .hwp/.hwpx가 있는 URL은 매직 넘버 불일치 시
     Content-Disposition 폴백 없이 즉시 차단
   - 다운로드 엔드포인트(*.do?id=... 등)만 Content-Disposition 보조 검증 허용

B. dist/security 중복 정리
   - build.mjs: 이전 빌드의 stale dist/security/ 자동 삭제
     (올바른 경로: dist/shared/security/)

C. updateDiscoverySignal 단일화
   - content-script.js: 설정 로드 이전 중복 호출 제거
   - settings 로드 성공/실패 모두 then/catch 내부에서 단 1회 호출
   - 로드 전 premature fingerprint 노출 방지

D. package.json test script
   - npm test → node --test url-validator.test.js (12/12 통과)
   - rhwp-shared/package.json "type": "module" 추가 (MODULE_TYPELESS 경고 제거)

E. shared API 계약 문서
   - rhwp-shared/security/README.md 신규 작성
   - 각 모듈 API 계약·매개변수·반환값·완화 범위 제한 규칙 문서화

F. dev-tools 로드 오류 fallback (선택)
   - devScript.onerror: 빌드에 dev-tools-inject.js 없어도 조용히 처리

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- url-validator.js: validateFetchUrl에 allowLocalhost 옵션 추가
  - allowLocalhost: true 시 localhost/127.* 만 허용
  - 10.*, 192.168.*, 172.16-31.*, ::1 등 그 외 내부 IP는 devMode에서도 차단
  - devMode 외에서는 allowLocalhost=false 기본값 유지
- message-router.js: extract-thumbnail 핸들러에 devMode 설정 읽어 연동
  - devMode=true → allowLocalhost: true 전달 (validateRedirectUrl 포함)
  - fetch-file은 viewer.html 전용 + SSRF 위험 크므로 미적용 (의도적)
- _locales: devMode 레이블에 "localhost 허용 — 배포 시 비활성화 권장" 경고 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
이전 커밋에서 service worker(message-router.js)만 수정했으나
content-script도 extract-thumbnail 메시지 전송 전에 isPrivateHost
검사를 수행하고 있어 실제로 메시지가 도달하지 않았음.

- hover card URL 필터: isPrivateHost → !settings.devMode && isPrivateHost
- prefetch URL 필터: 동일 조건 적용

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@edwardkim
Copy link
Copy Markdown
Owner

너무 열심히 하십니다. 대단하세요. 원래 hwpx 저장까지 완성해서 같이 배포할려고 했는데 이거 놔두고 먼저 파이어폭스 애드온 배포할까요?

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.

4 participants