Go Application Security: Top 10 Vulnerabilities and Protection Methods
The Go language (Golang) has gained popularity due to its high performance, simplicity, and built-in security mechanisms. However, like any other language, it does not protect the developer from all possible threats. Design errors, carelessness when working with external data, and incorrect use of standard libraries can lead to serious vulnerabilities. In this article, we will analyze the top 10 most critical vulnerabilities of Go applications, provide code examples, and explain how to avoid them.
1. SQL Injection
Despite the presence of the database/sql package, developers often allow string concatenation when building SQL queries. This is a classic vulnerability that allows an attacker to execute arbitrary SQL code.
Unsafe Code:
// DANGEROUS: string concatenationfunc getUser(w http.ResponseWriter, r *http.Request) { username := r.URL.Query().Get("username") query := "SELECT * FROM users WHERE username = '" + username + "'" rows, err := db.Query(query) // ...}Safe Code with Parameterization:
func getUser(w http.ResponseWriter, r *http.Request) { username := r.URL.Query().Get("username") // Use placeholders query := "SELECT * FROM users WHERE username = $1" rows, err := db.Query(query, username) // ...}Recommendation: Always use parameterized queries. Never concatenate user input into SQL strings.
2. Cross-Site Scripting (XSS)
If your Go application renders HTML on the server (for example, using html/template), you need to escape the output. The built-in text/template package does not do this.
Unsafe Code:
// Using text/template is dangeroustmpl, _ := template.New("test").Parse("<h1>{{.Name}}</h1>")tmpl.Execute(w, map[string]string{"Name": "<script>alert('XSS')</script>"})Safe Code:
// Always use html/template for HTML templatesimport "html/template"tmpl, _ := template.New("test").Parse("<h1>{{.Name}}</h1>")tmpl.Execute(w, map[string]string{"Name": "<script>alert('XSS')</script>"})// Output: <script>alert('XSS')</script>Recommendation: For working with HTML, only use html/template. Always validate and escape user input, especially if it is output into tag attributes or JavaScript.
3. Race Condition
Go is a language with concurrency, and race condition is one of the most common problems. It can lead to data corruption, memory leaks, and unexpected crashes.
Unsafe Code:
var counter int
func increment() { for i := 0; i < 1000; i++ { counter++ // Non-atomic operation }}
func main() { go increment() go increment()}Safe Code with Mutex:
var ( counter int mu sync.Mutex)
func increment() { for i := 0; i < 1000; i++ { mu.Lock() counter++ mu.Unlock() }}
func main() { go increment() go increment()}Recommendation: Use sync.Mutex, sync.RWMutex, or atomic operations (sync/atomic). Run tests with the -race flag to detect races.
4. Path Traversal
The vulnerability occurs when an application uses user input to form a file path without proper validation.
Unsafe Code:
func serveFile(w http.ResponseWriter, r *http.Request) { f