HIGH server side template injectiongorilla muxmongodb

Server Side Template Injection in Gorilla Mux with Mongodb

Server Side Template Injection in Gorilla Mux with Mongodb — how this specific combination creates or exposes the vulnerability

Server Side Template Injection (SSTI) occurs when an attacker can inject template expressions that are later evaluated by a server-side templating engine. In a Gorilla Mux application that uses server-side rendering with a Go HTML/template-based engine, user-controlled input can reach templates either through route parameters or query strings handled by mux.Vars and mux.Query. If those values are interpolated into templates—either directly or via a data structure passed to Execute—template actions may be triggered.

Consider a profile endpoint where the username is extracted from the request and passed to a template map. If the template uses the username in an {{.Username}} placeholder and the template engine processes that placeholder as an action, an attacker can supply input such as {{$x:=dict "a" 1}}{{$x.a}} to attempt execution of unintended logic. The risk is amplified when the application stores or retrieves additional data from Mongodb based on the same user input without strict allow-listing, because the template context may include sensitive fields returned from the database. A developer might assume that data from Mongodb is safe, but if the database contains user-defined fields (for example, a displayName or bio stored by users), those fields can also become injection vectors when rendered in templates.

Gorilla Mux does not execute templates itself; it only provides request routing and variable extraction. The vulnerability arises when developers combine mux.Vars or mux.Query values with a template engine that evaluates user-controlled data. If the application builds a struct or map from Mongodb results and passes it to the template, fields like "role" or "permissions" could be manipulated via injection if they were attacker-influenced at write time. For example, an attacker who can update their profile bio in Mongodb might store a payload such as {{/* test */}} which later executes when the profile page is rendered. Therefore, the combination of Gorilla Mux for routing, a server-side template engine for rendering, and Mongodb as a data source creates a chain where untrusted data can travel from the database through the template context and into evaluated template code.

To detect this pattern, scans check whether user-influenced data reaches templates and whether templates invoke actions like range, with, or function calls on that data. The presence of dynamic keys in maps sourced from Mongodb increases the attack surface. Developers should treat any data flowing into templates as untrusted, regardless of its source, and apply context-aware escaping and strict allow-listing of fields used in rendering.

Mongodb-Specific Remediation in Gorilla Mux — concrete code fixes

Remediation centers on preventing user-controlled data from being interpreted as template actions and ensuring Mongodb-derived fields are sanitized or excluded from the template context.

  • Use strict allow-listing for template execution: only pass the minimal set of fields required for rendering. Do not blindly pass entire Mongodb documents.
  • Apply context-aware escaping in templates. For HTML, use the html template action; for URLs, use the url query escaping; for JavaScript, use appropriate JS string escaping.
  • Validate and sanitize data at the point of entry and before storage in Mongodb, and apply the same discipline when reading data for templates.

Example vulnerable code

import (
    "html/template"
    "net/http"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/bson"
    "github.com/gorilla/mux"
)

func profileHandler(client *mongo.Client) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
        username := vars["username"]
        coll := client.Database("app").Collection("profiles")
        var doc bson.M
        if err := coll.FindOne(r.Context(), bson.M{"username": username}).Decode(&doc); err != nil {
            http.Error(w, "not found", http.StatusNotFound)
            return
        }
        t := template.Must(template.New("profile").Parse(`
            <h1>{{.Username}}</h1>
            <div>Bio: {{.Bio}}</div>
            <div>Role: {{.Role}}</div>
        `))
        // Risk: doc may contain user-controlled fields that execute as template actions
        t.Execute(w, doc)
    }
}

Secure remediation example

import (
    "html/template"
    "net/http"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/bson"
    "github.com/gorilla/mux"
)

// SafeProfile defines an allow-listed shape for rendering
type SafeProfile struct {
    Username string
    Bio      template.HTML // escaped explicitly if needed; use template.URL for trusted URLs
}

func safeProfileHandler(client *mongo.Client) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
        username := vars["username"]
        coll := client.Database("app").Collection("profiles")
        var raw bson.M
        if err := coll.FindOne(r.Context(), bson.M{"username": username}).Decode(&raw); err != nil {
            http.Error(w, "not found", http.StatusNotFound)
            return
        }
        // Build a strict allow-listed struct from Mongodb data
        safe := SafeProfile{
            Username: template.HTMLEscapeString(raw["username"]),
            Bio:      template.HTML(template.HTMLEscapeString(raw["bio"])),
        }
        t := template.Must(template.New("profile").Parse(`
            <h1>{{.Username}}</h1>
            <div>Bio: {{.Bio}}</div>
        `))
        // Safe: only known, escaped fields are passed; no executable template actions from data
        t.Execute(w, safe)
    }
}

Additionally, avoid storing raw user input into fields that templates might later render without escaping. If you must store rich text, store it separately and apply escaping at render time. For APIs that return JSON to clients that render templates, ensure the API layer does not forward user-controlled template syntax to a server-side renderer. With middleBrick scans, verify that user-influenced data does not reach templates and that sensitive Mongodb fields are not inadvertently exposed in the render context.

Frequently Asked Questions

Can SSTI via Gorilla Mux and Mongodb disclose server-side code or environment variables?
Yes, if user-controlled input reaches server-side templates and the template engine evaluates code-like expressions (e.g., with function maps or variable assignments), an attacker may read file paths or environment variables depending on the template engine’s permissions and available functions. Always treat Mongodb fields as untrusted and apply context-aware escaping.
Does using a NoSQL database like Mongodb change the SSTI risk compared to SQL databases?
No, the database type does not change template injection risk. The risk comes from how data is passed to templates. Mongodb documents may contain user-defined fields that become injection vectors if rendered without escaping. Mitigations are the same: allow-listing, escaping, and avoiding direct inclusion of raw database fields in templates.