Problem
How to use Content-Security-Policy header in ASP.NET Core to prevent XSS attacks.
Solution
Create an empty project and update Startup to include service and middleware for MVC.
- public void ConfigureServices(
- IServiceCollection services)
- {
- services.AddMvc();
- }
- public void Configure(
- IApplicationBuilder app,
- IHostingEnvironment env)
- {
- app.UseDeveloperExceptionPage();
- app.Use(async (context, next) =>
- {
- context.Response.Headers.Add(
- "Content-Security-Policy",
- "script-src 'self'; " +
- "style-src 'self'; " +
- "img-src 'self'");
- await next();
- });
- app.UseStaticFiles();
- app.UseMvcWithDefaultRoute();
- }
- }
Add a _Layout page and include scripts, styles and images from local (wwwroot) and remote domains.
- <!DOCTYPE html>
- <html>
- <head>
- <meta name="viewport" content="width=device-width" />
- <title>@ViewBag.Title</title>
- <link rel="stylesheet" href="~/css/site.css" />
- <link rel="stylesheet"
- href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/css/bootstrap.min.css" />
- </head>
- <body>
- <img src="~/img/site-banner.jpg" />
- <img src="https://media-www-asp.azureedge.net/media/5245130/home-hero-2.png" />
- <div>
- @RenderBody()
- </div>
- <script src="~/js/site.js"></script>
- <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
- </body>
- </html>
Run and observe the errors. When loading the page, the browser has rejected loading from remote sources.

Discussion
Content Security Policy (CSP) is an additional level of security that could help prevent Cross-Site Scripting (XSS) attacks. In these attacks, malicious scripts are executed on user’s browser since the browser doesn’t know whether the source of the script is trustworthy or not.
CSP allows developers to specify the sources (domains) that trustworthy and can serve executable scripts. This whitelisting of domains is achieved by using Content-Security-Type HTTP header, like -
Content-Security-Policy: [policy]
Here, the [policy] is made up of directives describing the type of restrictions and domains to the whitelist. It is a string defining a series of directives and sources separated by a semicolon -
[directive] <source> <…source>; [directive] <source> <…source>; …
Sources
Sources are the trusted domains; the commonly used ones are -
- *: allow any URL.
- ‘self’: allow the origin of the served page. Note that single quotes are required.
- ‘none’: no source should be allowed. Note that single quotes are required.
- Host: allow a specified internet host (by name or IP address). A wildcard (asterisk character) can be used to include all subdomains e.g. http://*.foo.com
- ‘unsafe-line’: allow inline scripts
- ‘nonce-[base64-value]’: allow inline scripts with a specific nonce (number used once). The nonce should be encrypted and unique for every HTTP request/response.
Note
Other sources could be found at Mozilla documents for developers; see Other Resources section at the end of this post.
Directives
Directives specify the resource types to put restrictions on. Commonly used ones are,
- script-src: defines valid sources of JavaScript
- style-src: defines valid sources of stylesheets
- img-src: defines valid sources of images
- connect-src: defines valid sources to which AJAX calls can be made
- font-src: defines valid sources of fonts
- object-src: defines valid sources for <object>, <embed> and <applet> elements
- media-src: defines valid sources of audio and video
- form-action: defines valid sources that can be used as a HTML <form> action.
- default-src: specifies the default policy for loading content
Note
Other directives could be found at Mozilla documents for developers, see Other Resources section at the end of this post.
Middleware
We could encapsulate the building and adding of CSP header in a reusable middleware. Below is an example to get you started. You could extend it as necessary. First, create a class to hold sources.
- public sealed class CspOptions
- {
- public List<string> Defaults { get; set; } = new List<string>();
- public List<string> Scripts { get; set; } = new List<string>();
- public List<string> Styles { get; set; } = new List<string>();
- public List<string> Images { get; set; } = new List<string>();
- public List<string> Fonts { get; set; } = new List<string>();
- public List<string> Media { get; set; } = new List<string>();
- }
Create a builder. We’ll use it when setting up the middleware.

Jim GulikPosted May 18, 2021, 5:52 PM
Searching for over an hour to solve my problem, stumbled upon this article, solved the problem in five minutes. You are a hero!
Ketan ShindePosted Feb 6, 2020, 12:40 AM
Not helpful......
Scott HelmePosted Jan 19, 2018, 7:01 AM
Hey Tahir, great article! It might be worth mentioning CSP reporting which is a great way of monitoring your policy to make sure everything is working as expected! I built a service where sites can do this for free: https://report-uri.com
Tridip BhattacharjeePosted Jan 18, 2018, 3:01 AM
How to implement CSP in asp.net mvc 4. give some idea or link please.
Tridip BhattacharjeePosted Jan 17, 2018, 3:54 AM
Nice article....keep up the good job. thanks
Anupam SinghPosted Jan 17, 2018, 12:05 AM
Nice Article, Well explained.
Bryian TanPosted Jan 15, 2018, 9:20 PM
Good stuff. Thanks for sharing it.