Cross site scripting (XSS) is identified as one of the main threats to web users by the OWASP Foundation.
XSS occurs when a malicious third party injects a script into content served by your website. Sites that serve user-supplied content to the browser without validating or escaping that content are vulnerable to XSS.
Other users could then be sent the malicious URL alongside a message saying 'Look at these cute cats' and, if they clicked on the link, the script would execute in their browser. This is an example of what is called a reflected attack, where data is read directly from the HTTP request and reflected back in the HTTP response.
Another common XSS attack method is the stored attack, where the link to the malicious script is uploaded to your site's database and served back to subsequent visitors. An example might be where a forum user includes such a link in their user profile.
Another way to help protect your site from XSS is to restrict the web domains where scripts can be served from, as is made possible by Content Security Policy (CSP) headers.
CSP headers allow the server to instruct the browser to only accept content served from specific domains, e.g. safedomain.com.
The 'Content-Security-Policy' header can restrict the source of all content served, or just specific content types, such as images, media and scripts.
Such restrictions are set using the CSP policy directives, which specify the domains to use. For example to specify that all content should be served from the site's domain you would set the CSP header like so.
Content-Security-Policy: default-src 'self'
To permit images to be served from any domain but to restrict the source of all other content to the site's domain.
Content-Security-Policy: default-src 'self'; img-src *
If you wanted to alter the restriction above to also allow media to be served from the media1.com and media2.com domains.
Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com
As you can see, each new domain is separated by whitespace and each new policy directive is separated using a semi-colon.
To broaden the permissions to allow scripts to be served from a trusted server.
Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src goodscripts.example.com
There are many different policy directives, such as style-src for specifying sources of stylesheets, font-src for sources of fonts and object-src for sources of plug-ins. A full list of directives can be found here.
To approve sub-domains as a content source you use the * symbol, for instance to approve subdomains of mysite.com.
Content-Security-Policy: default-src 'self' http://*.mysite.com
To implement a CSP without breaking your site you can test the restrictions using the Content-Security-Policy-Report-Only header. This header tells the browser not to enforce the restrictions on where to serve content from, but to report any violations to the specified URI, e.g.
Content-Security-Policy-Report-Only: default-src 'self'; report-uri: /mysite_csp_report;
All recent versions of major browsers support the use of the Content Security Policy header, except Internet Explorer. Internet Explorer 10+ supports the X-Content-Security-Policy header, which partially implements CSP. Browsers that don't support CSP won't throw up problems, they'll simply ignore it.