From 228ff32d385628250dc454b59a7d5f6d7f3cd922 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Wed, 29 Jul 2026 14:03:33 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[=EB=B3=B4?= =?UTF-8?q?=EC=95=88=20=EA=B0=9C=EC=84=A0]=20Prevent=20base=20tag=20inject?= =?UTF-8?q?ion=20by=20enforcing=20base-uri=20'none'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 이 커밋은 정적 사이트의 index.html Content-Security-Policy에서 `base-uri 'self'`를 `base-uri 'none'`으로 강화하여, 악의적인 베이스 태그 주입(Base Tag Injection) 공격의 가능성을 원천 차단합니다. 변경 사항을 검증하는 테스트 케이스를 추가하고, 관련 지식을 저널에 기록했습니다. --- .jules/sentinel.md | 4 ++++ CHANGELOG.md | 1 + index.html | 2 +- tests/test_index_security.py | 26 ++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 tests/test_index_security.py diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 4f173bc..c07cc17 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -38,3 +38,7 @@ **Vulnerability:** Missing input validation on `setLanguage()` could allow invalid strings (like Prototype Pollution payloads or arbitrary text) to be applied to the DOM (`lang` attribute) and stored in `localStorage`. **Learning:** The global `setLanguage` function assumed inputs would only come from predefined button clicks, skipping runtime validation. **Prevention:** Always sanitize and validate function arguments at the application boundary, even if the primary caller is trusted, to enforce defense in depth. +## 2026-07-29 - Prevent Base Tag Injection via CSP +**Vulnerability:** The Content-Security-Policy in `index.html` used `base-uri 'self'`, which, while somewhat restrictive, could still allow attackers to inject a `` tag pointing to a malicious path on the same origin (if one existed or could be created) or could be unnecessarily loose for a static site that does not use ``. +**Learning:** For static sites that do not explicitly require a `` tag for relative URL resolution, using `base-uri 'self'` is overly permissive. Base tag injection can hijack relative links and form submissions. +**Prevention:** When configuring Content Security Policy (CSP) for static sites that do not explicitly require a `` tag, use `base-uri 'none'` instead of `base-uri 'self'` to strictly prevent base tag injection attacks. diff --git a/CHANGELOG.md b/CHANGELOG.md index 56ad628..c0e8842 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CHANGELOG ## [Unreleased] +- **보안 개선**: 정적 사이트의 Base Tag Injection 공격을 예방하기 위해 `index.html`의 Content-Security-Policy에서 `base-uri 'self'`를 `base-uri 'none'`으로 강화했습니다. - **보안 개선**: 컴포넌트 갤러리의 인라인 스크립트와 스타일을 외부 파일로 분리하고, 엄격한 Content-Security-Policy를 적용해 XSS 방어를 강화했습니다. - **성능 회귀 복원**: 오프스크린 `.section` 렌더링을 `content-visibility: auto`로 지연하고, 일반 섹션은 600px·콘텐츠가 큰 DIKW/projects 섹션은 1000px의 `contain-intrinsic-size` placeholder를 유지해 초기 렌더링 비용과 스크롤바 이동을 함께 줄였습니다. - **보안 개선**: Trusted Types 기반 CSP 강화: 잠재적인 DOM 기반 XSS 공격을 방지하기 위해 `require-trusted-types-for 'script'` 지시어 추가 diff --git a/index.html b/index.html index c40fea3..25ee55a 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - + 맥락지혜 연구실 | Contextual Wisdom Lab str: + """Return the main index HTML source.""" + return INDEX.read_text(encoding="utf-8") + +def _csp_content(html: str) -> str: + """Extract the CSP meta policy from the HTML.""" + match = re.search( + r' None: + """The main site prevents base tag injection attacks.""" + policy = _csp_content(_index_html()) + assert "base-uri 'none'" in policy + assert "base-uri 'self'" not in policy