fix(bridge): CSP script-src 'unsafe-inline' patch for renderer v3 execution #task-264
This commit is contained in:
@@ -241,4 +241,11 @@
|
|||||||
- AG 패치 후 **반드시 풀 프로세스 재시작** 필요 (Reload Window 불충분)
|
- AG 패치 후 **반드시 풀 프로세스 재시작** 필요 (Reload Window 불충분)
|
||||||
- **양쪽 HTML (workbench.html + workbench-jetski-agent.html) 모두 inline 패치** 필수
|
- **양쪽 HTML (workbench.html + workbench-jetski-agent.html) 모두 inline 패치** 필수
|
||||||
- HTML 패치 변경 시 **`%APPDATA%\Antigravity\CachedData` 삭제 필수** (V8 바이트코드 캐시 무효화)
|
- HTML 패치 변경 시 **`%APPDATA%\Antigravity\CachedData` 삭제 필수** (V8 바이트코드 캐시 무효화)
|
||||||
|
- **CSP `script-src`에 `'unsafe-inline'` 패치 필수** (없으면 인라인 스크립트 무조건 차단)
|
||||||
|
|
||||||
|
### [2026-03-09] CSP script-src — 인라인 스크립트 무조건 차단
|
||||||
|
- **증상**: HTML 패치 ✅, 체크섬 ✅, CachedData 삭제 ✅ — 그런데도 renderer v3 스크립트 미실행 (`/deep-inspect` timeout)
|
||||||
|
- **원인**: `workbench.html`의 CSP `<meta http-equiv="Content-Security-Policy">`에서 `script-src 'self' 'unsafe-eval' blob:` — **`'unsafe-inline'` 없음**. 브라우저가 인라인 `<script>` 태그를 무조건 차단
|
||||||
|
- **해결**: CSP의 `script-src`에 `'unsafe-inline'` 추가. Extension `setupApprovalObserver()`에 CSP 자동 패치 로직 영구 추가
|
||||||
|
- **주의**: `style-src`에는 `'unsafe-inline'`이 있어 스타일은 동작 → 스크립트만 차단되는 것이 함정. `connect-src`에 `http://127.0.0.1:*` 존재하여 HTTP fetch는 허용됨 (CSP 통과 시 통신은 문제없음). 이 CSP 이슈는 **V8 CachedData 이슈와 동시에 존재**하여 진단이 매우 어려웠음
|
||||||
|
|
||||||
|
|||||||
@@ -8,3 +8,4 @@
|
|||||||
| 004 | 18:08~18:23 | Deep inspect HTTP endpoint (/deep-inspect) + 렌더러 재귀 인스펙터 | `a07d9d3` | 🔧 |
|
| 004 | 18:08~18:23 | Deep inspect HTTP endpoint (/deep-inspect) + 렌더러 재귀 인스펙터 | `a07d9d3` | 🔧 |
|
||||||
| 005 | 18:30~19:28 | workbench.html inline v3 패치 누락 수정 + pre-patch 검증 | `b61cff1` | 🔧 |
|
| 005 | 18:30~19:28 | workbench.html inline v3 패치 누락 수정 + pre-patch 검증 | `b61cff1` | 🔧 |
|
||||||
| 006 | 19:38~19:56 | V8 CachedData 진단 + 캐시 삭제 (renderer 미실행 근본 원인) | docs only | 🔧 |
|
| 006 | 19:38~19:56 | V8 CachedData 진단 + 캐시 삭제 (renderer 미실행 근본 원인) | docs only | 🔧 |
|
||||||
|
| 007 | 20:04~20:28 | CSP script-src `'unsafe-inline'` 패치 (renderer 미실행 진짜 근본 원인) | TBD | 🔧 |
|
||||||
|
|||||||
45
docs/devlog/entries/20260309-007.md
Normal file
45
docs/devlog/entries/20260309-007.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# CSP script-src `'unsafe-inline'` 패치 — 렌더러 v3 스크립트 미실행 근본 원인
|
||||||
|
|
||||||
|
- **시작**: 2026-03-09 20:04 KST
|
||||||
|
- **종료**: 2026-03-09 20:28 KST
|
||||||
|
- **상태**: 🔧 미완료 (AG 재시작 후 /deep-inspect 검증 필요)
|
||||||
|
- **Vikunja**: #264 → 진행중
|
||||||
|
|
||||||
|
## 핵심 발견
|
||||||
|
|
||||||
|
### Root cause: CSP `script-src`에 `'unsafe-inline'` 없음
|
||||||
|
|
||||||
|
이전 세션(#005~#006)에서 HTML 패치 + 체크섬 + CachedData 삭제 모두 정상이었으나 renderer v3 스크립트가 미실행되는 근본 원인 발견.
|
||||||
|
|
||||||
|
**CSP 분석:**
|
||||||
|
```
|
||||||
|
script-src 'self' 'unsafe-eval' blob: ← 'unsafe-inline' 없음!
|
||||||
|
style-src 'self' 'unsafe-inline' ← 스타일은 허용 (함정)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `<script src="./x.js">` → `'self'`로 허용되나 `vscode-file://`가 커스텀 파일 서빙 차단
|
||||||
|
- `<script>inline code</script>` → `'unsafe-inline'` 없어 CSP가 무조건 차단
|
||||||
|
- **두 방법 모두 차단 → deadlock이었음**
|
||||||
|
|
||||||
|
### 추가 검증
|
||||||
|
- `require-trusted-types-for 'script'` → static `<script>` 태그에 영향 없음 (확인)
|
||||||
|
- 스크립트 내 `innerHTML`/`document.write`/`eval` → 0건 (Trusted Types 충돌 없음)
|
||||||
|
- `connect-src`에 `http://127.0.0.1:*` → Bridge HTTP 통신은 CSP 허용 범위
|
||||||
|
|
||||||
|
### 이전 세션 KI와의 관계
|
||||||
|
- KI `renderer_security_and_lifecycle.md` Line 28: "인라인 스크립트로 우회" → 해결책으로 기록
|
||||||
|
- **그러나 인라인도 CSP가 차단한다는 분석이 누락** → 이번에 최초 발견
|
||||||
|
|
||||||
|
## 수정 내역
|
||||||
|
|
||||||
|
| 파일 | 변경 |
|
||||||
|
|------|------|
|
||||||
|
| `extension/src/extension.ts` | `setupApprovalObserver()`에 CSP `'unsafe-inline'` 자동 패치 로직 추가 |
|
||||||
|
| `.agents/references/known-issues.md` | CSP script-src 이슈 + 핵심 전제에 CSP 패치 필수 추가 |
|
||||||
|
| 양쪽 HTML (수동) | `'unsafe-inline'` 추가 + 체크섬 업데이트 + CachedData 삭제 |
|
||||||
|
|
||||||
|
## 다음 단계 (다음 세션)
|
||||||
|
|
||||||
|
1. AG 완전 재시작
|
||||||
|
2. `curl.exe http://127.0.0.1:34332/deep-inspect` → 렌더러 응답 확인
|
||||||
|
3. 응답 시 webview iframe 접근성 분석 → E2E 승인 테스트
|
||||||
@@ -303,6 +303,13 @@ async function setupApprovalObserver() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let html = fs.readFileSync(htmlPath, 'utf8');
|
let html = fs.readFileSync(htmlPath, 'utf8');
|
||||||
|
// CRITICAL: Patch CSP to allow inline scripts.
|
||||||
|
// Default CSP has script-src 'self' 'unsafe-eval' blob: — NO 'unsafe-inline'.
|
||||||
|
// Without 'unsafe-inline', all inline <script> tags are silently blocked.
|
||||||
|
if (html.includes('script-src') && !html.match(/script-src[^;]*'unsafe-inline'/)) {
|
||||||
|
html = html.replace(/(script-src\s[^;]*?)('self')/, "$1$2\n\t\t\t\t\t'unsafe-inline'");
|
||||||
|
logToFile(`[OBSERVER] ${htmlFileName} CSP patched: added 'unsafe-inline' to script-src`);
|
||||||
|
}
|
||||||
// Remove old external script tag if present (legacy, cannot be served)
|
// Remove old external script tag if present (legacy, cannot be served)
|
||||||
const extMarkerStart = '<!-- AG SDK [variet-gravity-bridge] -->';
|
const extMarkerStart = '<!-- AG SDK [variet-gravity-bridge] -->';
|
||||||
const extMarkerEnd = '<!-- /AG SDK [variet-gravity-bridge] -->';
|
const extMarkerEnd = '<!-- /AG SDK [variet-gravity-bridge] -->';
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -265,6 +265,17 @@ async function setupApprovalObserver() {
|
|||||||
}
|
}
|
||||||
let html = fs.readFileSync(htmlPath, 'utf8');
|
let html = fs.readFileSync(htmlPath, 'utf8');
|
||||||
|
|
||||||
|
// CRITICAL: Patch CSP to allow inline scripts.
|
||||||
|
// Default CSP has script-src 'self' 'unsafe-eval' blob: — NO 'unsafe-inline'.
|
||||||
|
// Without 'unsafe-inline', all inline <script> tags are silently blocked.
|
||||||
|
if (html.includes('script-src') && !html.match(/script-src[^;]*'unsafe-inline'/)) {
|
||||||
|
html = html.replace(
|
||||||
|
/(script-src\s[^;]*?)('self')/,
|
||||||
|
"$1$2\n\t\t\t\t\t'unsafe-inline'"
|
||||||
|
);
|
||||||
|
logToFile(`[OBSERVER] ${htmlFileName} CSP patched: added 'unsafe-inline' to script-src`);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove old external script tag if present (legacy, cannot be served)
|
// Remove old external script tag if present (legacy, cannot be served)
|
||||||
const extMarkerStart = '<!-- AG SDK [variet-gravity-bridge] -->';
|
const extMarkerStart = '<!-- AG SDK [variet-gravity-bridge] -->';
|
||||||
const extMarkerEnd = '<!-- /AG SDK [variet-gravity-bridge] -->';
|
const extMarkerEnd = '<!-- /AG SDK [variet-gravity-bridge] -->';
|
||||||
|
|||||||
Reference in New Issue
Block a user