Security of Go Applications: Top 10 Vulnerabilities and How to Avoid Them

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

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: &lt;script&gt;alert('XSS')&lt;/script&gt;


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                

Blogs

Book Recommendations