request( '/' ); if ( is_wp_error( $response ) ) { return $this->info( __( 'Unable to fetch the home page to inspect response headers.', 'aardwolf-security-scanner' ) ); } $headers = wp_remote_retrieve_headers( $response ); // Normalise header access — WP_HTTP_Requests_Response exposes an // ArrayAccess-ish object; fall back gracefully. $get = function ( $name ) use ( $headers ) { if ( is_object( $headers ) && method_exists( $headers, 'offsetExists' ) ) { return $headers->offsetExists( $name ) ? $headers[ $name ] : ''; } $lower = array_change_key_case( (array) $headers, CASE_LOWER ); return isset( $lower[ strtolower( $name ) ] ) ? $lower[ strtolower( $name ) ] : ''; }; $is_https = 'https' === wp_parse_url( home_url(), PHP_URL_SCHEME ); // Header => [severity, remediation snippet]. $expected = array( 'X-Frame-Options' => __( 'protects against clickjacking (set to SAMEORIGIN)', 'aardwolf-security-scanner' ), 'X-Content-Type-Options' => __( 'stops MIME-type sniffing (set to nosniff)', 'aardwolf-security-scanner' ), 'Referrer-Policy' => __( 'limits referrer leakage (e.g. strict-origin-when-cross-origin)', 'aardwolf-security-scanner' ), 'Content-Security-Policy' => __( 'mitigates cross-site scripting and data injection', 'aardwolf-security-scanner' ), ); if ( $is_https ) { $expected['Strict-Transport-Security'] = __( 'enforces HTTPS on future visits (HSTS)', 'aardwolf-security-scanner' ); } $missing = array(); foreach ( $expected as $header => $why ) { if ( '' === $get( $header ) ) { $missing[] = sprintf( '%s (%s)', $header, $why ); } } if ( empty( $missing ) ) { return $this->pass( __( 'All recommended HTTP security headers are present.', 'aardwolf-security-scanner' ) ); } // Missing the whole set is more serious than missing one. $severity = count( $missing ) >= 3 ? Aardwolf_Check_Result::SEVERITY_MEDIUM : Aardwolf_Check_Result::SEVERITY_LOW; return $this->warn( $severity, sprintf( /* translators: %s: newline separated list of missing headers. */ __( 'The following recommended security headers are missing: %s', 'aardwolf-security-scanner' ), "\n" . implode( "\n", $missing ) ), __( 'Add these headers at the web-server or CDN level (or with a dedicated headers plugin). Test a Content-Security-Policy carefully on staging first, since a strict policy can block legitimate scripts. HSTS should only be enabled once you are confident HTTPS is permanent.', 'aardwolf-security-scanner' ), 'https://owasp.org/www-project-secure-headers/' ); } }