Insecure or unset HTTP headers - Content-Security-Policy - Go

Insecure or unset HTTP headers - Content-Security-Policy - Go

Need

Implementation of secure and properly configured Content-Security-Policy headers

Context

  • Usage of Go 1.16 for building efficient 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()
}
        
        

The above code is a simple server application written in Go using the Gin framework. When the server receives a GET request at the root ("/") URL, it responds with a "Hello, World!" message.

The vulnerability lies in the fact that no HTTP headers are set in the response, specifically the Content-Security-Policy header is missing. This header is an important security feature that helps to prevent a variety of attacks, including Cross-site Scripting (XSS) and data injection attacks.

Not having this header means that the browser will allow any content to be loaded, leaving the application vulnerable to potential attacks. Even if the header is present but not configured correctly, it can still lead to vulnerabilities. For example, if the policies defined in the header contain insecure values, attackers could exploit these weaknesses to carry out attacks.

In this case, the server should be configured to include a properly set Content-Security-Policy header in its responses to enhance the security of the application.

Steps

  • Add the Content-Security-Policy header to the server responses.
  • Define the mandatory security policies in the Content-Security-Policy header.
  • Ensure that the defined security policies contain secure values.
  • Test the application to verify that the Content-Security-Policy header is properly configured and enforced.

Compliant code

        package main

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

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

    r.Use(func(c *gin.Context) {
        c.Header("Content-Security-Policy", "default-src 'self'")
        c.Next()
    })

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

The above code fixes the vulnerability by adding a middleware function that sets the Content-Security-Policy header for all server responses.

The Content-Security-Policy header is set to default-src 'self', which means that by default, only resources from the same origin as the application can be loaded. This is a secure value that helps to prevent Cross-Site Scripting (XSS) attacks and other code injection attacks.

The middleware function is added using the Use function of the gin router ( r). This function takes a handler function as an argument, which is called for every request that the router handles. The handler function sets the Content-Security-Policy header and then calls c.Next() to pass control to the next handler in the chain.

After the middleware function, the GET route for the root path ("/") is defined as before. The difference is that now, the response for this route (and all other routes of the application) will include the Content-Security-Policy header.

Finally, the application is started with r.Run().

This fix ensures that the Content-Security-Policy header is included in all server responses and that it has a secure value. This helps to protect the application against certain types of web attacks.

References