Insecure or unset HTTP headers - Cache Control - Go

Insecure or unset HTTP headers - Cache Control - Go

Need

Implementation of secure and appropriate Cache Control headers

Context

  • Usage of Go 1.16 for developing high-performance and scalable applications
  • Usage of gin-gonic/gin for building web applications in Go

Description

Non compliant code

        package main

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

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

	r.GET("/", func(c *gin.Context) {
		c.String(200, "Hello, World!")
	})

	r.Run() // listen and serve on 0.0.0.0:8080
}
        
        

The code above is a simple HTTP server written in Go using the Gin framework. The server has a single route ("/") that responds with "Hello, World!".

The vulnerability lies in the lack of HTTP security headers, specifically the Cache-Control header. The Cache-Control header defines how, and for how long the individual response can be cached by the browser and other intermediate caches.

Without the Cache-Control header, or if it's set with insecure values, sensitive information might be stored in caches and could be accessed by unauthorized users. This can lead to information disclosure and other security issues.

In the provided code, there is no Cache-Control header set in the server responses, which makes the application vulnerable to the mentioned risks.

Steps

  • Add the Cache-Control header to the HTTP response.
  • Set the value of the Cache-Control header to a secure value, such as 'no-store, no-cache, must-revalidate'.
  • Ensure that the Cache-Control header is set for all relevant routes and endpoints in the application.
  • Test the application to verify that the Cache-Control header is being set correctly.
  • Deploy the updated code to production.

Compliant code

        package main

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

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

	r.Use(func(c *gin.Context) {
		c.Header("Cache-Control", "no-store, no-cache, must-revalidate")
		c.Next()
	})

	r.GET("/", func(c *gin.Context) {
		c.String(200, "Hello, World!")
	})

	r.Run() // listen and serve on 0.0.0.0:8080
}
        
        

The updated code includes a middleware function that sets the Cache-Control header to a secure value ( no-store, no-cache, must-revalidate) for all HTTP responses. This function is added using the Use method of the gin router ( r), which applies the middleware to all routes and endpoints in the application.

The Cache-Control header is used to prevent sensitive information from being stored in the cache of the client's web browser. By setting this header to no-store, no-cache, must-revalidate, the application instructs the browser not to store the response in its cache, not to use a cached response to satisfy a subsequent request without successful validation on the server, and to revalidate the cache entry after every request.

This change helps to mitigate the risk of sensitive information being exposed through the browser's cache, which could potentially be accessed by an attacker.

After updating the code, it's important to test the application to verify that the Cache-Control header is being set correctly for all relevant routes and endpoints. Once this has been confirmed, the updated code can be deployed to production.

References