PluginProbe
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… / 2.11.8
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… v2.11.8
3.0.0 2.11.12 2.11.11 2.11.10 2.11.9 2.11.7 2.11.8 2.11.6 2.11.5 2.11.4 2.11.3 2.11.1 2.11.2 2.11.0 2.10.5 2.10.4 2.10.3 2.10.2 2.10.1 2.10.0 2.9.9 2.9.8 2.9.6 2.9.7 2.9.5 All 88 releases
← All changes | includes/class-security-headers.php +33 -45 2.9.82.11.8 View file →
@@ -53,9 +53,14 @@
53 53 * Apply security headers to .htaccess
54 54 *
55 55 * @return bool|WP_Error
56 56 */
57 - public function apply_rules() {
57 + /**
58 + * @param bool $automatic True when Vigilant is refreshing the block by
59 + * itself rather than because someone pressed Save.
60 + * See Vigilante_Htaccess_Manager::add_block().
61 + */
62 + public function apply_rules( $automatic = false ) {
58 63 require_once VIGILANTE_INCLUDES_DIR . 'class-htaccess-manager.php';
59 64
60 65 $manager = Vigilante_Htaccess_Manager::get_instance();
61 66
@@ -68,9 +73,9 @@
68 73 }
69 74
70 75 $rules = $this->generate_rules_content();
71 76
72 - $result = $manager->add_block( self::MARKER_START, self::MARKER_END, $rules, 'top' );
77 + $result = $manager->add_block( self::MARKER_START, self::MARKER_END, $rules, 'top', $automatic );
73 78
74 79 if ( true === $result ) {
75 80 /** This action is documented in class-wpconfig-security.php */
76 81 do_action( 'vigilante_critical_file_written', '.htaccess' );
@@ -306,11 +311,14 @@
306 311
307 312 /**
308 313 * Generate rules content (without markers)
309 314 *
315 + * Public since 2.10.0: it is also "what this configuration would write right
316 + * now", which is what Vigilante_Htaccess_Recovery compares the file against.
317 + *
310 318 * @return string
311 319 */
312 - private function generate_rules_content() {
320 + public function generate_rules_content() {
313 321 $rules = array();
314 322
315 323 $rules[] = '# Vigilante - Security Headers';
316 324 $rules[] = '# Generated: ' . gmdate( 'Y-m-d H:i:s' ) . ' UTC';
@@ -465,22 +473,37 @@
465 473 }
466 474 }
467 475 }
468 476
469 - // Cross-Origin policies
477 + /*
478 + * Cross-Origin policies.
479 + *
480 + * Allow-listed rather than escaped, for the same reason sanitize_header_value()
481 + * runs at generation time: these three became editable in 2.10.0 and their value
482 + * is written verbatim inside a Header directive. Only the tokens the specs define
483 + * are ever emitted, so an unexpected value (a crafted request, an imported
484 + * settings file, a direct write to the option) drops the header instead of
485 + * reaching the .htaccess.
486 + *
487 + * COEP deliberately omits unsafe-none: it is the browser default, so emitting it
488 + * adds nothing. That was the behaviour before this list existed and it is kept.
489 + */
470 490 if ( ! empty( $this->options['cross_origin_policies'] ) ) {
471 491 $policies = $this->options['cross_origin_policies'];
472 492
473 - if ( ! empty( $policies['embedder_policy'] ) && 'unsafe-none' !== $policies['embedder_policy'] ) {
474 - $rules[] = ' Header always set Cross-Origin-Embedder-Policy "' . $this->sanitize_header_value( $policies['embedder_policy'] ) . '"';
493 + $coep = isset( $policies['embedder_policy'] ) ? (string) $policies['embedder_policy'] : '';
494 + if ( in_array( $coep, array( 'require-corp', 'credentialless' ), true ) ) {
495 + $rules[] = ' Header always set Cross-Origin-Embedder-Policy "' . $coep . '"';
475 496 }
476 497
477 - if ( ! empty( $policies['opener_policy'] ) ) {
478 - $rules[] = ' Header always set Cross-Origin-Opener-Policy "' . $this->sanitize_header_value( $policies['opener_policy'] ) . '"';
498 + $coop = isset( $policies['opener_policy'] ) ? (string) $policies['opener_policy'] : '';
499 + if ( in_array( $coop, array( 'unsafe-none', 'same-origin-allow-popups', 'same-origin' ), true ) ) {
500 + $rules[] = ' Header always set Cross-Origin-Opener-Policy "' . $coop . '"';
479 501 }
480 502
481 - if ( ! empty( $policies['resource_policy'] ) ) {
482 - $rules[] = ' Header always set Cross-Origin-Resource-Policy "' . $this->sanitize_header_value( $policies['resource_policy'] ) . '"';
503 + $corp = isset( $policies['resource_policy'] ) ? (string) $policies['resource_policy'] : '';
504 + if ( in_array( $corp, array( 'same-site', 'same-origin', 'cross-origin' ), true ) ) {
505 + $rules[] = ' Header always set Cross-Origin-Resource-Policy "' . $corp . '"';
483 506 }
484 507 }
485 508
486 509 // Remove X-Powered-By
@@ -489,43 +512,8 @@
489 512
490 513 $rules[] = '</IfModule>';
491 514
492 515 return implode( "\n", $rules );
493 - }
494 -
495 - /**
496 - * Get headers preview
497 - *
498 - * @return array
499 - */
500 - public function get_headers_preview() {
501 - $headers = array();
502 -
503 - if ( ! empty( $this->options['x_frame_options'] ) ) {
504 - $headers['X-Frame-Options'] = $this->options['x_frame_options'];
505 - }
506 -
507 - if ( ! empty( $this->options['x_content_type_options'] ) ) {
508 - $headers['X-Content-Type-Options'] = 'nosniff';
509 - }
510 -
511 - if ( ! empty( $this->options['referrer_policy'] ) ) {
512 - $headers['Referrer-Policy'] = $this->options['referrer_policy'];
513 - }
514 -
515 - if ( ! empty( $this->options['hsts']['enabled'] ) ) {
516 - $hsts = $this->options['hsts'];
517 - $value = 'max-age=' . absint( $hsts['max_age'] );
518 - if ( ! empty( $hsts['include_subdomains'] ) ) {
519 - $value .= '; includeSubDomains';
520 - }
521 - if ( ! empty( $hsts['preload'] ) ) {
522 - $value .= '; preload';
523 - }
524 - $headers['Strict-Transport-Security'] = $value;
525 - }
526 -
527 - return $headers;
528 516 }
529 517
530 518 /**
531 519 * Get security grade based on enabled headers