html/template, not text/template
The APIs are near-identical, which is the problem. text/template renders user content into a page verbatim, and the code compiles and works. Until someone submits a script tag.
html/template escapes based on context, so a value in an attribute, in a URL and in a script block are each handled correctly.
template.HTML, template.JS and template.URL bypass escaping by design. Anywhere one wraps user input is a review trigger.
Set timeouts
http.ListenAndServe with default settings has no timeouts at all. A client that opens connections and sends headers slowly holds them indefinitely, the classic Slowloris shape, and it needs very little bandwidth to exhaust a server.
ReadHeaderTimeout is the one that closes that specific hole. Set all four.
Also cap request bodies with http.MaxBytesReader, or a large upload consumes memory unchecked.
SQL
database/sql parameterises when you pass arguments:
The placeholder style depends on the driver. $1 for pq/pgx, ? for MySQL.
Ownership belongs in the query, as everywhere else:
Context and cancellation
Pass r.Context() into downstream calls. Without it, a client disconnecting leaves database queries and outbound requests running, which is both a resource leak and a way to amplify load.
Set timeouts on outbound HTTP too, http.DefaultClient has none, so a slow upstream can hold your handlers open indefinitely.
Errors
Go errors frequently contain file paths, connection strings and query fragments. Log them, don't return them.
The rest
No CSRF protection in the standard library. Use gorilla/csrf or equivalent for cookie-authenticated browser traffic. No rate limiting either; golang.org/x/time/rate or a proxy in front.
Command execution is a good default: exec.Command doesn't invoke a shell unless you ask for one.
gosec is a reasonable free static analyser and catches the SQL, command execution and weak-crypto cases. Like everything else, it won't catch a missing ownership check.