Vulnerability: Missing Content Security Policy (CSP) header.
Learning: Static HTML sites often neglect CSP, leaving them exposed to XSS or data injection if they later add dynamic content or if third-party scripts are compromised.
Prevention: Always include a strict baseline CSP (default-src 'self') in index.html for static sites to establish defense-in-depth from the start.
Vulnerability: Unvalidated user input from location.search was used directly as an object key (messages[query]). This allowed an attacker to supply ?lang=__proto__ or ?lang=valueOf, resulting in messages[query] returning built-in objects or functions rather than the intended language strings.
Learning: Checking for truthiness like messages[query] ? query : ... fails securely when dealing with inherited Object properties. Without a whitelist, user input accessing un-prototyped object keys is dangerous.
Prevention: Always validate external input against a strict whitelist (e.g. ['ko', 'en'].includes(query)) before using it in application logic, or ensure dictionaries are created without prototypes (Object.create(null)).
Vulnerability: Unhandled exceptions when accessing localStorage in strict browser privacy modes (e.g., when cookies are blocked).
Learning: Browsers throw a SecurityError when localStorage is accessed and the user has blocked third-party cookies or is in a strict privacy mode. If unhandled, this crashes the executing script, leading to a degraded user experience (DoS-like behavior for privacy-conscious users).
Prevention: Always wrap localStorage.getItem and localStorage.setItem in try-catch blocks to fail securely and fall back to sensible defaults.
Vulnerability: 외부 링크(특히 참조문헌 링크 등)에 target="_blank" 속성을 사용하거나 새 탭으로 여는 동작을 유도할 때, rel="noopener noreferrer" 속성이 누락되어 Reverse Tabnabbing 공격에 노출될 수 있음.
Learning: rel="noopener noreferrer"가 없으면 새로 열린 탭의 페이지가 window.opener 객체를 통해 원래 페이지의 location을 악의적인 사이트로 변경할 수 있습니다.
Prevention: 외부 링크를 새 탭으로 열기 위해 target="_blank"를 사용할 때만 rel="noopener noreferrer"를 함께 추가하여 부모 창에 대한 접근을 차단해야 합니다.
Vulnerability: 애플리케이션에 Trusted Types가 적용되지 않아, 향후 innerHTML과 같은 안전하지 않은 DOM sink가 도입될 경우 잠재적인 DOM 기반 XSS 공격에 취약해질 수 있음.
Learning: 애플리케이션이 textContent와 같은 안전한 DOM API만을 사용하고 위험한 sink가 없기 때문에, Trusted Types 정책이나 DOMPurify 같은 외부 새니타이저 없이도 CSP를 통해 네이티브하게 require-trusted-types-for 'script'를 강제할 수 있음.
Prevention: 적용 가능할 때는 항상 CSP에 Trusted Types를 적용하여 DOM XSS 회귀를 선제적으로 방지해야 함.
Vulnerability: Trusted Types 정책 부재로 인한 DOM 기반 XSS (Cross-Site Scripting) 취약점 위험.
Learning: 이 정적 웹사이트는 innerHTML 같은 위험한 Sink를 사용하지 않고 textContent, setAttribute 등 안전한 DOM API만을 사용하고 있으므로, 별도의 Trusted Types 정책이나 외부 Sanitizer(예: DOMPurify) 없이도 CSP에서 require-trusted-types-for 'script'를 안전하게 기본 강제할 수 있음을 확인했습니다.
Prevention: CSP에 require-trusted-types-for 'script'를 적용하여 XSS를 방어하고, 앞으로도 안전한 DOM API만 사용하도록 합니다. 부득이하게 innerHTML을 도입해야 할 경우에는 반드시 적절한 Sanitizer를 함께 구성해야 합니다.
Vulnerability: Application lacked Trusted Types enforcement, which left it potentially vulnerable to DOM-based XSS if DOM sinks (like innerHTML) were manipulated.
Learning: Enforcing require-trusted-types-for 'script' in CSP causes Chromium-based browsers to throw a Trusted Types violation (a TypeError) when a string is assigned to a DOM sink without a registered policy, rather than crashing the browser.
Prevention: When a default Trusted Types policy is needed, pair the CSP require-trusted-types-for 'script' directive with a defensively loaded sanitizer such as DOMPurify, defer the scripts in dependency order, and keep policy creation wrapped so an existing policy or CSP restriction does not break page load.
Vulnerability: DOM 기반 XSS (안전하지 않은 DOM 싱크 노출 위험)
Learning: 이 앱은 주로 textContent와 같은 안전한 DOM API 사용을 하고 innerHTML 등의 위험한 싱크를 피함. 이러한 환경에서는 브라우저 네이티브인 require-trusted-types-for 'script' CSP 규칙이 1차 방어선이며, 기본 Trusted Types 정책과 DOMPurify는 실제 HTML 싱크 또는 호환성 요구가 있을 때 방어적으로 로드해야 함.
Prevention: 새로운 기능을 추가할 때 앱의 DOM API 사용 방식을 먼저 파악하고, 네이티브 Trusted Types CSP만으로 충분한지 또는 DOMPurify 기반 기본 정책이 필요한지 판단할 것. 기본 정책을 유지한다면 window.trustedTypes와 window.DOMPurify를 확인하고 try/catch로 감싸 페이지 로드를 깨지 않도록 할 것.
Vulnerability: Weak Content-Security Policy due to lack of headers and usage of inline scripts/styles in components/index.html.
Learning: Adding a strict CSP (style-src 'self') breaks inline HTML style attributes and inline data: image URIs in CSS, requiring extraction into CSS classes and explicit scheme additions (e.g., img-src 'self' data:;).
Prevention: Always refactor inline <script> and <style> blocks to external files, and replace inline style="..." attributes with utility classes before rolling out a strict CSP.
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.
Vulnerability: The main index.html used a permissive default-src 'self' CSP and base-uri 'self', which is weaker than a strict deny-by-default approach.
Learning: Even static HTML sites should use a strict deny-by-default CSP (default-src 'none') and explicitly allow only necessary asset types (script-src, style-src, etc.) to minimize attack surface in case of future changes or vulnerabilities. base-uri 'none' and object-src 'none' are also crucial.
Prevention: Always default to a strict default-src 'none' CSP for all HTML entry points, explicitly declaring necessary sources.
Vulnerability: 사용자 입력값(lang)을 검증 없이 console.warn과 같은 로그 함수에 그대로 보간하여 출력할 경우, 로그 인젝션(Log Forging) 공격에 노출될 수 있음.
Learning: 사용자 입력이 포함된 문자열을 직접 보간하면 악의적인 페이로드가 로그 파일에 주입되어 로그 분석 시스템을 방해하거나 다른 취약점을 연계할 수 있음.
Prevention: 로그를 남길 때는 검증되지 않은 외부 입력값을 동적으로 문자열에 주입(Interpolation)하는 대신, 사전에 정의된 정적이고 안전한 메시지로 대체해야 함.
Vulnerability: DOM 요소를 탐색할 때 (예: document.getElementById, element.closest) 결과가 null인지 확인하지 않고 속성을 변경하거나 메서드를 호출하여 발생하는 unhandled script exception.
Learning: 정적 웹사이트 프론트엔드 코드에서 DOM 요소를 조회할 때, 해당 요소가 존재하지 않으면 TypeError가 발생하여 스크립트 실행이 중단될 수 있습니다. 이를 DoS 취약점으로 취급하지는 않으나(보안 극장 방지), 방어적 프로그래밍 관점에서 우아한 기능 저하(graceful degradation)를 위해 null 체크가 필수적입니다.
Prevention: Vanilla JavaScript에서 DOM API로 요소를 조회한 후 속성 변경이나 메서드 호출을 수행하기 전에 항상 반환값이 null이 아닌지 검증하는 방어적 프로그래밍 패턴을 적용해야 합니다.