Server Side Template Injection in Fiber (Go)
Server Side Template Injection in Fiber with Go — how this specific combination creates or exposes the vulnerability
Server Side Template Injection (SSTI) occurs when user-controlled data is reflected into a template and interpreted as code. In Go, the standard html/template package is designed to auto-escape and prevent execution, but developers can inadvertently disable these protections. Using the ParseFiles or ParseGlob methods with user-influenced template names or paths can lead to arbitrary template execution when unsafe options are used or when templates are re-used across different contexts.
In Fiber, routes often render templates directly with data from request parameters (e.g., query strings or body fields). If a route passes unsanitized input into template parsing or variable injection, attackers can craft payloads that execute arbitrary Go template code. For example, including user input in a template name or leveraging template actions like {{define}}, {{template}}, or function maps with unsafe reflection can expose the application. Because Go templates allow function calls and type constructors, an attacker may chain methods to achieve remote code execution (RCE) or sensitive data exposure when the runtime reflection is accessible to the template engine.
Consider a Fiber handler that renders a user-provided template file without validation:
// Unsafe: user input directly influences template selection
app.Get("/render", func(c *fiber.Ctx) error {
tmplName := c.Query("name", "home")
tmpl, err := template.ParseFiles(tmplName + ".html")
if err != nil {
return c.SendStatus(fiber.StatusBadRequest)
}
return tmpl.Execute(c.Body(), nil)
})
An attacker can set name to a path like ../../../etc/passwd or to a crafted template that includes malicious actions. Even if the template file exists, the reflected template code can invoke functions that read files or interact with the runtime if the function map is permissive. The risk is amplified when developers use custom function maps that expose unsafe operations or when templates are dynamically composed based on user input.
Because SSTI in Go often requires precise knowledge of the runtime and template internals, the impact can include unauthorized file reads, information disclosure, or, in rare configurations with reflection enabled, arbitrary code execution. This specific stack—Fiber routing, Go’s html/template package, and developer patterns that relax escaping or allow dynamic template selection—creates a path for attackers to inject and execute template logic that should remain confined to the intended rendering layer.
Go-Specific Remediation in Fiber — concrete code fixes
Remediation focuses on strict input validation, avoiding dynamic template selection, and ensuring auto-escaping remains enabled. Always treat template names and paths as untrusted and do not concatenate them with user input. Prefer a fixed set of templates and use explicit mapping rather than file-system discovery.
Use template.New with defined templates and avoid ParseFiles or ParseGlob with untrusted input. If dynamic content is needed, pass data variables safely and never allow template names or paths from the client.
Secure Fiber handler example:
// Safe: templates are preloaded and selected by a fixed mapping var templates = template.Must(template.New("").ParseGlob("templates/*.html")) app.Get("/render", func(c *fiber.Ctx) error { name := c.Query("page", "home") // Whitelist allowed templates allowed := map[string]bool{"home": true, "about": true, "status": true} if !allowed[name] { return c.Status(fiber.StatusBadRequest).SendString("invalid template") } tmpl := templates.Lookup(name + ".html") if tmpl == nil { return c.Status(fiber.StatusInternalServerError).SendString("template not found") } data := struct { Title string }{Title: "Dashboard"} return tmpl.Execute(c.Body(), data) })Additionally, ensure that any custom function maps do not expose filesystem or reflection operations that could amplify an injection. Keep
html/template(nottext/template) to benefit from automatic HTML escaping, and validate all inputs before they reach template construction. For API-driven workflows, consider using JSON responses with strict serialization rather than server-side templates to reduce the attack surface.By combining these practices—fixed template sets, strict whitelisting, and avoiding runtime template assembly—you eliminate the injection vector while retaining Go’s performance and safety guarantees in a Fiber service.