"MV3의 보안 모델은 까칠할 정도로 의견이 강해 — 그게 버그가 아니라 feature."
Extension Sandbox
모든 Chrome extension은 자기 renderer process에서 돌아, 상호작용하는 host page와 격리. Extension은 chrome.* API와 사적 origin (chrome-extension://<id>/)에 접근하지만, host page의 JavaScript context에 직접 손 못 대. 통신은 의도된 채널로만 — message / isolated world에 injected 된 content script / Chrome의 tab API.
이 격리가 extension이 user-script injector 보다 안전한 전체 이유. Host page가 extension storage를 손쉽게 못 읽고, extension이 host의 global scope를 실수로 오염시킬 수도 없어.
MV3의 Content Security Policy
MV3는 extension page (popup / options / side panel)에 빡센 default CSP를 박아:
script-src 'self'; object-src 'self';
풀어 쓰면 이래. script는 extension package 안에 있는 것만 돌아. inline <script> 태그 안 되고, eval() 안 되고, new Function() 안 되고, handler에 JavaScript URI도 안 돼. Lesson 4에서 만난 CSP gotcha가 바로 이 default에서 나온 거야.
CSP를 더 조일 수는 있어. 드물지만 가능해. 반대로 푸는 건 아주 빡빡하게 막혀 있고. 'unsafe-eval'은 완전 금지. 'unsafe-inline'은 script에 대해 금지. WebAssembly compilation 진짜 필요하면 'wasm-unsafe-eval' 허용.
host_permissions — 어떤 page를 만질 수 있어
API permissions와 별개로 host_permissions는 민감한 tab field 읽기, cross-origin fetch, scripting을 통한 programmatic injection 같은 URL 범위 능력을 열어. 이것만 쓴다고 script가 자동 injection되지는 않아. 정적 injection은 content_scripts.matches, 동적 injection은 scripting 같은 API가 따로 맡아.
- 좁게 — 특정 origin list:
["https://news.ycombinator.com/*", "https://*.github.com/*"]. Chrome이 install 시 user 한테 정확히 어떤 site가 영향받는지 보여줌. - 광범위 —
["<all_urls>"]. 살벌한 install 경고 발동: "모든 website의 모든 data를 읽고 변경." Extension이 진짜로 어디든 page access 필요할 때만 (ClipDeck은 결국 필요 — selection capture가 어느 page 에서든 동작해야).
중간 길이 하나 있어. API permissions에 activeTab을 넣는 거야. 필요한 순간에만 주는 방식이지 — user가 toolbar icon을 누르면 Chrome이 그 tab의 민감한 metadata와 origin 접근을 잠깐 열어 주고, DOM injection 자체는 chrome.scripting이나 이미 선언한 content script가 맡고, 그 tab이 다른 데로 넘어가면 도로 닫혀. Install 할 때 경고도 안 뜨고, 넓은 권한을 계속 들고 있지도 않아.
Remote code 금지
MV3는 network로 JavaScript fetch 후 실행 금지. 구체적으로:
fetch("https://...")후 response에eval()안 됨.- Extension HTML page에
<script src="https://cdn.example.com/foo.js">안 됨. new Function(remoteString)안 됨.
허용되는 거: network로 fetch 한 data (JSON / text / image)를 data로 다루기. 경계선은 실행. Server가 extension 한테 뭘 렌더하라고 알려 — OK. Server가 extension 한테 뭘 실행하라고 알려 — 금지.
chrome.permissions API — 필요할 때 요청
optional_permissions 또는 optional_host_permissions에 선언된 permission은 extension이 runtime에 chrome.permissions.request로 요청 가능. 그러면 Chrome이 확인 창을 띄우고 user가 허락하거나 거절해. 다 미리 선언해 놓고 install 할 때 사람 놀래키는 것보다 훨씬 예의 있는 방식이지.
ClipDeck은 필요한 permission을 전부 미리 선언한 채로 갈 거야. 사적인 tailnet 안에서 혼자 쓰는 도구한테는 optional-permission flow가 딱히 쓸 데가 없거든. 그래도 이런 API가 있다는 건 알아 둬. 여러 Mac에 뿌릴 extension을 설계할 때, install 화면부터 사람 겁주고 싶지 않다면 그때 이게 필요해져.
<script> 태그랑 onclick= handler를 훑는 게 제일 빠른 복구 경로야.