I’ve recently been developing a WordPress replacement for https://found-art.roguelj.co.uk. WordPress is overkill for the needs of that site, and the additional functionality that I required would have had to have been provided by 3rd party plug-ins. Or I could have created the plug-ins myself, but it’s been a while since I coded any PHP.
In addition to this, I have also been wanting to test out some web app vulnerability scanners. Development of the new site for Found Art presented a perfect opportunity to test out ZAP – Zed Attack Proxy.
Now, I’ve never used ZAP before, so I just dived in and ran it using ‘Attack’ mode against the locally-running dev-site. It flagged several issues, all related to missing Content Security Policy headers.

A quick internet search on how to fix this for an ASP Core NET website lead me to the following page https://the-runtime.dev/articles/content-security-policy-headers. Implementing the policies was easy, with the pertinent code being as follows:
app.Use(async (context, next) =>
{
var nonce = Convert.ToBase64String(RandomNumberGenerator.GetBytes(16));
context.Items["CspNonce"] = nonce;
context.Response.Headers.Append(
"Content-Security-Policy",
$"default-src 'self'; script-src 'self' 'nonce-{nonce}'");
await next();
});
The code above was specifically related to using a nonce for inline scripts. All well and good, and things worked as required once I had set the nonce in the appropriate scripts, as follows:
@{
ViewData["Title"] = "Home Page";
var nonce = Context.Items["CspNonce"]?.ToString();
}
I did have to tweak the code a little, because by default it didn’t include the other policies created by the CspBuilder (details on the page, go check it out)
context.Response.Headers.Append(
Constants.Headers.CONTENT_SECURITY_POLICY_HEADER,
$"{csp}; script-src 'nonce-{nonce}' 'self'; style-src 'nonce-{nonce}' 'self';");
A line in the middleware for the request (app.Use) caught my eye:
Convert.ToBase64String(RandomNumberGenerator.GetBytes(16)
This middleware runs for every request and therefore it should be as fast as possible. I wondered if there was a faster way to get 16 random characters, and it appears that there is:
var nonce = Random.Shared.GetString("abcdef0123456789", 16);
The documentation for GetString can be found here.
This will basically return a hex string, however we’re limiting the characters that the function can use so the available entropy is not as high as it could be. Increasing the pool of characters to draw from does come with a little quirk, stick around for part 2 for the details.