Golang Content Security
Policy Guide: What It Is and
How to Enable It

stackhawk

StackHawk|September 10, 2021

Learn what content security policy (CSP) is in Golang, how to enable it, how to fix errors, what errors will show, and how to enable CSP.

Learning that so-and-so big tech company has been hacked isn't surprising news anymore. Hackers are now capable of setting companies back millions of dollars—a trend that makes it beneficial to adopt a security-first development approach. If you're using Go at any level of your software delivery process, such an approach includes looking into Golang content security policy (CSP) headers. And you should look at how they can help your security goals in particular. 

This guide explains the implementation of a Golang content security policy at length. Our approach starts with a specific definition of CSP. This is followed by some reasoning to justify why you should implement a content security policy. Finally, we'll discuss best-practice methods to enforce CSP in Golang applications. 

Let's dive right in!

What Is a Content Security Policy?

A content security policy is a set of rules that guard web applications against innocently executing unscrupulous scripts otherwise pushing hackers' agendas. The core functions of a content security policy distill into the following three-point list: 

  1. Identity-matching scripts within the app such that only those known by the server ever get to run

  2. Cross-checking resource tags before they render/fire such that only those from trusted sources appear on the front end

  3. Cleaning/sanitizing communication with external resources (for example, turning HTTP to HTTPS defaults) to avoid Golang CSRF

These three functionality aspects make CSP a useful XSS and code (tag manipulation) injection deterrent. 

To learn more about content security policies, check out this post that describes the subject in more detail.

Golang Content Security Policy Format

Good as all this seems, it's worth mentioning that CSP should not be the primary security feature for your Golang applications. Mostly because it best works as a blanket solution to a static set of access permutations. If your Golang project is just a single page of static content, implementing a content security policy can prove futile. This, due to it being a lesser target than projects handling user data. However, dynamic projects would benefit from CSP. 

By no means will CSP be the most comprehensive security strategy for your Golang project. Make sure you explore the headers in your project along with their associated risks. This way, you can follow up with more elaborate security solutions to reinforce the effects of even the most well-thought-out content security policy. The more deliberate and focused a solution, the better your application security overall. 

Let's refer to the uncomplicated Golang content security policy implementation below to explain the structure of CSP.

Golang Content Security Policy Guide: What It Is and How to Enable It - Picture 1 image

Typical Golang CSP implementation.

This content security policy specifies just four values, but it's not rare for double the amount (or even more) to feature therein. Now for a breakdown of what the code in the screenshot means. 

object-src

The object-src value is a protection variable that specifies any scripts embedded in the Golang application that should be executed. The 'none' option specified in this case negates the possibility of running applets or flash elements wherever this policy is included/called. Often you'll encounter the 'self' keyword as the object source directive. It simply instructs that scripts emerging from the host domain itself can be executed as they're deemed safe by origin. 

script-src

When the script-src value is specified in CSP, any scripts that mirror the {{nonce}} will execute. This works in much the same way as encryption in that the matching key is stored on the server side, away from hackers' reconnaissance efforts. You'll do well to notice that passing a second directive is possible with the script source variable. In this case, the 'strict-dynamic' option accepts execution of scripts if, and only if, they were added to a page by already-approved sources. This caters to any dynamic resource builds. 

base-uri

The base-uri value works in a similar fashion to the object source variable in that it specifies if any base tag values can run. The 'self' option therein limits any chance of manipulation of the URLs in base tags. It's worth specifying this tag even when your code consists of no base values, lest hackers inject them post-production. 

reporting-uri

The reporting-uri value directs the interpreter to post any reports/errors to a specified webpage for analysis. This reporting feature notes down any hacker attempts to assist with any audit and safe-fencing efforts thereafter. 

CSP Errors

Typically, any values for which directives exist in the Golang content security policy should fire off errors when access attempts fail. All of which should reflect at the address set in the reporting-uri variable. As an example, let's take a look at some errors/blocks that result in errors. Facebook is one company using Golang, among a handful of other big names. 

Golang Content Security Policy Guide: What It Is and How to Enable It  image

CSP errors and their sources.

Key to note from this screenshot is how the platform has actively placed an information resource explaining some of the errors. In particular, it shows those from attempted Self-XSS attacks. This helps with a sneaky kind of attack that blends social engineering with cross-site scripting for persistent access to user accounts. 

Some of the errors detected by the browser happen on the client side. If you encounter these during your Golang testing stages, consider doing away with any deprecated value-directive pairs in your CSP declaration. This browser compatibility chart maintained by the Mozilla Foundation should help troubleshoot most CSP errors. 

Typically, resolving an error requires a specific element value-directive declaration that either excludes the self or sanitizes the particular access instance. However, you should be careful not to open the rest of your web application to attacks for the sake of a single tag. Otherwise, to mitigate risk, you may as well apply a single value-directive case for each error-flagging tag like this: 

<tag nonce="3hDsif/="> ... </tag>

This would be a tedious procedure. Especially if your application looks to scale significantly in the long run. Clearly, there must be a better way to implement CSP.

How to Enable CSP

No two Golang projects will come out identical, even (especially) when you patch together various Git repositories to come up with one. As such, it's tempting to create a Golang content security policy from scratch. Without taking anything away from your team and their competence, you may realize that's probably the least effective route. 

The Golang package library is awash with stable all-encompassing templates and even header generators that fit snugly with your project. More important than understanding the code is how you approach the implementation and maintenance thereof. 

Best practice alert: Like you would with any module in your project, ensure you test your Golang content security policy across the possible access device matrix. Make sure your policy evolves with the project to cover any resource tag introductions. 

Find and Fix Security Vulnerabilities

In Conclusion

By the time you read this sentence, you'll have acquired ample knowledge around the Golang content security policy subject to implement your very first headers. This should provide the first line of defense against injection-dependent attacks, at the same time patching basic cross-site scripting vulnerabilities. 

That said, in the event of a rapidly scaling application, your headers will need equally attentive efforts. The cat-and-mouse game that can ensue as you update new headers and fitting values is likely to cause a lot of developer exhaustion. This is where automated security testing tools that seamlessly merge with CI/CD workflows come in handy. StackHawk is a perfect case in point. 

Since missing headers don't necessarily mean your code has bugs, associated vulnerabilities easily make it into production. StackHawk lets your developers focus on feature development by automating security vulnerability checks. 

This post was written by Taurai Mutimutema. Taurai is a systems analyst with a knack for writing, which was probably sparked by the need to document technical processes during code and implementation sessions. He enjoys learning new technology and talks about tech even more than he writes.


StackHawk  |  September 10, 2021