Skip to content

Commit

Permalink
Merge branch 'release-0.22.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
chesio committed Feb 1, 2024
2 parents da03cfa + de0d2e3 commit 8be2b59
Show file tree
Hide file tree
Showing 156 changed files with 1,038 additions and 437 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/integrate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ jobs:
- name: "Set up PHP"
uses: "shivammathur/setup-php@v2"
with:
php-version: "8.0"
php-version: "8.1"
extensions: "mbstring"
coverage: "none"

- name: "Checkout code"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"

- name: "Install dependencies"
uses: "ramsey/composer-install@v2"
Expand All @@ -72,9 +72,9 @@ jobs:
strategy:
matrix:
php-version:
- "8.3"
- "8.2"
- "8.1"
- "8.0"
dependencies:
- "lowest"
- "locked"
Expand Down Expand Up @@ -125,7 +125,7 @@ jobs:
- name: "Set up PHP"
uses: "shivammathur/setup-php@v2"
with:
php-version: "8.0"
php-version: "8.1"
extensions: "mbstring"
coverage: "none"

Expand Down Expand Up @@ -156,7 +156,7 @@ jobs:
- name: "Set up PHP"
uses: "shivammathur/setup-php@v2"
with:
php-version: "8.0"
php-version: "8.1"
extensions: "mbstring"
coverage: "none"

Expand Down
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
# BC Security Changelog

## Upcoming version 0.21.0 (2023-08-17)
## Version 0.22.0 (2024-02-01)

This release has been tested with PHP 8.3 and WordPress 6.4. PHP 8.1 or newer and WordPress 6.2 or newer are now required!

### Added

