|
1 | 1 | <?php |
2 | 2 | /* |
3 | 3 | Plugin Name: BeAPI Default - HTTP Headers |
4 | | -Version: 1.0.0 |
| 4 | +Version: 1.1.0 |
5 | 5 | Plugin URI: https://beapi.fr |
6 | 6 | Description: Add custom http headers (CP, CSP, ....) |
7 | 7 | Author: Be API |
|
41 | 41 | * @return array |
42 | 42 | * |
43 | 43 | * @author Alexandre Sadowski |
44 | | - * |
45 | 44 | */ |
46 | 45 | function wp_headers( array $headers ): array { |
47 | 46 | if ( is_admin() ) { |
48 | 47 | return $headers; |
49 | 48 | } |
50 | 49 |
|
51 | | - $csp = get_csp_headers(); |
| 50 | + $csp = get_csp_headers(); |
| 51 | + $has_report_url = defined( 'WP_SENTRY_SECURITY_HEADER_ENDPOINT' ) && ! empty( WP_SENTRY_SECURITY_HEADER_ENDPOINT ); |
| 52 | + $report_only = defined( 'CSP_REPORT_ONLY' ) && CSP_REPORT_ONLY; |
| 53 | + |
| 54 | + if ( $report_only && $has_report_url ) { |
| 55 | + $report_url = WP_SENTRY_SECURITY_HEADER_ENDPOINT; |
| 56 | + // include env name in the URL if available. |
| 57 | + if ( defined( 'WP_SENTRY_ENV' ) && ! empty( WP_SENTRY_ENV ) ) { |
| 58 | + $report_url = add_query_arg( array( 'sentry_environment' => WP_SENTRY_ENV ), $report_url ); |
| 59 | + } |
52 | 60 |
|
53 | | - if ( defined( 'CSP_REPORT_ONLY' ) && defined( 'WP_SENTRY_SECURITY_HEADER_ENDPOINT' ) ) { |
54 | | - $csp['report-uri'] = WP_SENTRY_SECURITY_HEADER_ENDPOINT; |
55 | | - $csp['report-to'] = 'csp-endpoint'; |
| 61 | + /** |
| 62 | + * Setup CSP violation reporting. |
| 63 | + * |
| 64 | + * @see https://docs.sentry.io/platforms/go/security-policy-reporting/#content-security-policy Sentry documentation on setting the CSP reporting. |
| 65 | + */ |
| 66 | + // CSP directives use for reporting CSP violations. |
| 67 | + $csp['report-to'] = 'csp-endpoint'; |
| 68 | + |
| 69 | + // Deprecated CSP directive for reporting, kept for compatibility with old browsers. |
| 70 | + $csp['report-uri'] = $report_url; |
| 71 | + |
| 72 | + // Include reporting endpoint domain to the list of allowed host |
| 73 | + $csp['connect-src'] = ( $csp['connect-src'] ?? '' ) . ' ' . wp_parse_url( $report_url, PHP_URL_HOST ); |
| 74 | + |
| 75 | + // Additional headers required by the "report-to" CSP directive. |
| 76 | + $headers['Report-To'] = wp_json_encode( |
| 77 | + [ |
| 78 | + 'group' => 'csp-endpoint', |
| 79 | + 'max_age' => 10886400, |
| 80 | + 'endpoints' => [ |
| 81 | + 'url' => $report_url, |
| 82 | + 'include_subdomains' => true, |
| 83 | + ] |
| 84 | + ] |
| 85 | + ); |
| 86 | + $headers['Reporting-Endpoints'] = sprintf( 'csp-endpoint="%s"', $report_url ); |
56 | 87 | } |
57 | 88 |
|
58 | 89 | /** |
59 | 90 | * We rely on the CSP_REPORT_ONLY .env value to decide whether we apply the CSP or just report the errors |
60 | 91 | */ |
61 | | - $csp_header = defined( 'CSP_REPORT_ONLY' ) && CSP_REPORT_ONLY ? 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy'; |
62 | | - $csp_headers_array[ $csp_header ] = get_prepare_csp( $csp ); |
| 92 | + $csp_header = $report_only ? 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy'; |
| 93 | + $headers[ $csp_header ] = get_prepare_csp( $csp ); |
63 | 94 |
|
64 | | - $custom_headers_array = []; |
65 | | - |
66 | | - /**$custom_headers_array = [ |
67 | | - * 'X-Content-Type-Options' => 'nosniff', |
68 | | - * 'X-Frame-Options' => 'SAMEORIGIN', |
69 | | - * 'X-XSS-Protection' => '1; mode=block', |
70 | | - * 'Referrer-Policy' => 'no-referrer-when-downgrade', |
71 | | - * 'Permissions-Policy' => 'accelerometer=(), geolocation=(), fullscreen=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=()', |
72 | | - * ];**/ |
| 95 | + /** |
| 96 | + * Additional security headers. |
| 97 | + * |
| 98 | + * Example : |
| 99 | + * $headers['X-Content-Type-Options'] = 'nosniff'; |
| 100 | + * $headers['X-Frame-Options'] = 'SAMEORIGIN'; |
| 101 | + * $headers['Referrer-Policy'] = 'no-referrer-when-downgrade'; |
| 102 | + * $headers['Permissions-Policy'] = 'accelerometer=(), geolocation=(), fullscreen=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=()'; |
| 103 | + */ |
| 104 | + $headers['X-Content-Type-Options'] = 'nosniff'; |
| 105 | + $headers['X-Frame-Options'] = 'SAMEORIGIN'; |
73 | 106 |
|
74 | | - return wp_parse_args( $csp_headers_array, $custom_headers_array ); |
| 107 | + return $headers; |
75 | 108 | } |
76 | 109 |
|
77 | 110 | add_filter( 'wp_headers', __NAMESPACE__ . '\\wp_headers', 99 ); |
@@ -111,20 +144,21 @@ function get_prepare_csp( array $csp ): string { |
111 | 144 | */ |
112 | 145 | function get_csp_headers(): array { |
113 | 146 | $csp = [ |
114 | | - 'default-src' => '\'self\'', |
115 | | - 'script-src' => '\'self\'', |
116 | | - 'style-src' => '\'self\'', |
117 | | - 'img-src' => '\'self\'', |
118 | | - 'font-src' => '\'self\'', |
119 | | - 'connect-src' => '\'self\'', |
120 | | - 'frame-src' => '\'self\'', |
121 | | - 'manifest-src' => '\'self\'', |
122 | | - 'worker-src' => '\'self\'', |
123 | | - 'object-src' => '\'none\'', |
| 147 | + 'default-src' => "'self'", |
| 148 | + 'script-src' => "'self'", |
| 149 | + 'style-src' => "'self'", |
| 150 | + 'img-src' => "'self'", |
| 151 | + 'font-src' => "'self'", |
| 152 | + 'connect-src' => "'self'", |
| 153 | + 'frame-src' => "'self'", |
| 154 | + 'manifest-src' => "'self'", |
| 155 | + 'worker-src' => "'self'", |
| 156 | + 'object-src' => "'self'", |
| 157 | + 'base-uri' => "'self'", |
124 | 158 | ]; |
125 | 159 |
|
126 | 160 | //if ( 'production' === WP_ENV ) { |
127 | | - //$csp = []; |
| 161 | + // $csp = []; |
128 | 162 | //} |
129 | 163 |
|
130 | 164 | return apply_filters( 'csp_headers', $csp ); |
|
0 commit comments