1+ const { v4 : uuidv4 } = require ( 'uuid' ) ;
2+ const CSP_DATA = {
3+ CSP : 'csp' ,
4+ CSPRO : 'cspro' ,
5+ CSPRO_EXPOSURE : 'cspro_exposure' ,
6+ CSPRO_2 : 'cspro_p2' ,
7+ CSPRO_2_EXPOSURE : 'cspro_p2_exposure' ,
8+ SESSION_ID_QUERY_PARAM : 'p' ,
9+ VID_QUERY_PARAM : 'v' ,
10+ REPORT_URI_STRING_LENGTH : 11
11+ } ;
12+ const CD_COOCKIE = '__pxvid' ;
13+
14+ function CdEnforce ( cspData , req , res ) {
15+ const cdVid = getCdCookie ( req ) ;
16+ handleCSP ( res , cspData , cdVid ) ;
17+
18+ }
19+
20+ function handleCSP ( response , cspData , vid ) {
21+ const rand = Math . floor ( Math . random ( ) * 100 ) + 1 ; //random number between 1-100 include
22+ try {
23+ let csp = cspData [ CSP_DATA . CSP ] ;
24+ const sessionId = uuidv4 ( ) ;
25+ if ( csp ) {
26+ csp = updateCspReportUri ( csp , sessionId , vid ) ;
27+ response . setHeader ( 'Content-Security-Policy' , csp ) ;
28+ }
29+
30+ let cspReportOnly = getCSPROHeader ( cspData , CSP_DATA . CSPRO_EXPOSURE , CSP_DATA . CSPRO , rand , sessionId , vid ) ;
31+ if ( cspReportOnly ) {
32+ response . setHeader ( 'Content-Security-Policy-Report-Only' , cspReportOnly ) ;
33+ } else {
34+ cspReportOnly = getCSPROHeader ( cspData , CSP_DATA . CSPRO_2_EXPOSURE , CSP_DATA . CSPRO_2 , rand , sessionId , vid ) ;
35+ if ( cspReportOnly ) {
36+ response . setHeader ( 'Content-Security-Policy-Report-Only' , cspReportOnly ) ;
37+ }
38+ }
39+ } catch ( e ) {
40+ // CSP couldnt be read, continue without it
41+ console . log ( `Exception Caught in HandleCSP. error: ${ e } ` ) ;
42+ }
43+ }
44+
45+ function getCSPROHeader ( cspData , exposureKey , policyKey , rand , sessionId , vid ) {
46+ const percentage = parseInt ( cspData [ exposureKey ] ) ;
47+ if ( rand <= percentage ) {
48+ let cspReportOnly = cspData [ policyKey ] ;
49+ if ( cspReportOnly ) {
50+ cspReportOnly = updateCspReportUri ( cspReportOnly , sessionId , vid ) ;
51+ return cspReportOnly ;
52+ }
53+ }
54+ }
55+
56+ function updateCspReportUri ( policy , sessionId , vid ) {
57+ const matches = policy . match ( / r e p o r t - u r i ( [ ^ ; ] + ) / ) ;
58+ if ( matches && matches . length > 1 ) {
59+ const reportUrl = new URL ( matches [ 1 ] ) ;
60+ reportUrl . searchParams . append ( CSP_DATA . SESSION_ID_QUERY_PARAM , sessionId ) ;
61+ if ( vid ) {
62+ reportUrl . searchParams . append ( CSP_DATA . VID_QUERY_PARAM , vid ) ;
63+ }
64+ const result = reportUrl . toString ( ) ;
65+ const index = matches . index + matches [ 0 ] . length ;
66+ policy = policy . slice ( 0 , matches . index + CSP_DATA . REPORT_URI_STRING_LENGTH ) + result + policy . slice ( index ) ;
67+ }
68+
69+ return policy ;
70+ }
71+
72+ function getCdCookie ( req ) {
73+ const cookies = req . cookies ;
74+ if ( cookies && cookies [ CD_COOCKIE ] ) {
75+ return cookies [ CD_COOCKIE ] ;
76+ }
77+ }
78+
79+ module . exports = CdEnforce ;
0 commit comments