1
1
import * as path from 'path' ;
2
2
import merge from "webpack-merge" ;
3
+ import { RawSource } from 'webpack-sources' ;
3
4
import * as SentryPlugin from '@sentry/webpack-plugin' ;
4
5
5
6
import { InjectManifest } from 'workbox-webpack-plugin' ;
6
7
import * as ssri from "ssri" ;
7
-
8
8
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer' ;
9
+ import CspHtmlWebpackPlugin from 'csp-html-webpack-plugin' ;
9
10
10
11
import common from "./webpack.common" ;
11
12
@@ -16,6 +17,14 @@ console.log(shouldPublishSentryRelease
16
17
: "Sentry source map upload disabled - no token set"
17
18
) ;
18
19
20
+ const CSP_REPORT_URL = process . env . REPORT_URI && process . env . UI_VERSION
21
+ ? `${ process . env . REPORT_URI } &sentry_release=${ process . env . UI_VERSION } `
22
+ : false ;
23
+ console . log ( CSP_REPORT_URL
24
+ ? "CSP reporting enabled"
25
+ : `CSP reporting skipped (uri: ${ process . env . REPORT_URI } . version: ${ process . env . UI_VERSION } )`
26
+ ) ;
27
+
19
28
export default merge ( common , {
20
29
mode : "production" ,
21
30
@@ -68,7 +77,13 @@ export default merge(common, {
68
77
'services' ,
69
78
'ui-update-worker.ts'
70
79
) ,
71
- exclude : [ 'google-fonts' , / ^ a p i \/ / , 'ui-update-worker.js' , / .m a p $ / ] ,
80
+ exclude : [
81
+ 'google-fonts' ,
82
+ / ^ a p i \/ / ,
83
+ 'ui-update-worker.js' ,
84
+ / \. m a p $ / ,
85
+ / \. c a d d y f i l e $ /
86
+ ] ,
72
87
maximumFileSizeToCacheInBytes : 100 * 1024 * 1024 ,
73
88
manifestTransforms : [
74
89
( originalManifest : any , compilation : any ) => {
@@ -111,6 +126,52 @@ export default merge(common, {
111
126
analyzerMode : 'static' ,
112
127
openAnalyzer : false ,
113
128
excludeAssets : / a p i \/ .* \. j s o n /
114
- } )
129
+ } ) ,
130
+ ...( CSP_REPORT_URL
131
+ ? [
132
+ new CspHtmlWebpackPlugin ( {
133
+ 'base-uri' : "'self'" ,
134
+ 'default-src' : "'none'" ,
135
+ 'object-src' : "'none'" ,
136
+ 'frame-ancestors' : "'none'" ,
137
+ 'img-src' : [ "'self'" , 'https://httptoolkit.com' , 'data:' ] ,
138
+ 'font-src' : [ "'self'" ] ,
139
+ 'style-src' : [ "'report-sample'" , "'self'" , "'unsafe-inline'" ] ,
140
+ 'script-src' : [
141
+ "'report-sample'" ,
142
+ "'unsafe-eval'" , // For both wasm & real eval() uses
143
+ "'self'" , 'https://cdn.auth0.com/' , 'https://cdn.eu.auth0.com/'
144
+ ] ,
145
+ 'connect-src' : [
146
+ "'self'" , 'http://127.0.0.1:45456' , 'http://127.0.0.1:45457' , 'ws://127.0.0.1:45456' , 'https://*.httptoolkit.tech' , 'https://sentry.io' , 'data:'
147
+ ] ,
148
+ 'report-uri' : CSP_REPORT_URL ,
149
+ 'report-to' : 'csp-endpoint'
150
+ } , {
151
+ enabled : true ,
152
+ hashEnabled : {
153
+ 'script-src' : true ,
154
+ 'style-src' : false
155
+ } ,
156
+ nonceEnabled : {
157
+ 'script-src' : false ,
158
+ 'style-src' : false
159
+ } ,
160
+ // Output CSP into a Caddy config file, that's imported by Caddyfile
161
+ processFn : (
162
+ builtPolicy : any ,
163
+ _htmlPluginData : any ,
164
+ _obj : any ,
165
+ compilation : any
166
+ ) => {
167
+ const header = `
168
+ header Content-Security-Policy-Report-Only "${ builtPolicy } "
169
+ header Reporting-Endpoints \`csp-endpoint="${ CSP_REPORT_URL } "\`
170
+ ` ;
171
+ compilation . emitAsset ( 'csp.caddyfile' , new RawSource ( header ) ) ;
172
+ }
173
+ } as any )
174
+ ]
175
+ : [ ] )
115
176
]
116
- } ) ;
177
+ } ) ;
0 commit comments