PluginProbe
Falcon – Cache, Performance, Security, Cleanup, and Tweaks / 2.11.1
Falcon – Cache, Performance, Security, Cleanup, and Tweaks v2.11.1
2.11.2 2.11.1 2.11.0 2.10.1 trunk 1.0.1 1.0.2 1.0.3 1.1 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.3 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1.0 2.10.0 2.2.0 All 45 releases
falcon / src / Security.php

Security.php in Falcon – Cache, Performance, Security, Cleanup, and Tweaks 2.11.1, at src/Security.php

155 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Falcon;
3
4 use WP_Error;
5
6 class Security extends Base {
7 protected $features = [
8 'no_rest_api',
9 'no_xmlrpc',
10 'no_login_errors',
11 'restrict_upload',
12 'block_ai_bots',
13 'force_login',
14 'comment_spam_protection',
15 'limit_logins',
16 ];
17
18 public function no_rest_api(): void {
19 remove_action( 'wp_head', 'rest_output_link_wp_head' );
20 remove_action( 'xmlrpc_rsd_apis', 'rest_output_rsd' );
21 remove_action( 'template_redirect', 'rest_output_link_header', 11 );
22
23 add_filter( 'rest_authentication_errors', [ $this, 'no_public_rest_api' ] );
24 }
25
26 public function no_public_rest_api( $access ) {
27 return is_user_logged_in()
28 ? $access
29 : new WP_Error( 'rest_login_required', __( 'REST API restricted to authenticated users.', 'falcon' ), [ 'status' => rest_authorization_required_code() ] );
30 }
31
32 public function no_xmlrpc(): void {
33 add_filter( 'xmlrpc_enabled', '__return_false' );
34 add_filter( 'xmlrpc_methods', '__return_empty_array' );
35 add_filter( 'pings_open', '__return_false' );
36 }
37
38 public function no_login_errors(): void {
39 add_filter( 'login_errors', [ $this, 'custom_login_errors' ] );
40 }
41
42 public function custom_login_errors( string $error ): string {
43 if ( Components\LimitLogins::was_blocked() ) {
44 return $error;
45 }
46
47 return __( 'There is something wrong. Please try again.', 'falcon' );
48 }
49
50 public function restrict_upload(): void {
51 add_filter( 'upload_mimes', [ $this, 'restrict_upload_mimes' ] );
52 }
53
54 public function restrict_upload_mimes(): array {
55 return [
56 'jpg|jpeg' => 'image/jpeg',
57 'gif' => 'image/gif',
58 'png' => 'image/png',
59 'avif' => 'image/avif',
60 'webp' => 'image/webp',
61 'mp4' => 'video/mp4',
62 'pdf' => 'application/pdf',
63 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
64 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
65 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
66 ];
67 }
68
69 public function block_ai_bots(): void {
70 add_action( 'do_robotstxt', [ $this, 'block_ai_bots_in_robots_txt' ] );
71 }
72
73 /**
74 * Block AI bots via robots.txt
75 *
76 * @link https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/
77 */
78 public function block_ai_bots_in_robots_txt(): void {
79 $user_agents = [
80 'CCBot',
81 'ChatGPT-User',
82 'GPTBot',
83 'Google-Extended',
84 'anthropic-ai',
85 'Omgilibot',
86 'Omgili',
87 'FacebookBot',
88 'Bytespider',
89 ];
90 $content = [];
91 foreach ( $user_agents as $user_agent ) {
92 $content[] = "User-agent: $user_agent";
93 $content[] = 'Disallow: /';
94 $content[] = '';
95 }
96
97 echo "\n", implode( "\n", $content ), "\n"; // phpcs:ignore
98 }
99
100 public function force_login(): void {
101 add_action( 'template_redirect', [ $this, 'redirect_non_logged_in_users' ] );
102 }
103
104 /**
105 * Simple technique to prevent spam comments. Credit to Maarten Belmans.
106 * @link https://x.com/PoeHaH/status/2043964375959048388
107 */
108 public function comment_spam_protection(): void {
109 add_filter( 'pre_comment_approved', [ $this, 'check_comment_spam' ], 10, 2 );
110 add_action( 'comment_form_after', [ $this, 'add_comment_spam_protection_script' ] );
111 }
112
113 public function check_comment_spam( $approved ) {
114 if ( ! is_admin() && ( empty( $_POST['comment-check'] ) || $_POST['comment-check'] !== 'ok' ) ) {
115 return new WP_Error( 'comment_lang', __( 'Your comment is detected as spam.', 'falcon' ), 429 );
116 }
117
118 return $approved;
119 }
120
121 public function add_comment_spam_protection_script(): void {
122 ?>
123 <script>
124 {
125 let form = document.querySelector( '#commentform' );
126 if ( form ) {
127 setTimeout( function() {
128 let input = document.createElement( 'input' );
129 input.type = 'hidden';
130 input.name = 'comment-check';
131 input.value = 'ok';
132 form.appendChild( input );
133 }, 2000 );
134 }
135 }
136 </script>
137 <?php
138 }
139
140 public function limit_logins(): void {
141 new Components\LimitLogins;
142 }
143
144 public function redirect_non_logged_in_users(): void {
145 if ( is_user_logged_in() ) {
146 return;
147 }
148
149 nocache_headers();
150
151 wp_safe_redirect( wp_login_url(), 302 );
152 die;
153 }
154 }
155