An Attack Prevented by CSP
The same-origin policy doesn't prevent XSS attacks very well. Instead, we need to use Content Security Policy. Here is an example.

The Attack
We have a website that allows users to comment on posts. One of the new features is allowing users to write comments in Markdown.
Markdown allows any HTML tag. Therefore a user can use HTML in the comments.
The script tag is valid HTML; therefore, it’s allowed.
A simple attack is to create comments advertising a website:
<script>
const newComment = { content: “Visit my website: FancyUser99.com” };
// The attacker can learn how to create posts
// by checking the network tab when a post is created
fetch( “/comments”, {method: “POST”, body: JSON.stringify(newComment) });
</script>
When a user visits the website with the comment, the script tag is executed, and the actions are performed without the user’s consent.
Cross-Site Scripting (XSS)
“XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users” Wikipedia
The previous scenario is an example of an XSS attack. When the attacker created the comment, it added a script embedded in it. The script is then executed when users visit the website, and the comment is rendered.
First Line of Defense: Same-origin Policy
The same-origin policy doesn’t prevent this kind of attack. The script is executed within the same website. Therefore, the server has no way of knowing that the action to create the comment comes from the attacker's script.
Content Security Policy (CSP)
“Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks” MDN
CSP is a way to tell the browser what it can trust and what it cannot trust. For example, we can tell the browser which JS files or inline scripts can execute, and it will block the rest.
Defensive Player of the Year: CSP
CSP can be set as a header or as a meta tag.
<meta http-equiv="Content-Security-Policy" content="script-src ‘self’">
The previous tag tells the browser to allow only JS files from the same origin. By default, CSP disables all inline scripting.
‘script-src ‘self’’ prevents XSS attacks.
Yet, our website might use inline scripts for different purposes; we can’t just disable it. Instead, we can tell the browser which inline scripts can execute.
<meta http-equiv="Content-Security-Policy" content="script-src ‘self’ ‘nonce-someRandomNumber’">
<script nonce=”someRandomNumber”>
// our inline script
</script>
Using nonce is one of the ways to allow inline scripting safely, but there are others. For more details, I recommend the CSP MDN page.
Attack Prevented
With CSP in place, we can safely render Markdown, and all the injected scripts are safely ignored. With just one line of code, we made our website safer.
<meta http-equiv="Content-Security-Policy" content="script-src ‘self’">
CSP prevents XSS attacks.
If you like this post, consider sharing it with your friends on twitter or forwarding this email to them 🙈
Don't hesitate to reach out to me if you have any questions or see an error. I highly appreciate it.
And thanks to Michal and Miquel for reviewing this article 🙏