Content security policy explained using Flask

RohanRohan
2 min read

If you want to improve the security of your website, you can use a content security policy to help detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. Basically, a content security policy tells the browser which origins it is allowed to load data from. CSP can be enabled by setting the Content-Security-Policy HTTP response header.

Let's look into this further using a simple Flask app.

Simple Flask app

We will use a Flask extension called Talisman. Here is our main code file:

app.py

from flask import Flask, redirect, render_template, request, url_for
from flask_talisman import Talisman

app = Flask(__name__)
csp = {
    'default-src': '\'self\''
}
talisman = Talisman(app, content_security_policy=csp)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

@app.route("/youtube")
def youtube():
    return render_template("youtube.html")

Notice the content security policy:

csp = {
    'default-src': '\'self\''
}

This will force all content to come from the same origin as the application. Note that the default-src policy directive is a fallback for other resource types when they don't have policies of their own (for more info on that click here).

Next, let's create the template we need for the /youtube route and embed a youtube video in it:

templates/youtube.html

<iframe 
    width="560" 
    height="315"
    src="https://www.youtube.com/embed/eoTpdTU8nTA" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    allowfullscreen>
</iframe>

Now, let's run the application using flask run --debug and navigate to /youtube :

The embedded video is not shown by the browser. If you open dev tools, you will see the error below:

On the network tab, take a look at the response headers and notice the Content-Security-Policy header:

To fix this, we will change our CSP in app.py to allow content from Youtube:

csp = {
    'default-src': ['\'self\'', 'https://www.youtube.com']
}

Now, run the app again, and navigate to /youtube and you can see that the video renders successfully as below:

If you see the response headers for this request on the network tab, you will see that the Content-Security-Policy header has changed as well:

Summary

We took a look at the basics of content security policies and for demonstration, we wrote a simple application using Python Flask.

Thanks for reading and I hope you found this article useful.

0
Subscribe to my newsletter

Read articles from Rohan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rohan
Rohan

Software engineer and blogger