Conversation
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>
There was a problem hiding this comment.
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.
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 제거 + 관련 주석 정리.
There was a problem hiding this comment.
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.
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 가드로 대상 한정
There was a problem hiding this comment.
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.
…ch() 추가 Copilot 리뷰 (PR edwardkim#169) 반영. Firefox browser.* API는 Promise를 반환하므로, 배지 클릭 및 호버 카드 클릭의 fire-and-forget sendMessage()에 .catch()를 추가하여 unhandled rejection 방지. Chrome 원본은 콜백 기반이라 불필요했지만 Firefox 전환에 따른 필수 보완. Refs edwardkim#156
There was a problem hiding this comment.
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.
- 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>
- execSync 문자열 실행을 execFileSync 인자 배열 실행으로 변경 - Vite 빌드 호출을 shell=false 경로로 고정해 경로 기반 셸 해석 리스크 제거 Refs edwardkim#84 Refs edwardkim#156 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
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.
- 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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
- 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>
- 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>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
af2f977 to
1045006
Compare
- 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>
1045006 to
a8cb1ae
Compare
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>
|
너무 열심히 하십니다. 대단하세요. 원래 hwpx 저장까지 완성해서 같이 배포할려고 했는데 이거 놔두고 먼저 파이어폭스 애드온 배포할까요? |
변경 요약
rhwp-chrome기반으로 Firefox 확장 프로그램rhwp-firefox/를 신규 추가합니다. 포팅과 함께 확장 보안 기준선(발신자 검증, SSRF 방어, fetch 안전화, 접근성, 리소스 노출 축소)까지 같은 PR에서 정립합니다. 기존 Rust/WASM/rhwp-studio 코드 및rhwp-chrome/은 수정하지 않습니다.커밋 구성
Firefox 전용으로 재작성이 필요한 포팅 커밋(#1
6)과 Copilot 리뷰 대응·보안 기준선 커밋(#710)으로 구성됩니다.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종feat(rhwp-firefox): manifest — Firefox MV3 + gecko settingsmanifest.jsonfeat(rhwp-firefox): browser.* API 네임스페이스 전환background.js,content-script.js,sw/{context-menus,message-router,viewer-launcher}.jsfeat(rhwp-firefox): download-interceptor — onCreated + onChanged 기반 재구현sw/download-interceptor.jsfeat(rhwp-firefox): options 페이지 — CSP 호환 외부 스크립트 분리options.html,options.jsdocs(rhwp-firefox): README — Firefox 설치/빌드 가이드 재작성README.mdfeat(rhwp-firefox): message-router — sender/URL 검증 및 fetch 안전화sw/message-router.js,build.mjsfeat(rhwp-firefox): content-script — 프리페치/호버 URL 필터 적용 (SSRF 방어)content-script.js,test/06-security.htmlfix(rhwp-firefox): build 스크립트 shell 실행 제거build.mjs(execSync→execFileSync)fix(rhwp-firefox): resolve Copilot review comments on PR #169content-script.{js,css},manifest.json,sw/{message-router,thumbnail-extractor,viewer-launcher}.jsFirefox 전용 수정 근거
1.
manifest.json— Firefox MV3 + gecko settings (커밋 2)background.service_worker→background.scripts배열browser_specific_settings.gecko추가 —id,strict_min_version: "112.0",data_collection_permissions: {"required":["none"]}options_ui.browser_style: false2.
browser.*API 네임스페이스 전환 (커밋 3)Firefox 네이티브
browser.*는 콜백을 지원하지 않고 Promise만 반환합니다. 단순 문자열 치환만으로는 콜백 기반 코드가 동작하지 않아 아래 파일을 Promise 체인/async-await로 재작성했습니다.content-script.js:runtime.sendMessage3곳(get-settings, 호버 썸네일, 프리페치 썸네일) —.catch()오류 처리 포함sw/context-menus.js,sw/viewer-launcher.js,sw/message-router.js3.
sw/download-interceptor.js— 알고리즘 재설계 (커밋 4)Firefox는 Chrome 전용
downloads.onDeterminingFilename을 지원하지 않아 재구현.onCreated에서 URL 기반 즉시 감지onChanged(filename 확정) 시browser.downloads.search로 최신DownloadItem재조회handledSet으로 중복 처리 방지 (완료/에러 30초 후 cleanup)4.
options.html+options.js— CSP 인라인 스크립트 분리 (커밋 5)Firefox MV3의 CSP(
script-src 'self')가 인라인<script>를 차단하므로 외부 파일로 분리.browser.storage.syncPromise 기반 재작성.확장 보안 기준선
커밋 #7~10에서 확립한 최종 기준선입니다. 웹 확장이 공격자 페이지의 링크를 신뢰할 수 없다는 전제 아래, 프리페치·호버·뷰어 fetch 전 구간에서 방어를 적용합니다.
발신자 검증 (sw/message-router.js)
fetch-file:isViewerPage로viewer.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/.localURL().hostname이[::1]를::1로 반환하는 점을 반영해normalizeHostname으로 대괄호 제거 후 매칭fetch 안전화
credentials: 'omit'— 쿠키·인증 누출 차단redirect: 'manual'+response.type === 'opaqueredirect'와 3xx status 거부 — 검증 통과 URL이 내부망으로 30x 우회되는 SSRF 차단'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통과 — 기존 코드 무수정about:debugging로 임시 부가 기능 로드, HWP 파일 뷰어 탭 렌더링 확인Firefox 확장 자체 검증
web-ext lint: errors 0KEY_FIREFOX_UNSUPPORTED_BY_MIN_VERSION(strict_min_version 112.0 정책적 유지로 인한 안내성 경고)rhwp-firefox/test/6종 — 전체 통과Chrome 확장의 수동 테스트 페이지를 그대로 복사한
rhwp-firefox/test/를 Firefox 임시 부가 기능으로 로드해 실행한 결과, 모든 검증 항목이 Chrome과 동일하게 동작함을 확인했습니다.01-auto-detect.html02-data-hwp-protocol.htmldata-hwp-*메타데이터 속성(제목/쪽수/용량/작성자/썸네일 등) 반영03-dynamic-content.htmlMutationObserver로 동적 DOM에 추가된 HWP 링크에도 배지 부착04-devtools.htmlrhwpDev개발자 API 노출 및 호출 가능05-gov-site-sim.html06-security.htmljavascript:) / SSRF(http://127.0.0.1,http://[::1], userinfo URL) 차단스크린샷
범위 외 (참고)
gecko.id: 현재rhwp@edwardkim.github.io— 변경 가능하도록 manifest에 주석 명시DEVELOPER_GUIDE.md: 중복 생성 없이../rhwp-chrome/DEVELOPER_GUIDE.md를README.md에서 참조rhwp-firefox/test/*.html을 headless 실행하는 single-log verdict 하니스는 본 PR 범위 외로 분리 예정 (별도 PR)