PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 1.10.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v1.10.0
2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
thinkrank / includes / core / class-security-headers.php

class-security-headers.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 1.10.0, at includes/core/class-security-headers.php

200 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Security Headers Manager
4 *
5 * Manages security headers for the ThinkRank plugin to prevent
6 * XSS, clickjacking, and other security vulnerabilities.
7 *
8 * @package ThinkRank
9 * @subpackage Core
10 * @since 1.0.0
11 */
12
13 declare(strict_types=1);
14
15 namespace ThinkRank\Core;
16
17 // Prevent direct access
18 if (!defined('ABSPATH')) {
19 exit;
20 }
21
22 /**
23 * Security Headers Manager Class
24 *
25 * Implements basic security headers for admin pages and API endpoints
26 * to enhance security posture.
27 *
28 * @since 1.0.0
29 */
30 class Security_Headers {
31
32 /**
33 * Initialize security headers
34 *
35 * @since 1.0.0
36 */
37 public function __construct() {
38 add_action('admin_init', [$this, 'add_admin_security_headers']);
39 add_action('rest_api_init', [$this, 'add_api_security_headers']);
40 }
41
42 /**
43 * Add security headers for admin pages
44 *
45 * @since 1.0.0
46 */
47 public function add_admin_security_headers(): void {
48 // Only add headers on ThinkRank admin pages
49 if (!$this->is_thinkrank_admin_page()) {
50 return;
51 }
52
53 // Prevent clickjacking
54 if (!headers_sent()) {
55 header('X-Frame-Options: SAMEORIGIN');
56 header('X-Content-Type-Options: nosniff');
57 header('X-XSS-Protection: 1; mode=block');
58 header('Referrer-Policy: strict-origin-when-cross-origin');
59
60 // Basic CSP for admin pages
61 $csp = $this->get_admin_csp_policy();
62 header("Content-Security-Policy: {$csp}");
63 }
64 }
65
66 /**
67 * Add security headers for API endpoints
68 *
69 * @since 1.0.0
70 */
71 public function add_api_security_headers(): void {
72 add_filter('rest_pre_serve_request', [$this, 'add_rest_security_headers'], 10, 4);
73 }
74
75 /**
76 * Add security headers to REST API responses
77 *
78 * @since 1.0.0
79 *
80 * @param bool $served Whether the request has already been served
81 * @param WP_HTTP_Response $result Result to send to the client
82 * @param WP_REST_Request $request Request used to generate the response
83 * @param WP_REST_Server $server Server instance
84 * @return bool
85 */
86 public function add_rest_security_headers($served, $result, $request, $server): bool {
87 // Only add headers to ThinkRank API endpoints
88 if (!$this->is_thinkrank_api_request($request)) {
89 return $served;
90 }
91
92 if (!headers_sent()) {
93 header('X-Content-Type-Options: nosniff');
94 header('X-Frame-Options: DENY');
95 header('X-XSS-Protection: 1; mode=block');
96 header('Referrer-Policy: strict-origin');
97
98 // CORS headers for API
99 $this->add_cors_headers();
100 }
101
102 return $served;
103 }
104
105 /**
106 * Check if current page is a ThinkRank admin page
107 *
108 * @since 1.0.0
109 *
110 * @return bool
111 */
112 private function is_thinkrank_admin_page(): bool {
113 if (!is_admin()) {
114 return false;
115 }
116
117 $screen = get_current_screen();
118 if (!$screen) {
119 return false;
120 }
121
122 // Check if it's a ThinkRank admin page
123 return strpos($screen->id, 'thinkrank') !== false ||
124 strpos($screen->base, 'thinkrank') !== false ||
125 (isset($_GET['page']) && strpos($_GET['page'], 'thinkrank') !== false);
126 }
127
128 /**
129 * Check if request is to a ThinkRank API endpoint
130 *
131 * @since 1.0.0
132 *
133 * @param WP_REST_Request $request Request object
134 * @return bool
135 */
136 private function is_thinkrank_api_request($request): bool {
137 $route = $request->get_route();
138 return strpos($route, '/thinkrank/') === 0;
139 }
140
141 /**
142 * Get Content Security Policy for admin pages
143 *
144 * @since 1.0.0
145 *
146 * @return string CSP policy string
147 */
148 private function get_admin_csp_policy(): string {
149 $site_url = get_site_url();
150 $admin_url = admin_url();
151
152 $policies = [
153 "default-src 'self'",
154 "script-src 'self' 'unsafe-inline' 'unsafe-eval' {$site_url} {$admin_url}",
155 "style-src 'self' 'unsafe-inline' {$site_url} {$admin_url}",
156 "img-src 'self' data: {$site_url}",
157 "font-src 'self' {$site_url}",
158 "connect-src 'self' {$site_url}",
159 "frame-src 'none'",
160 "object-src 'none'",
161 "base-uri 'self'"
162 ];
163
164 return implode('; ', $policies);
165 }
166
167 /**
168 * Add CORS headers for API endpoints
169 *
170 * @since 1.0.0
171 */
172 private function add_cors_headers(): void {
173 $origin = get_site_url();
174
175 header("Access-Control-Allow-Origin: {$origin}");
176 header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
177 header('Access-Control-Allow-Headers: Content-Type, Authorization, X-WP-Nonce');
178 header('Access-Control-Allow-Credentials: true');
179 header('Access-Control-Max-Age: 86400'); // 24 hours
180 }
181
182 /**
183 * Get security headers status
184 *
185 * @since 1.0.0
186 *
187 * @return array Security headers status
188 */
189 public function get_security_status(): array {
190 return [
191 'headers_enabled' => true,
192 'csp_enabled' => true,
193 'cors_configured' => true,
194 'xss_protection' => true,
195 'clickjacking_protection' => true,
196 'content_type_protection' => true
197 ];
198 }
199 }
200