Sensitive information in source code - API Key - Go

Sensitive information in source code - API Key - Go

Need

Secure storage and retrieval of sensitive information such as API keys

Context

  • Usage of Go 1.16 for developing scalable and efficient applications
  • Usage of Gin for building web applications in Go

Description

Non compliant code

        package main

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

const APIKey = "1234567890abcdef"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
			"apiKey":  APIKey,
		})
	})
	r.Run() 
}
        
        

In the above code, an API key is hard-coded as a constant at the beginning of the file. This API key is used in the /ping endpoint to authenticate the request. This is a security vulnerability because anyone who has access to this source code will be able to see the API key in plain text.

This is a common mistake made by developers. API keys should never be stored in the source code or anywhere that is accessible in plain text. They should be stored in a secure place where they can't be accessed by unauthorized users.

If an attacker gains access to this API key, they could use it to make requests to the API, potentially gaining access to sensitive information or performing malicious actions.

The best practice is to store sensitive information like API keys in environment variables or in a secure key vault. This way, the keys are not exposed in the source code and can be managed securely.

Steps

  • Remove the API key from the source code.
  • Store the API key in a secure location, such as a configuration file or environment variable.
  • Update the code to retrieve the API key from the secure location.
  • Ensure that the secure location is properly protected and accessible only to authorized users.
  • Consider using a secrets management solution to securely store and manage API keys.

Compliant code

        package main

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

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
			"apiKey":  os.Getenv("API_KEY"),
		})
	})
	r.Run() 
}
        
        

The original code had a vulnerability where the API key was stored directly in the source code. This is a security risk as it exposes sensitive information that could be exploited by malicious users.

The updated code fixes this vulnerability by removing the API key from the source code and instead retrieving it from an environment variable. This is a more secure method of storing sensitive information as environment variables are not typically included in version control and can be protected from unauthorized access.

To use this updated code, you would need to set the API_KEY environment variable in your server's environment. This can typically be done in the command line with the following command:

                export API_KEY=your_api_key

            


Replace your_api_key with your actual API key. This command sets the API_KEY environment variable to your API key.

Please note that this is a basic solution and for more secure applications, you should consider using a secrets management solution. These solutions provide more robust methods of storing, accessing, and managing sensitive information.

References