Start learning free

LESSON 2 OF 20 · SECURITY: COMMON ATTACKS

Content-Security-Policy in Python

Practice

The product page shows reviews, and every review goes through html.escape, so a <script> tag typed into a review shows up as harmless text. But escaping only swaps a few characters: <, >, & and quotes. A photo link like javascript:alert(document.cookie) has none of them, so it lands in the page as a working link.

The attack: a visitor clicks "photo" on that review, and the browser runs the attacker's code inside the shop's page. What the attacker gets: their own JavaScript running on the shop's page, as the visitor.

A Content-Security-Policy header is a second wall. It tells the browser where the page may load things from, and the browser obeys it even when bad code slipped into the page. The policy is one text of rules separated by ;. default-src 'self' allows content only from the shop's own address, and script-src 'self' allows only script files from the shop. Inline script, a <script> written into the page or a javascript: link, is refused.

Each app picks its own rules, and the single quotes around 'self' are part of them. This policy, from another app, also allows images from one photo site:

POLICY = "default-src 'self'; img-src 'self' https://photos.example.com"

The page still holds the bad link (cleaning stored links is another job), but every answer now carries the policy, so the browser won't run it:

POST /products/1/reviews  {"text": "Great mug, keeps tea hot!", "link": "https://photos.example.com/mug.jpg"}
  →  201  {"id": 1, "link": "https://photos.example.com/mug.jpg", "text": "Great mug, keeps tea hot!"}
POST /products/1/reviews  {"text": "See my photo", "link": "javascript:alert(document.cookie)"}
  →  201  {"id": 2, "link": "javascript:alert(document.cookie)", "text": "See my photo"}
GET /products/1   →  200  <h1>Mug</h1><p>Great mug, keeps tea hot! <a href='https://photos.example.com/mug.jpg'>photo</a></p><p>See my photo <a href='javascript:alert(document.cookie)'>photo</a></p>
GET /products/6   →  200  <h1>Teapot</h1>
GET /products/99  →  404  Product not found

Every GET answer carries:
Content-Security-Policy: default-src 'self'; script-src 'self'

Your task: add a constant CSP set to "default-src 'self'; script-src 'self'", and a function add_csp(response) with the decorator @app.after_request that sets the Content-Security-Policy header to CSP and returns the response.


Assignment
Follow the Coding Tutorial to send the Content-Security-Policy header with every answer the shop gives.


Hint
Write the policy in double quotes, so the single quotes around 'self' fit inside. Like every after_request function, add_csp must return response.


STEP 1 OF 5
    Ctrl + Enter to check

    Secx Csp in Python

    Keep going with Python1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free