diff --git a/src/.vitepress/config.js b/src/.vitepress/config.js index 9116a4e6..e70bae45 100644 --- a/src/.vitepress/config.js +++ b/src/.vitepress/config.js @@ -35,6 +35,7 @@ export default defineConfig({ { text: "Block Helpers", link: "/block-helpers" }, { text: "Built-in Helpers", link: "/builtin-helpers" }, { text: "Hooks", link: "/hooks" }, + { text: "Security", link: "/security" }, ], }, { @@ -117,6 +118,7 @@ export default defineConfig({ { text: "블록 헬퍼(Block Helpers)", link: "/block-helpers" }, { text: "내장 헬퍼(Built-in Helpers)", link: "/builtin-helpers" }, { text: "훅(Hooks)", link: "/hooks" }, + { text: "보안", link: "/security" }, ], }, { @@ -202,6 +204,7 @@ export default defineConfig({ { text: "块助手代码", link: "/block-helpers" }, { text: "内置助手代码", link: "/builtin-helpers" }, { text: "钩子", link: "/hooks" }, + { text: "安全", link: "/security" }, ], }, { diff --git a/src/guide/security.md b/src/guide/security.md new file mode 100644 index 00000000..1d95295f --- /dev/null +++ b/src/guide/security.md @@ -0,0 +1,74 @@ +# Security + +::: v-pre + +Handlebars is designed to render templates with data. Treat the template, its input data, registered helpers, partials, +and runtime configuration as parts of your application's security boundary. + +## Rendering HTML in the browser + +By default, Handlebars HTML-escapes values rendered with `{{expression}}`. This protects text inserted into HTML markup +from being interpreted as HTML: + +```handlebars +

{{comment}}

+``` + +Do not use triple-stash expressions (`{{{expression}}}`) or return `Handlebars.SafeString` for untrusted content. They +disable this escaping and can introduce cross-site scripting (XSS). If a helper returns HTML, it must escape every +untrusted value before marking the result safe. + +HTML escaping is context-specific. It does not make untrusted data safe in JavaScript, CSS, URLs, or event-handler +attributes. Avoid using templates to generate inline scripts or event handlers. Validate and encode data for its exact +output context, and apply an allowlist before placing untrusted values in CSS. + +### URLs + +HTML escaping does not prevent a URL such as `javascript:...` from executing when used in an `href` or similar +attribute. Sanitize user-provided URLs before rendering them, using an allowlist of permitted schemes such as `https`. + +### Content Security Policy + +Use a [Content Security Policy](https://developer.mozilla.org/docs/Web/HTTP/Guides/CSP) (CSP) when rendering Handlebars +output in a browser. A restrictive CSP can limit the impact of an XSS vulnerability by preventing inline scripts and +restricting the origins from which scripts, styles, images, and other resources may load. Compiling templates in the +browser requires CSP's `'unsafe-eval'`; use [precompiled templates](installation/precompilation.md) and the runtime-only +build to avoid it. Avoid `'unsafe-inline'`. CSP is defense in depth: it does not replace escaping and sanitizing +untrusted content. + +## Compiling and rendering templates on the server + +A template can invoke the helpers and partials that your application exposes, and it renders the data that you provide. +Do not give a template access to secrets or privileged application objects unless it genuinely needs them. Keep the +rendering context small and use helpers with narrow, well-defined behavior. A helper must validate its arguments and +must not turn template input into arbitrary file, network, database, or command access. + +Keep Handlebars up to date and review the runtime options used by your application. In particular, do not relax +prototype-property access controls or enable `allowCallsToHelperMissing`. These options can allow template authors to +execute unintended code through objects available to a template. + +## User-supplied templates + +Templates from users are untrusted programs for resource-consumption purposes. A deeply nested template, repeated +partials, or a template that performs large iterations can consume substantial CPU, memory, or output space. This can +cause a denial of service even when the template cannot execute arbitrary JavaScript. + +When users may submit templates, enforce limits before and during processing: + +- Limit template size, nesting depth, partial recursion, input size, and rendered output size in your application. +- Limit the size of arrays and objects passed to templates, since Handlebars does not limit iterations. +- Apply request timeouts and resource quotas to compilation and rendering. +- Rate-limit template submission and rendering endpoints. + +Compile and render user-supplied templates in an isolated sandbox, such as a separate process or container with strict +CPU, memory, filesystem, and network limits. Do not rely on Handlebars alone as a security sandbox. In that isolated +environment, expose only an allowlist of safe helpers and partials, pass a minimal data object, and avoid application +credentials or host access. + +## Compiling ASTs + +Only compile ASTs produced by Handlebars from trusted template source. Compiling a user-provided or otherwise untrusted +AST is inherently unsafe and must never be done. A crafted AST can violate the compiler's assumptions and produce +executable JavaScript with behavior that the original template language would not permit. + +::: diff --git a/src/ko/guide/security.md b/src/ko/guide/security.md new file mode 100644 index 00000000..e089b973 --- /dev/null +++ b/src/ko/guide/security.md @@ -0,0 +1,74 @@ +# 보안 + +::: v-pre + +Handlebars는 템플릿과 데이터로 결과물을 렌더링하도록 설계되었습니다. 템플릿, 입력 데이터, 등록된 헬퍼, 부분 템플릿, +그리고 런타임 설정은 모두 애플리케이션의 보안 경계 일부로 취급해야 합니다. + +## 브라우저에서 HTML 렌더링 + +기본적으로 Handlebars는 `{{expression}}`으로 렌더링되는 값을 HTML 이스케이프합니다. 이렇게 하면 HTML 마크업에 삽입된 +텍스트가 HTML로 해석되는 것을 방지합니다. + +```handlebars +

{{comment}}

+``` + +신뢰할 수 없는 콘텐츠에는 트리플 스태시 표현식(`{{{expression}}}`)을 사용하거나 `Handlebars.SafeString`을 반환하지 +마세요. 이는 이스케이프를 비활성화하며 크로스 사이트 스크립팅(XSS) 취약점을 만들 수 있습니다. 헬퍼가 HTML을 반환하는 +경우 결과를 안전한 것으로 표시하기 전에 신뢰할 수 없는 모든 값을 이스케이프해야 합니다. + +HTML 이스케이프는 컨텍스트별로 적용됩니다. 신뢰할 수 없는 데이터를 JavaScript, CSS, URL 또는 이벤트 핸들러 속성에서 +안전하게 만들지는 않습니다. 템플릿으로 인라인 스크립트나 이벤트 핸들러를 생성하지 마세요. 정확한 출력 컨텍스트에 맞게 +데이터를 검증하고 인코딩하며, CSS에 신뢰할 수 없는 값을 넣기 전에 허용 목록을 적용하세요. + +### URL + +HTML 이스케이프는 `href` 또는 유사한 속성에서 사용할 때 `javascript:...`와 같은 URL의 실행을 막지 않습니다. 렌더링하기 +전에 `https`와 같이 허용된 스키마의 허용 목록을 사용하여 사용자 제공 URL을 정화하세요. + +### 콘텐츠 보안 정책 + +브라우저에서 Handlebars 출력을 렌더링할 때는 +[콘텐츠 보안 정책](https://developer.mozilla.org/docs/Web/HTTP/Guides/CSP)(CSP)을 사용하세요. 제한적인 CSP는 인라인 +스크립트를 방지하고 스크립트, 스타일, 이미지 및 기타 리소스를 로드할 수 있는 출처를 제한하여 XSS 취약점의 영향을 줄일 수 +있습니다. 브라우저에서 템플릿을 컴파일하려면 CSP의 `'unsafe-eval'`이 필요합니다. 이를 피하려면 +[사전 컴파일된 템플릿](installation/precompilation.md)과 런타임 전용 빌드를 사용하세요. `'unsafe-inline'`은 피하세요. +CSP는 심층 방어 수단이며, 신뢰할 수 없는 콘텐츠의 이스케이프 및 정화를 대체하지 않습니다. + +## 서버에서 템플릿 컴파일 및 렌더링 + +템플릿은 애플리케이션이 제공하는 헬퍼와 부분 템플릿을 호출할 수 있으며, 제공한 데이터를 렌더링합니다. 꼭 필요한 경우가 +아니면 템플릿에 비밀 정보나 권한 있는 애플리케이션 객체에 대한 접근 권한을 부여하지 마세요. 렌더링 컨텍스트를 작게 +유지하고, 동작이 좁고 명확하게 정의된 헬퍼를 사용하세요. 헬퍼는 인수를 검증해야 하며, 템플릿 입력을 임의의 파일, +네트워크, 데이터베이스 또는 명령 접근으로 바꾸면 안 됩니다. + +Handlebars를 최신 상태로 유지하고 애플리케이션이 사용하는 런타임 옵션을 검토하세요. 프로토타입 속성 접근 제어를 +완화하거나 `allowCallsToHelperMissing`을 활성화하지 마세요. 이러한 옵션은 템플릿 작성자가 템플릿에서 사용할 수 있는 +객체를 통해 의도하지 않은 코드를 실행하도록 허용할 수 있습니다. + +## 사용자가 제공한 템플릿 + +사용자 템플릿은 리소스 소비 측면에서 신뢰할 수 없는 프로그램입니다. 깊게 중첩된 템플릿, 반복되는 부분 템플릿 또는 대규모 +반복을 수행하는 템플릿은 상당한 CPU, 메모리 또는 출력 공간을 소비할 수 있습니다. 템플릿이 임의의 JavaScript를 실행할 수 +없더라도 서비스 거부를 일으킬 수 있습니다. + +사용자가 템플릿을 제출할 수 있다면 처리 전후로 제한을 적용하세요. + +- 애플리케이션에서 템플릿 크기, 중첩 깊이, 부분 템플릿 재귀, 입력 크기 및 렌더링된 출력 크기를 제한하세요. +- Handlebars는 반복 횟수를 제한하지 않으므로 템플릿에 전달되는 배열과 객체의 크기를 제한하세요. +- 컴파일과 렌더링에 요청 시간 제한 및 리소스 할당량을 적용하세요. +- 템플릿 제출 및 렌더링 엔드포인트에 속도 제한을 적용하세요. + +사용자 제공 템플릿은 엄격한 CPU, 메모리, 파일 시스템 및 네트워크 제한이 적용된 별도의 프로세스나 컨테이너와 같은 격리된 +샌드박스에서 컴파일하고 렌더링하세요. Handlebars만을 보안 샌드박스로 신뢰하지 마세요. 이 격리된 환경에서는 안전한 헬퍼와 +부분 템플릿의 허용 목록만 노출하고, 최소한의 데이터 객체만 전달하며, 애플리케이션 자격 증명이나 호스트 접근을 제공하지 +마세요. + +## AST 컴파일 + +신뢰할 수 있는 템플릿 소스에서 Handlebars가 생성한 AST만 컴파일하세요. 사용자가 제공했거나 그 외에 신뢰할 수 없는 AST를 +컴파일하는 일은 본질적으로 안전하지 않으므로 절대 해서는 안 됩니다. 조작된 AST는 컴파일러의 가정을 깨뜨리고 원래 템플릿 +언어가 허용하지 않는 동작을 하는 실행 가능한 JavaScript를 생성할 수 있습니다. + +::: diff --git a/src/zh/guide/builtin-helpers.md b/src/zh/guide/builtin-helpers.md index 9637f444..89c2fcba 100644 --- a/src/zh/guide/builtin-helpers.md +++ b/src/zh/guide/builtin-helpers.md @@ -101,8 +101,8 @@ 嵌套的每个块都可以通过基于深度的路径来访问迭代变量。例如,要访问父级的索引,可以使用 `{{@../index}}`。 -在当前项本身是一个数组时,可以使用 [段字面量语法](expressions.md#文字) -来读取固定的索引。普通的 `this[0]` 不是有效的 Handlebars 语法,应该写成 `this.[0]`: +在当前项本身是一个数组时,可以使用 [段字面量语法](expressions.md#文字) 来读取固定的索引。普通的 `this[0]` +不是有效的 Handlebars 语法,应该写成 `this.[0]`: ```handlebars