* New built-in rule to bad request banner module that triggers when non-existing `readme.txt` file is accessed [#149](https://github.com/chesio/bc-security/issues/149).
* Plugin has been tested with PHP 8.3 [#145](https://github.com/chesio/bc-security/issues/145).
* Plugin has been tested with WordPress 6.4 [#144](https://github.com/chesio/bc-security/issues/144).

### Changed

* PHP 8.1 is required [#143](https://github.com/chesio/bc-security/issues/143). As part of an effort to use modern PHP features whenever useful, _access scope_ values are now passed as [backed enum](https://stitcher.io/blog/php-enums) instances instead of plain `int`. This is a **breaking change** for actions and filters that have _access scope_ value as their argument:
1. `bc-security/action:external-blocklist-hit`
2. `bc-security/action:internal-blocklist-hit`
3. `bc-security/filter:is-ip-address-blocked`
* WordPress 6.2 is required [#147](https://github.com/chesio/bc-security/issues/147).

## Version 0.21.0 (2023-08-17)

PHP 8.0 or newer and WordPress 6.0 or newer are now required!

Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ A WordPress plugin that helps keeping WordPress websites secure.

## Requirements

* [PHP](https://www.php.net/) 8.0 or newer
* [WordPress](https://wordpress.org/) 6.0 or newer
* [PHP](https://www.php.net/) 8.1 or newer
* [WordPress](https://wordpress.org/) 6.2 or newer

## Limitations

Expand Down Expand Up @@ -142,14 +142,17 @@ Passwords are validated on user creation, password change or password reset. If

### Bad requests banner

Remote IP addresses that are scanning your website for weaknesses can be automatically [locked from access](#internal-blocklist) for configured amount of time. Such scanners can be usually quite easily detected because while scanning a website they trigger a lot of 404 errors and URLs they try to access differ from "valid" 404 errors: usually they try to find a known vulnerable plugin file, forgotten backup file or PHP script used for administrative purposes.
Remote IP addresses that are scanning your website for weaknesses can be automatically [blocked](#internal-blocklist) for configured amount of time. Such scanners can be usually quite easily detected because while scanning a website they trigger a lot of 404 errors and URLs they try to access differ from "valid" 404 errors: usually they try to find a known vulnerable plugin, forgotten backup file or PHP script used for administrative purposes.

There are two built-in rules available (they are not active by default):
There are three built-in rules available (they are not active by default):
1. ban when non-existent PHP file is requested (any URL ending with `.php`)
2. ban when backup file is requested (any URL targeting file with `backup` in basename or with `.back`, `.old` or `.tmp` extension)
2. ban when non-existent backup file is requested (any URL targeting file with `backup` in basename or with `.back`, `.old` or `.tmp` extension)
3. ban when non-existent `readme.txt` file is accessed

You may define custom rules as well (in form of regular expression).

Important: When using this feature it is strongly recommended to activate [synchronization](#synchronization-with-htaccess-file) of internal blocklist with `.htaccess` file!

### Internal blocklist

BC Security maintains a list of IP addresses with limited access to the website. This list is automatically populated by [Login security](#login-security) and [Bad requests banner](#bad-requests-banner) modules, but manual addition of IP addresses is also possible.
Expand Down
4 changes: 2 additions & 2 deletions autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

/**
* Register autoloader for classes shipped with the plugin.
*
* @package BC_Security
*/

declare(strict_types=1);

// Register autoload function
\spl_autoload_register(function (string $class) {
// Only autoload classes shipped with the plugin.
Expand Down
14 changes: 8 additions & 6 deletions bc-security.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,26 @@
* Plugin Name: BC Security
* Plugin URI: https://github.com/chesio/bc-security
* Description: Helps keeping WordPress websites secure.
* Version: 0.21.0
* Version: 0.22.0
* Author: Česlav Przywara <[email protected]>
* Author URI: https://www.chesio.com
* Requires PHP: 8.0
* Requires WP: 6.0
* Tested up to: 6.3
* Requires PHP: 8.1
* Requires at least: 6.2
* Tested up to: 6.4
* Text Domain: bc-security
* GitHub Plugin URI: https://github.com/chesio/bc-security
* Update URI: https://github.com/chesio/bc-security
*/

if (version_compare(PHP_VERSION, '8.0', '<')) {
declare(strict_types=1);

if (version_compare(PHP_VERSION, '8.1', '<')) {
// Warn user that his/her PHP version is too low for this plugin to function.
add_action('admin_notices', function () {
echo '<div class="notice notice-error"><p>';
echo esc_html(
sprintf(
__('BC Security plugin requires PHP 8.0 to function properly, but you have version %s installed. The plugin has been auto-deactivated.', 'bc-security'),
__('BC Security plugin requires PHP 8.1 to function properly, but you have version %s installed. The plugin has been auto-deactivated.', 'bc-security'),
PHP_VERSION
)
);
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Admin.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security;

/**
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Core/Admin/AbstractPage.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Core\Admin;

/**
Expand Down
6 changes: 4 additions & 2 deletions classes/BlueChip/Security/Core/Admin/CountablePage.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Core\Admin;

use BlueChip\Security\Modules\Countable;
Expand Down Expand Up @@ -46,9 +48,9 @@ public function getCount(): int
{
$user = wp_get_current_user();

$last_visit_timestamp = get_user_meta($user->ID, $this->getCounterUserMetaKey(), true);
$last_visit_timestamp = absint(get_user_meta($user->ID, $this->getCounterUserMetaKey(), true));

return empty($last_visit_timestamp) ? $this->counter->countAll() : $this->counter->countFrom($last_visit_timestamp);
return $last_visit_timestamp ? $this->counter->countFrom($last_visit_timestamp) : $this->counter->countAll();
}


Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Core/Admin/ListingPage.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Core\Admin;

use BlueChip\Security\Core\ListTable;
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Core/Admin/PageWithAssets.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Core\Admin;

use BlueChip\Security\Core\AssetsManager;
Expand Down
4 changes: 3 additions & 1 deletion classes/BlueChip/Security/Core/Admin/SettingsPage.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Core\Admin;

use BlueChip\Security\Core\Settings;
Expand Down Expand Up @@ -95,7 +97,7 @@ public function setSettingsPage(string $page): void
* @param string $key
* @param mixed $value [optional] Value to use instead of current value of setting with $key.
*
* @return array<string,mixed>
* @return array{label_for:string,key:string,name:string,value:mixed}
*/
protected function getFieldBaseProperties(string $key, $value = null): array
{
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Core/AssetsManager.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Core;

class AssetsManager
Expand Down
4 changes: 3 additions & 1 deletion classes/BlueChip/Security/Core/ListTable.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Core;

use BlueChip\Security\Helpers\AdminNotices;
Expand Down Expand Up @@ -60,7 +62,7 @@ public function __construct(string $url, string $per_page_option_name, array $ar
$this->items_per_page = $this->get_items_per_page($per_page_option_name);

$order_by = \filter_input(INPUT_GET, 'orderby');
if (\in_array($order_by, $this->get_sortable_columns(), true)) {
if (\is_string($order_by) && \in_array($order_by, $this->get_sortable_columns(), true)) {
$this->order_by = $order_by;
$this->url = add_query_arg('orderby', $order_by, $this->url);
}
Expand Down
16 changes: 13 additions & 3 deletions classes/BlueChip/Security/Core/Settings.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Core;

use ArrayAccess;
use ArrayIterator;
use IteratorAggregate;
use Traversable;

/**
* Basis (abstract) class for setting objects.
*
* Every setting object's data are internally stored as single option in `wp_options` table using Settings API.
*
* @link https://developer.wordpress.org/plugins/settings/settings-api/
*
* @phpstan-implements ArrayAccess<string,mixed>
* @phpstan-implements IteratorAggregate<string,mixed>
*/
abstract class Settings implements \ArrayAccess, \IteratorAggregate
abstract class Settings implements ArrayAccess, IteratorAggregate
{
/**
* @var array<string,mixed> Default values for all settings. Descendant classes should override it.
Expand Down Expand Up @@ -124,9 +134,9 @@ public function offsetUnset(mixed $offset): void

//// IteratorAggregate API /////////////////////////////////////////////////

public function getIterator(): \Traversable
public function getIterator(): Traversable
{
return new \ArrayIterator($this->data);
return new ArrayIterator($this->data);
}


Expand Down
29 changes: 19 additions & 10 deletions classes/BlueChip/Security/Helpers/AdminNotices.php
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

/**
* @link https://digwp.com/2016/05/wordpress-admin-notices/
*/
abstract class AdminNotices
{
public const ERROR = 'notice-error';
public const WARNING = 'notice-warning';
public const SUCCESS = 'notice-success';
public const INFO = 'notice-info';
public const ERROR = 'error';
public const WARNING = 'warning';
public const SUCCESS = 'success';
public const INFO = 'info';

/**
* Add dismissible admin notice with given $message of given $type.
*
* @link https://make.wordpress.org/core/2023/10/16/introducing-admin-notice-functions-in-wordpress-6-4/
* @link https://make.wordpress.org/core/2015/04/23/spinners-and-dismissible-admin-notices-in-4-2/
*
* @param string $message Message to display in admin notice.
Expand All @@ -24,11 +27,17 @@ abstract class AdminNotices
*/
public static function add(string $message, string $type = self::INFO, bool $is_dismissible = true, bool $escape_html = true): void
{
$classes = \implode(' ', \array_filter(['notice', $type, $is_dismissible ? 'is-dismissible' : '']));
add_action('admin_notices', function () use ($message, $classes, $escape_html) {
echo '<div class="' . $classes . '">';
echo '<p>' . ($escape_html ? esc_html($message) : $message) . '</p>';
echo '</div>';
});
if (is_wp_version_compatible('6.4')) {
add_action('admin_notices', function () use ($message, $type, $is_dismissible) {
wp_admin_notice($message, ['type' => $type, 'dismissible' => $is_dismissible,]);
});
} else {
$classes = \implode(' ', \array_filter(['notice', 'notice-' . $type, $is_dismissible ? 'is-dismissible' : '']));
add_action('admin_notices', function () use ($message, $classes, $escape_html) {
echo '<div class="' . $classes . '">';
echo '<p>' . ($escape_html ? esc_html($message) : $message) . '</p>';
echo '</div>';
});
}
}
}
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Helpers/AjaxHelper.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

/**
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Helpers/FormHelper.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

abstract class FormHelper
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Helpers/HaveIBeenPwned.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

/**
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Helpers/Hooks.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

/**
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Helpers/IpAddress.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

abstract class IpAddress
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Helpers/Is.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

use WP_User;
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Helpers/MySQLDateTime.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

/**
Expand Down
2 changes: 2 additions & 0 deletions classes/BlueChip/Security/Helpers/Plugin.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace BlueChip\Security\Helpers;

/**
Expand Down
Loading

0 comments on commit 8be2b59

Please sign in to comment.