Sensitive information in source code - Go

Sensitive information in source code - Go

Need

Protection of sensitive information in source code

Context

  • Usage of Go 1.16 for developing high-performance and efficient applications
  • Usage of Gin framework for building web applications in Go

Description

Non compliant code

        package main

import (
	"github.com/gin-gonic/gin"
)

type User struct {
	Username string `json:"username"`
	Password string `json:"password"`
	Email    string `json:"email"`
}

var users = []User{
	{"admin", "123", "admin@example.com"},
	{"test", "test", "test@example.com"},
}

func main() {
	r := gin.Default()

	r.GET("/users", func(c *gin.Context) {
		c.JSON(200, users)
	})

	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
        
        

The above Go code using the Gin framework is a simple server that handles a GET request to "/users" and responds with a JSON array of users. Each user is represented by a struct that contains a username, password, and email. The users are stored in an array in the source code, with the passwords and emails in plaintext.

This is a security vulnerability because sensitive information such as passwords and emails should not be stored in plaintext, especially in the source code. Anyone with access to the source code would have access to this sensitive information, and if the source code is ever exposed (for example, through a repository), that sensitive information would be exposed as well.

Furthermore, the server is exposing this sensitive information to anyone who sends a GET request to "/users". This is another security vulnerability, as this sensitive information should not be exposed to clients. Clients should only receive the minimum amount of information necessary for them to function, and passwords and emails are typically not necessary.

The best practice is to store sensitive information in a secure and encrypted form, such as through hashing passwords and not storing emails in the source code. Sensitive information should also not be exposed to clients unless absolutely necessary.

Steps

  • Remove sensitive information from the source code
  • Store sensitive information in a secure and encrypted manner
  • Use environment variables or configuration files to store sensitive information
  • Implement a secure secrets management solution
  • Ensure that sensitive information is not logged or printed in error messages
  • Regularly review and audit the source code repository for any accidental inclusion of sensitive information

Compliant code

        package main

import (
	"github.com/gin-gonic/gin"
	"os"
)

type User struct {
	Username string `json:"username"`
	Password string `json:"password"`
	Email    string `json:"email"`
}

var users = []User{
	{os.Getenv("ADMIN_USERNAME"), os.Getenv("ADMIN_PASSWORD"), os.Getenv("ADMIN_EMAIL")},
	{os.Getenv("TEST_USERNAME"), os.Getenv("TEST_PASSWORD"), os.Getenv("TEST_EMAIL")},
}

func main() {
	r := gin.Default()

	r.GET("/users", func(c *gin.Context) {
		c.JSON(200, users)
	})

	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
        
        

The original code had sensitive information such as usernames, passwords, and email addresses hardcoded into the source code. This is a security vulnerability as it exposes sensitive information to anyone who has access to the source code.

The fixed code removes these hardcoded values and instead retrieves them from environment variables using the os.Getenv function. This is a more secure practice as it allows sensitive information to be stored outside of the source code in a secure and encrypted manner.

In a production environment, these environment variables would be set through a secure secrets management solution, ensuring that sensitive information is not exposed.

It's important to note that sensitive information should never be logged or printed in error messages, and the source code repository should be regularly reviewed and audited for any accidental inclusion of sensitive information.

Remember to set the environment variables in your production environment before running the application.

References