Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions internal/config/allowlist/allowed_ext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ func TestIsAllowedExt(t *testing.T) {
{".ETS", true},
{".json5", true},
{".JSON5", true},
{".ftl", true},
{".FTL", true},
{".ftlh", true},
{".FTLH", true},
{".ftlx", true},
{".FTLX", true},
{".txt", false},
{".md", false},
{".png", false},
Expand Down
3 changes: 3 additions & 0 deletions internal/config/allowlist/supported_file_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
".less",
".html",
".htm",
".ftl",
".ftlh",
".ftlx",
".astro",
".vue",
".svelte",
Expand Down
36 changes: 36 additions & 0 deletions internal/config/rules/rule_docs/freemarker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#### Obvious Typos or Spelling Errors
- Spelling errors in macro names, assigned variable names, or user-facing text at their declaration sites; do not report at reference sites
- Typos in `<#assign>`/`<#macro>`/`<#function>` names that surface only at render time (`InvalidReferenceException` / macro not found), or that are silently masked by `!` defaults and `??` guards

#### Output Escaping and XSS
- Interpolations (`${...}`) that reach HTML without escaping: flag only when auto-escaping is not already active — i.e. the template lacks `<#ftl output_format="HTML">` (FreeMarker 2.3.24+) AND does not use the `.ftlh`/`.ftlx` extension (which auto-activate HTML/XML escaping via `recognize_standard_file_extensions`, on by default since 2.3.24) — and the value is not passed through `?html`/`?url`/`?js_string` appropriate to its sink (HTML body, attribute, URL, JS, CSS)
- Explicit `?no_esc` or `<#noautoesc>` on values that carry user-controlled data — treat as a high-risk escape hatch; flag unless the source is clearly trusted or already sanitized
- Escaping with the wrong context builtin (e.g. `?html` for a value placed inside a URL or inline `<script>`)
- Do not report missing `?html` when auto-escaping is active for the file's output format and no override disables it

#### Template Injection / RCE (SSTI)
- User-controlled data concatenated into template source, or templates whose name/body derives from request input (`<#include>`, `<#import>`, `.get_optional_template(userValue)`) — enables server-side template injection
- Use of the `?new()` builtin to instantiate `TemplateModel` classes, especially `freemarker.template.utility.Execute` or `ObjectConstructor` — arbitrary code execution; flag unless the class is a vetted internal type
- `?api` / `?eval` on untrusted input, or exposing raw `Class`/`ClassLoader`/`ProcessBuilder`-reachable objects into the data model
- Templates authored from untrusted input without a restricted `TemplateClassResolver` (e.g. `SAFER_RESOLVER`) — call it out as a hardening gap

#### Null and Missing-Value Handling
- Interpolations or directive arguments on possibly-absent values without `!` (default) or `??` (existence) — missing values raise `InvalidReferenceException` at render time
- Overuse of a bare `!` that masks genuinely-required data with a silent empty string; prefer an explicit default (`value!"fallback"`) or an `<#if value??>` guard where absence is meaningful
- `!` precedence mistakes in expressions (`a.b.c!` guards only the last step); confirm the intended nullable segment

#### Logic-in-Template Smells
- Business logic, data-access, or non-trivial computation embedded in templates that belongs in the controller/model layer
- Deeply nested `<#if>`/`<#list>` or duplicated conditional blocks that indicate the view is doing the model's job
- `<#assign>` used to build state that should have been prepared before rendering

#### Macro and Include Hygiene
- `<#include>` where `<#import>` (namespaced) is intended, causing global-namespace pollution or accidental variable shadowing
- Macros/functions defined but never called, or duplicated across templates instead of shared via a common library template
- Relative template names passed to `<#include>`/`.get_optional_template` without `?absolute_template_name` when resolution context is ambiguous
- Missing-template failures not handled (`.get_optional_template(...).exists`) where the include is optional

#### Internationalization and Locale-Sensitive Formatting
- Numbers, dates, times, and currency emitted with locale-default formatting where a fixed machine format is required (e.g. `?string`/`?c` for numbers in URLs, JSON, or IDs) — `?c` (computer format) prevents locale-dependent thousands separators corrupting non-display output
- Hard-coded user-facing strings that should come from a localized message/resource bundle
- Date/number output relying on an implicit locale/timezone without confirming the render environment sets them intentionally
1 change: 1 addition & 0 deletions internal/config/rules/system_rules.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
".github/**/*.{yaml,yml}": "github_config.md",
"**/*.{yaml,yml}": "yaml.md",
"**/*.java": "java.md",
"**/*.{ftl,ftlh,ftlx}": "freemarker.md",
"**/*.ets": "arkts.md",
"**/*.astro": "astro.md",
"**/*.{ts,js,tsx,jsx}": "ts_js_tsx_jsx.md",
Expand Down
4 changes: 4 additions & 0 deletions internal/config/rules/system_rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ func TestResolve_DefaultRules(t *testing.T) {
}{
{"src/main/java/com/example/foo.java", "Logic Error Detection"},
{"foo.java", "Logic Error Detection"},
{"src/main/resources/templates/email.ftl", "Template Injection"},
{"foo.ftl", "Template Injection"},
{"foo.ftlh", "Template Injection"},
{"foo.ftlx", "Template Injection"},
{"src/main/resources/mapper/usermapper.xml", "SQL Logic Error Detection"},
{"src/main/resources/dao/userdao.xml", "SQL Logic Error Detection"},
{"pom.xml", "snapshot"},
Expand Down
1 change: 1 addition & 0 deletions pages/src/content/docs/en/review-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ The embedded `system_rules.json` ships with these patterns (in order):
| `.github/**/*.{yaml,yml}` | `github_config.md` — other `.github` config YAML. |
| `**/*.{yaml,yml}` | `yaml.md` |
| `**/*.java` | `java.md` |
| `**/*.{ftl,ftlh,ftlx}` | `freemarker.md` — FreeMarker templates (SSTI / XSS / null handling). |
| `**/*.ets` | `arkts.md` — ArkTS / HarmonyOS. |
| `**/*.{ts,js,tsx,jsx}` | `ts_js_tsx_jsx.md` |
| `**/*.{kt}` | `kotlin.md` |
Expand Down
1 change: 1 addition & 0 deletions pages/src/content/docs/ja/review-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ OCR は [`bmatcuk/doublestar/v4`](https://pkg.go.dev/github.com/bmatcuk/doublest
| `.github/**/*.{yaml,yml}` | `github_config.md`: その他の `.github` 設定 YAML。 |
| `**/*.{yaml,yml}` | `yaml.md` |
| `**/*.java` | `java.md` |
| `**/*.{ftl,ftlh,ftlx}` | `freemarker.md`: FreeMarker テンプレート(SSTI / XSS / null 処理)。 |
| `**/*.ets` | `arkts.md`: ArkTS / HarmonyOS。 |
| `**/*.{ts,js,tsx,jsx}` | `ts_js_tsx_jsx.md` |
| `**/*.{kt}` | `kotlin.md` |
Expand Down
1 change: 1 addition & 0 deletions pages/src/content/docs/zh/review-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ OCR 用 [`bmatcuk/doublestar/v4`](https://pkg.go.dev/github.com/bmatcuk/doublest
| `.github/**/*.{yaml,yml}` | `github_config.md`——其他 `.github` 配置 YAML。 |
| `**/*.{yaml,yml}` | `yaml.md` |
| `**/*.java` | `java.md` |
| `**/*.{ftl,ftlh,ftlx}` | `freemarker.md`——FreeMarker 模板(SSTI / XSS / null 处理)。 |
| `**/*.ets` | `arkts.md`——ArkTS / HarmonyOS。 |
| `**/*.{ts,js,tsx,jsx}` | `ts_js_tsx_jsx.md` |
| `**/*.{kt}` | `kotlin.md` |
Expand Down