Skip to main content
BlogSecurityCutting Latency, Not Security

Cutting Latency, Not Security

An illustration that shows a stop watch and a shield with a check mark with the text "Cutting Latency, Not Security"

Content Security Policy (CSP) is a security feature implemented in web browsers to protect websites and web applications from various types of attacks—such as cross-site scripting (XSS) and data injection attacks. CSP controls and limits the sources of different types of content that you might load or execute on a web page. Those types of content include:

  • Scripts
  • Stylesheets
  • Images

In this post, we’ll first take a look at how CSP works. We’ll see that a more effective and dynamic use of CSP includes some computation that needs to happen at the server. However, it’s possible to move that computation to the edge, reducing latency and ensuring an optimal end-user experience. We’ll also explore how this edge computing solution might work.

Are you ready to dive in? Let’s start by understanding how CSP works.

How CSP works

A CSP is typically defined server-side by adding a Content-Security-Policy header to your HTTP response. This is sent by the web server to a user requesting a web page. This header specifies the rules that the browser should follow when loading and executing content on the page.

Examples of setting the Content-Security-Policy header

Let’s say you were working with Express in Node.js. You would set your CSP header this way:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.set('Content-Security-Policy', 'directive1 value1; directive2 value2; ...');
  res.status(200).send('hello world');
});

If you were using Python with Flask, then the code would look like this:

app = Flask(__name__)

@app.route('/hello', methods=['GET'])
def hello_world():
    response = make_response('hello world')
    response.headers['Content-Security-Policy'] = 'directive1 value1; directive2 value2; ...'
    return response

Working with directives

Each CSP header can have multiple directives, and each directive can have values that are appropriate for the type of setting provided. These directives define the security rules for various types of resources. For example, the script-src directive specifies the allowed sources for stylesheets.

Consider the following CSP header:

Content-Security-Policy: default-src 'self'; script-src 'self' https://static.example.com; style-src 'self' 'unsafe-inline';

In the above header, we see three directives, each with accompanying values.

  • The default-src directive, set to 'self', specifies that by default, all content should be loaded from the same origin as the page itself.
  • The script-src directive allows scripts to be loaded from the same origin ('self') and the specified external source (https://static.example.com).
  • The style-src directive allows stylesheets to be loaded from the same origin and also allows inline styles.

The list of available directives is actually quite exhaustive. It can be found here. Directives include:

  • font-src: Sources for fonts loaded using @font-face
  • frame-src: Sources for nested browsing contexts loaded into elements such as <frame> and <iframe>
  • img-src: Sources of images and favicons

Tying the CSP into the HTML

Once the CSP header is set on the server, the browser enforces these rules when loading resources on the web page.

In the HTML source, developers can add elements (such as scripts or stylesheets) inline, or by referencing resources (from the same origin or elsewhere). The browser will then check the CSP header to ensure that these resources comply with the defined rules. If a resource is not allowed by the CSP, the browser will block its inclusion and execution.

Unique on every request

Because of how CSP headers are defined, they are typically consistent across all requests for a particular web page. The details and directives for each request of a single page will be the same with each subsequent request of that page.

That brings up an interesting question: How would we deal with dynamic, inline scripts and styles? We may want to allow the execution of specific inline scripts and styles without opening the door for including all inline scripts and styles.

For this scenario, it’s possible to introduce nonce values or hashes to ensure that even if the source of a script or style is not explicitly listed in the CSP, it can still be executed—as long as it matches the nonce or hash value specified by the CSP header.

These nonce values or hashes can change on each request, thereby making them unique. So, they would need to be generated and managed on a server. However, just because these nonces or hashes need to be executed on a server, they don’t necessarily need to be executed on the main server for your site. And this is where edge computing comes in.

What is edge computing?

Edge computing is essentially the concept that some computation can be set up to run at the outer edge of your network—geographically close to your end users. Basically, it’s a type of distributed computing that makes it possible to get closer to real-time computation speeds, even over the internet, while also reducing network latency.

With edge computing, you could move the concerns around, generating nonces and hashes for your CSP headers closer to your end users, reducing the time they need to wait for you to secure your site.

How edge computing can help with CSP

One of the key reasons why CSP can slow down your site is that the nonces in the headers can cause cache misses, requiring your customer’s browser to go all the way to the server for your site to get the freshest headers generated properly. To address this, you can implement a dynamic CSP nonce generator in an edge instance. This will provide a way to ensure your caching is still useful while also maintaining security.

The benefits of this approach include:

  • Reduced latency: The edge compute instance generates and inserts the nonce into the request. The requests, now with nonce inserted, continue to traverse to the cache, thus preventing the need to hit the origin server to fetch new responses every time a request is made.
  • Distributed security: Using edge computation means that you have an extra layer of security before customers ever need to interact with the primary servers and application code of your system. Even if you have an application vulnerability, your edge computation that calculates the CSP nonce provides an added layer of security, helping you to mitigate potential problems.
  • Ease of maintenance: If you manage the dynamic nonce for the CSP header at the edge with a serverless approach, this will simplify your maintenance tasks. In particular, you can manage CSP policies without modifying application code. You can also typically manage these sorts of changes from a central control system without needing to do any special code deploys. These edge computation functions can also be used by multiple independent applications, thus separating concerns from specific teams that work on each application and allowing security professionals to make sure the correct nonce generation is happening.

Conclusion

Are you interested in learning more about using edge computing? If so, check out some of Akamai’s featured products. In particular, EdgeWorkers create a serverless experience that can do exactly what we’ve been discussing in this article—without the complexity of figuring out how to deploy servers to the edge of your networks yourself.

When you’re ready to try it out for yourself, sign up for a free trial today! It’s time to work on securing your site with better CSP headers that don’t blow your caching scheme!

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *