Reputation: 51
I have containerized and deployed my angular app to nginx. I want to send a Content-Security-Policy header with a nonce. I am using $ssl_session_id for the nonce from nginx.
I am able to pass the nonce to the angular app and use it. But the issue I noticed is that for the ssl_session_id of each of the subrequests within the index.html, some are using a seperate $ssl_session_id and some are using the same $ssl_session_id as index.html
Thus the nonce set in the meta tag of the index.html is not matching with the nonce in the Content-Security-Policy header of some subrequests.
The expectation is that the nonce must be regenerated only everytime the index.html is served i.e everytime the angular app is reloaded and not for every subrequest within the index.html. Below is the index.html.
<!doctype html>
<html lang="en">
<head>
<title>CsrfInAngular</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="CSP_NONCE" content="NGINX_CSP_NONCE" />
<link rel="icon" type="image/x-icon" href="favicon.ico">
<style >
h4{
color:red;
}
</style>
<script type="text/javascript" src="assets/js/external.js"></script>
</head>
<body>
<script>
console.log("I am an inline script")
</script>
<app-root></app-root>
</body>
</html>
Below is the app.module.ts
import { Observable } from 'rxjs';
import { FormsModule } from '@angular/forms';
import { Meta } from '@angular/platform-browser';
function setCSPNonce(metaService:Meta):()=> InjectionToken<string>{
return ()=> new InjectionToken(metaService.getTag("name='CSP_NONCE'")?.content || "");
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
HttpClientModule,
],
providers: [
{
provide:CSP_NONCE,
useFactory:setCSPNonce,
deps:[Meta],
multi:true
}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
Below is the nginx.conf I am using right now
server{
listen 0.0.0.0:5443 ssl;
server_name innocent.csrfexample.com;
ssl_certificate /etc/nginx/secureAngularExample.crt;
ssl_certificate_key /etc/nginx/secureAngularExample.key;
default_type application/octet-stream;
error_log /var/log/nginx/error.log debug;
set $cspNonce $ssl_session_id;
sub_filter_once off;
sub_filter_types *;
sub_filter NGINX_CSP_NONCE $cspNonce;
gzip on;
gzip_comp_level 6;
gzip_vary on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_buffers 16 8k;
client_max_body_size 256M;
add_header 'Content-Security-Policy' "default-src 'self'; script-src 'self' 'nonce-$cspNonce'; style-src 'self' 'nonce-$cspNonce' always";
root /usr/share/nginx/html;
location /assets/ {
#assets within the root
autoindex on;
}
location / {
# matches any path within the root
try_files $uri $uri/index.html /index.html =404;
}
error_page 404 /index.html;
}
Upvotes: 1
Views: 247