Skip to content
Merged
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ If necessary, you may install it manually by downloading a Zip archive from [Git
- REST API links
- Oembed links
- Windows Live Writer manifest links
- Set sensible security headers

### Capabilities

Expand Down Expand Up @@ -95,6 +96,7 @@ The following filters can be used to override the default behavior of certain fe
- `orbit_enable_rest_api_user_endpoints`: Enable or disable REST API user endpoints. Default `false` (disabled).
- `orbit_enable_xmlrpc`: Enable or disable XML-RPC functionality. Default `false` (disabled).
- `orbit_enable_expose_wordpress_version`: Show or hide the WordPress version in the site's frontend markup. Default `false` (hidden).
- `orbit_default_security_headers`: Set an array of security headers.

### Capabilities

Expand Down
77 changes: 40 additions & 37 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions includes/classes/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public function setup(): void {
Performance\Fast404::instance()->setup();
Security\DisableAPI::instance()->setup();
Security\DisableXMLRPC::instance()->setup();
Security\Headers::instance()->setup();
Security\HideAuthor::instance()->setup();
Security\HideVersion::instance()->setup();
Security\RemoveHeadLinks::instance()->setup();
Expand Down
73 changes: 73 additions & 0 deletions includes/classes/Security/Headers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
/**
* Amend security headers
*
* @package Orbit
*/

namespace Eighteen73\Orbit\Security;

use Eighteen73\Orbit\Singleton;

/**
* Add a sensible baseline set of security headers to the response.
*/
class Headers {
use Singleton;

/**
* Setup module
*/
public function setup() {
add_filter( 'wp_headers', [ $this, 'set_security_headers' ], 99, 1 );
}

/**
* Set security headers
*
* @param array $headers Headers
* @return array
*/
public function set_security_headers( $headers ) {

$default_security_headers = [
// Cross-origin hardening
'Cross-Origin-Opener-Policy' => 'same-origin',
'Cross-Origin-Resource-Policy' => 'same-origin',

// Sensible privacy default
'Referrer-Policy' => 'strict-origin-when-cross-origin',

// Stops MIME sniffing
'X-Content-Type-Options' => 'nosniff',

// Prevent clickjacking inside iframes (legacy)
'X-Frame-Options' => 'SAMEORIGIN',

// Permissive CSP (websites should customise this, ideally)
'Content-Security-Policy' => implode('; ', [
"default-src 'self' https:",
"img-src 'self' https: data: blob:",
"script-src 'self' https: 'unsafe-inline' 'unsafe-eval'",
"style-src 'self' https: 'unsafe-inline'",
"frame-ancestors 'self'",
]),
];

// Only if SSL
if ( is_ssl() ) {
$default_security_headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains';
$default_security_headers['Content-Security-Policy'] .= '; upgrade-insecure-requests';
}

$security_headers = apply_filters( 'orbit_default_security_headers', $default_security_headers );

foreach ( $security_headers as $header => $value ) {
if ( ! empty( $value ) ) {
$headers[ $header ] = $value;
}
}

return $headers;
}
}
8 changes: 7 additions & 1 deletion includes/lib/Symfony/Component/CssSelector/Parser/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,20 @@ class Token
public const TYPE_NUMBER = 'number';
public const TYPE_STRING = 'string';

/**
* @param self::TYPE_*|null $type
*/
public function __construct(
private ?string $type,
private ?string $value,
private ?int $position,
) {
}

public function getType(): ?int
/**
* @return self::TYPE_*|null
*/
public function getType(): ?string
{
return $this->type;
}
Expand Down