diff --git a/CHANGELOG.md b/CHANGELOG.md index fc13de9..0e8b1f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # BC Security Changelog +## Version 0.24.0 (2024-07-29) + +WordPress 6.4 or newer is now required! + +### Added + +* Disable autoloading of plugin options when plugin is deactivated [#160](https://github.com/chesio/bc-security/issues/160). +* New built-in rule for bad request banner module that triggers when non-existing `.asp` or `.aspx` file is accessed [#161](https://github.com/chesio/bc-security/issues/161). +* Plugin has been tested with WordPress 6.6 [#157](https://github.com/chesio/bc-security/issues/157). + +### Changed + +* WordPress 6.4 is required [#159](https://github.com/chesio/bc-security/issues/159). + ## Version 0.23.0 (2024-04-04) **Important**: either deactivate and reactivate plugin after update or install new cron job manually via WP-CLI: `wp cron event schedule bc-security/failed-logins-clean-up now daily`. diff --git a/README.md b/README.md index caeb137..c7c9890 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A WordPress plugin that helps keeping WordPress websites secure. ## Requirements * [PHP](https://www.php.net/) 8.1 or newer -* [WordPress](https://wordpress.org/) 6.2 or newer +* [WordPress](https://wordpress.org/) 6.4 or newer ## Limitations @@ -144,11 +144,12 @@ Passwords are validated on user creation, password change or password reset. If 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 four 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 non-existent archive file is requested (any URL ending with `.tgz` or `.zip`) -3. ban when non-existent backup file is requested (any URL targeting file with `backup` in basename or with `.back`, `.old` or `.tmp` extension) -4. ban when non-existent `readme.txt` file is accessed +There are five built-in rules available (they are not active by default): +1. ban when non-existent APS file is requested (any URL ending with `.asp` or `.aspx`) +2. ban when non-existent PHP file is requested (any URL ending with `.php`) +3. ban when non-existent archive file is requested (any URL ending with `.tgz` or `.zip`) +4. ban when non-existent backup file is requested (any URL targeting file with `backup` in basename or with `.back`, `.old` or `.tmp` extension) +5. ban when non-existent `readme.txt` file is accessed You may define custom rules as well (in form of regular expression). diff --git a/bc-security.php b/bc-security.php index 5f0e26d..3bf8336 100644 --- a/bc-security.php +++ b/bc-security.php @@ -4,12 +4,12 @@ * Plugin Name: BC Security * Plugin URI: https://github.com/chesio/bc-security * Description: Helps keeping WordPress websites secure. - * Version: 0.23.0 + * Version: 0.24.0 * Author: Česlav Przywara * Author URI: https://www.chesio.com * Requires PHP: 8.1 - * Requires at least: 6.2 - * Tested up to: 6.5 + * Requires at least: 6.4 + * Tested up to: 6.6 * Text Domain: bc-security * GitHub Plugin URI: https://github.com/chesio/bc-security * Update URI: https://github.com/chesio/bc-security diff --git a/classes/BlueChip/Security/Core/Admin/SettingsPage.php b/classes/BlueChip/Security/Core/Admin/SettingsPage.php index c6cea12..5e2057a 100644 --- a/classes/BlueChip/Security/Core/Admin/SettingsPage.php +++ b/classes/BlueChip/Security/Core/Admin/SettingsPage.php @@ -63,7 +63,15 @@ public function displaySettingsErrors(): void */ public function registerSettings(): void { - register_setting($this->option_group, $this->option_name, [$this->settings, 'sanitize']); + register_setting( + $this->option_group, + $this->option_name, + [ + 'type' => 'array', + 'sanitize_callback' => $this->settings->sanitize(...), + 'default' => $this->settings->getDefaultValue(), + ] + ); } @@ -105,7 +113,7 @@ protected function getFieldBaseProperties(string $key, $value = null): array 'label_for' => \sprintf('%s-%s', $this->option_name, $key), // "label_for" is WP reserved name 'key' => $key, 'name' => \sprintf('%s[%s]', $this->option_name, $key), - 'value' => null === $value ? $this->settings[$key] : $value, + 'value' => $value ?? $this->settings[$key], ]; } diff --git a/classes/BlueChip/Security/Core/Settings.php b/classes/BlueChip/Security/Core/Settings.php index 416cae4..7d428e9 100644 --- a/classes/BlueChip/Security/Core/Settings.php +++ b/classes/BlueChip/Security/Core/Settings.php @@ -5,9 +5,6 @@ namespace BlueChip\Security\Core; use ArrayAccess; -use ArrayIterator; -use IteratorAggregate; -use Traversable; /** * Basis (abstract) class for setting objects. @@ -17,9 +14,8 @@ * @link https://developer.wordpress.org/plugins/settings/settings-api/ * * @phpstan-implements ArrayAccess - * @phpstan-implements IteratorAggregate */ -abstract class Settings implements ArrayAccess, IteratorAggregate +abstract class Settings implements ArrayAccess { /** * @var array Default values for all settings. Descendant classes should override it. @@ -35,7 +31,7 @@ abstract class Settings implements ArrayAccess, IteratorAggregate /** * @var array Settings data (kind of cache for get_option() result). */ - protected array $data; + private array $data; /** @@ -48,40 +44,6 @@ public function __construct(private string $option_name) } - /** - * Get value of setting under key $name. - * - * @param string $name - * - * @return mixed A null value is returned if $name is not a valid key. - */ - public function __get(string $name): mixed - { - if (isset($this->data[$name])) { - return $this->data[$name]; - } else { - _doing_it_wrong(__METHOD__, \sprintf('Unknown settings key "%s"', $name), '0.1.0'); - return null; - } - } - - - /** - * Set value of setting under key $name to $value. - * - * @param string $name - * @param mixed $value - */ - public function __set(string $name, mixed $value): void - { - if (isset($this->data[$name])) { - $this->update($name, $value); - } else { - _doing_it_wrong(__METHOD__, \sprintf('Unknown settings key "%s"', $name), '0.1.0'); - } - } - - //// ArrayAccess API /////////////////////////////////////////////////////// /** @@ -91,7 +53,7 @@ public function __set(string $name, mixed $value): void */ public function offsetExists(mixed $offset): bool { - return isset($this->data[$offset]); + return $this->offsetGet($offset) !== null; } @@ -106,7 +68,7 @@ public function offsetExists(mixed $offset): bool */ public function offsetGet(mixed $offset): mixed { - return isset($this->data[$offset]) ? $this->data[$offset] : null; + return $this->data[$offset] ?? null; } @@ -117,7 +79,23 @@ public function offsetGet(mixed $offset): mixed */ public function offsetSet(mixed $offset, mixed $value): void { - $this->update($offset, $value); + $data = $this->get(); + + if (!isset($data[$offset])) { + // Cannot update, invalid setting name. + return; + } + + if (null === $value) { + // Null value unsets (resets) setting to default state + unset($data[$offset]); + } else { + // Any other value updates it + $data[$offset] = $value; + } + + // Use set() here to have the data sanitized properly. + $this->set($data); } @@ -128,15 +106,20 @@ public function offsetSet(mixed $offset, mixed $value): void */ public function offsetUnset(mixed $offset): void { - $this->update($offset, null); + $this->offsetSet($offset, null); } - //// IteratorAggregate API ///////////////////////////////////////////////// + //// Public API //////////////////////////////////////////////////////////// - public function getIterator(): Traversable + /** + * Get default value for settings. + * + * @return array + */ + public function getDefaultValue(): array { - return new ArrayIterator($this->data); + return static::DEFAULTS; } @@ -163,7 +146,7 @@ public function get(): array /** - * Set $data as option data. + * Sanitize $data and set them as option value. * * @param array $data * @@ -171,20 +154,27 @@ public function get(): array */ public function set(array $data): bool { - $this->data = $this->sanitize($data); - return $this->persist(); + return $this->persist($this->sanitize($data)); } /** - * Reset option data. + * Reset option data to default values. * * @return bool */ public function reset(): bool { - $this->data = static::DEFAULTS; - return $this->persist(); + return $this->persist(static::DEFAULTS); + } + + + /** + * Set autoload value of underlying option to $autoload. + */ + public function setAutoload(bool $autoload): bool + { + return wp_set_option_autoload($this->option_name, $autoload); } @@ -200,16 +190,26 @@ public function destroy(): bool /** - * Persist the value of data into database. + * Set the value of $data into local cache and also persist it in database. + * + * @internal This function does no sanitization and thus is private - use set() or reset() in external code. + * + * @param array $data Sanitized (!) data to persist. * * @return bool True if settings have been updated (= changed), false otherwise. */ - public function persist(): bool + private function persist(array $data): bool { + // Update local cache. + $this->data = $data; + + // Persist new data. return update_option($this->option_name, $this->data); } + //// Sanitization ////////////////////////////////////////////////////////// + /** * Sanitize $settings array: only keep known keys, provide default values for missing keys. * @@ -228,7 +228,7 @@ public function persist(): bool public function sanitize(array $settings, array $defaults = []): array { // If no default values are provided, use data from internal cache as default values. - $values = ($defaults === []) ? $this->data : $defaults; + $values = ($defaults === []) ? $this->get() : $defaults; // Loop over default values instead of provided $settings - this way only known keys are preserved. foreach ($values as $key => $default_value) { @@ -258,7 +258,7 @@ public function sanitize(array $settings, array $defaults = []): array * * @return mixed[]|bool|float|int|string */ - protected static function sanitizeByType(mixed $value, array|bool|float|int|string $default): array|bool|float|int|string + private static function sanitizeByType(mixed $value, array|bool|float|int|string $default): array|bool|float|int|string { if (\is_bool($default)) { return (bool) $value; @@ -281,43 +281,13 @@ protected static function sanitizeByType(mixed $value, array|bool|float|int|stri * * @return string[] */ - protected static function parseList(array|string $list): array + private static function parseList(array|string $list): array { return \is_array($list) ? $list : \array_filter(\array_map('trim', \explode(PHP_EOL, $list))); } - /** - * Update setting under $name with $value. Store update values in DB. - * - * @param string $name - * @param mixed $value - * - * @return bool - */ - public function update(string $name, mixed $value): bool - { - if (!isset($this->data[$name])) { - // Cannot update, invalid setting name. - return false; - } - - $data = $this->data; - - if (null === $value) { - // Null value unsets (resets) setting to default state - unset($data[$name]); - } else { - // Any other value updates it - $data[$name] = $value; - } - - // Sanitize new value and update cache. - $this->data = $this->sanitize($data); - // Make changes permanent. - return $this->persist(); - } - + //// Update hook callback ////////////////////////////////////////////////// /** * Execute provided $callback as soon as settings are updated and persisted. diff --git a/classes/BlueChip/Security/Helpers/Is.php b/classes/BlueChip/Security/Helpers/Is.php index 8da23f1..093df91 100644 --- a/classes/BlueChip/Security/Helpers/Is.php +++ b/classes/BlueChip/Security/Helpers/Is.php @@ -65,7 +65,7 @@ public static function request(string $type): bool case 'frontend': return (!is_admin() || wp_doing_ajax()) && !wp_doing_cron(); case 'wp-cli': - return \defined('WP_CLI') && WP_CLI; + return \defined('WP_CLI') && \constant('WP_CLI'); default: _doing_it_wrong(__METHOD__, \sprintf('Unknown request type: %s', $type), '0.1.0'); return false; diff --git a/classes/BlueChip/Security/Modules/BadRequestsBanner/BuiltInRules.php b/classes/BlueChip/Security/Modules/BadRequestsBanner/BuiltInRules.php index 9177cf8..a533717 100644 --- a/classes/BlueChip/Security/Modules/BadRequestsBanner/BuiltInRules.php +++ b/classes/BlueChip/Security/Modules/BadRequestsBanner/BuiltInRules.php @@ -10,6 +10,10 @@ abstract class BuiltInRules private const ARCHIVE_FILES_PATTERN = '\.(tgz|zip)$'; + public const ASP_FILES = 'asp-files'; + + private const ASP_FILES_PATTERN = '\.aspx?$'; + public const BACKUP_FILES = 'backup-files'; private const BACKUP_FILES_PATTERN = 'backup|(\.(back|old|tmp)$)'; @@ -28,6 +32,11 @@ abstract class BuiltInRules public static function enlist(): array { return [ + self::ASP_FILES => new BanRule( + __('Non-existent ASP files', 'bc-security'), + self::ASP_FILES_PATTERN, + __('(any URI targeting file with .asp or .aspx extension)', 'bc-security') + ), self::PHP_FILES => new BanRule( __('Non-existent PHP files', 'bc-security'), self::PHP_FILES_PATTERN, diff --git a/classes/BlueChip/Security/Modules/BadRequestsBanner/Settings.php b/classes/BlueChip/Security/Modules/BadRequestsBanner/Settings.php index 5383e48..1ca0e79 100644 --- a/classes/BlueChip/Security/Modules/BadRequestsBanner/Settings.php +++ b/classes/BlueChip/Security/Modules/BadRequestsBanner/Settings.php @@ -13,6 +13,11 @@ class Settings extends CoreSettings */ public const BUILT_IN_RULE_ARCHIVE_FILES = BuiltInRules::ARCHIVE_FILES; + /** + * @var string Is built-in rule "ASP files" active? [bool:no] + */ + public const BUILT_IN_RULE_ASP_FILES = BuiltInRules::ASP_FILES; + /** * @var string Is built-in rule "Backup files" active? [bool:no] */ @@ -50,6 +55,7 @@ class Settings extends CoreSettings */ protected const DEFAULTS = [ self::BUILT_IN_RULE_ARCHIVE_FILES => false, + self::BUILT_IN_RULE_ASP_FILES => false, self::BUILT_IN_RULE_BACKUP_FILES => false, self::BUILT_IN_RULE_PHP_FILES => false, self::BUILT_IN_RULE_README_FILES => false, @@ -67,7 +73,7 @@ public function getActiveBanRules(): array // Fill built in rules first. foreach (BuiltInRules::enlist() as $identifier => $ban_rule) { - if ($this->data[$identifier]) { + if ($this[$identifier]) { $ban_rules[] = $ban_rule; } } @@ -86,7 +92,7 @@ public function getActiveBanRules(): array */ public function getBanDuration(): int { - return $this->data[self::BAN_DURATION] * MINUTE_IN_SECONDS; + return $this[self::BAN_DURATION] * MINUTE_IN_SECONDS; } @@ -97,7 +103,7 @@ private function getBadRequestPatterns(): array { return apply_filters( Hooks::BAD_REQUEST_CUSTOM_PATTERNS, - $this->removeComments($this->data[self::BAD_REQUEST_PATTERNS]) + $this->removeComments($this[self::BAD_REQUEST_PATTERNS]) ); } diff --git a/classes/BlueChip/Security/Modules/ExternalBlocklist/Settings.php b/classes/BlueChip/Security/Modules/ExternalBlocklist/Settings.php index e946a00..9422141 100644 --- a/classes/BlueChip/Security/Modules/ExternalBlocklist/Settings.php +++ b/classes/BlueChip/Security/Modules/ExternalBlocklist/Settings.php @@ -46,7 +46,7 @@ public function isEnabled(string $class): bool public function getAccessScope(string $class): ?Scope { - $value = $this->data[$class] ?? null; + $value = $this[$class]; return \is_int($value) ? Scope::tryFrom($value) : null; } } diff --git a/classes/BlueChip/Security/Modules/Log/Settings.php b/classes/BlueChip/Security/Modules/Log/Settings.php index 21f83ef..18ce80b 100644 --- a/classes/BlueChip/Security/Modules/Log/Settings.php +++ b/classes/BlueChip/Security/Modules/Log/Settings.php @@ -36,7 +36,7 @@ class Settings extends CoreSettings */ public function getMaxAge(): int { - return $this->data[self::LOG_MAX_AGE] * DAY_IN_SECONDS; + return $this[self::LOG_MAX_AGE] * DAY_IN_SECONDS; } @@ -45,6 +45,6 @@ public function getMaxAge(): int */ public function getMaxSize(): int { - return $this->data[self::LOG_MAX_SIZE] * 1000; + return $this[self::LOG_MAX_SIZE] * 1000; } } diff --git a/classes/BlueChip/Security/Modules/Login/Settings.php b/classes/BlueChip/Security/Modules/Login/Settings.php index 6d68e88..ce2c63f 100644 --- a/classes/BlueChip/Security/Modules/Login/Settings.php +++ b/classes/BlueChip/Security/Modules/Login/Settings.php @@ -86,7 +86,7 @@ public static function sanitizeUsernameBlacklist(array $value): array */ public function getLongLockoutDuration(): int { - return $this->data[self::LONG_LOCKOUT_DURATION] * HOUR_IN_SECONDS; + return $this[self::LONG_LOCKOUT_DURATION] * HOUR_IN_SECONDS; } @@ -95,7 +95,7 @@ public function getLongLockoutDuration(): int */ public function getResetTimeoutDuration(): int { - return $this->data[self::RESET_TIMEOUT] * DAY_IN_SECONDS; + return $this[self::RESET_TIMEOUT] * DAY_IN_SECONDS; } @@ -104,7 +104,7 @@ public function getResetTimeoutDuration(): int */ public function getShortLockoutDuration(): int { - return $this->data[self::SHORT_LOCKOUT_DURATION] * MINUTE_IN_SECONDS; + return $this[self::SHORT_LOCKOUT_DURATION] * MINUTE_IN_SECONDS; } @@ -117,6 +117,6 @@ public function getShortLockoutDuration(): int */ public function getUsernameBlacklist(): array { - return apply_filters(Hooks::USERNAME_BLACKLIST, $this->data[self::USERNAME_BLACKLIST]); + return apply_filters(Hooks::USERNAME_BLACKLIST, $this[self::USERNAME_BLACKLIST]); } } diff --git a/classes/BlueChip/Security/Plugin.php b/classes/BlueChip/Security/Plugin.php index 362abfd..c977b1d 100644 --- a/classes/BlueChip/Security/Plugin.php +++ b/classes/BlueChip/Security/Plugin.php @@ -106,7 +106,7 @@ private function init(): void } } - if (is_admin()) { + if (is_admin() && !wp_doing_ajax()) { $assets_manager = new Core\AssetsManager($this->plugin_filename); // Initialize admin interface (set necessary hooks). @@ -161,9 +161,9 @@ private function init(): void */ public function activate(): void { - // Explicitly persist every setting object, so related option is autoloaded. + // Make sure plugin related options are autoloaded when plugin is active. foreach ($this->settings as $settings) { - $settings->persist(); + $settings->setAutoload(true); } // Install every module that requires it. @@ -196,6 +196,11 @@ public function deactivate(): void $module->deactivate(); } } + + // Make sure plugin related options are *not* autoloaded when plugin is inactive. + foreach ($this->settings as $settings) { + $settings->setAutoload(false); + } } diff --git a/composer.lock b/composer.lock index b8cca25..90e13b9 100644 --- a/composer.lock +++ b/composer.lock @@ -402,16 +402,16 @@ }, { "name": "mockery/mockery", - "version": "1.6.7", + "version": "1.6.11", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06" + "reference": "81a161d0b135df89951abd52296adf97deb0723d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", - "reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", + "url": "https://api.github.com/repos/mockery/mockery/zipball/81a161d0b135df89951abd52296adf97deb0723d", + "reference": "81a161d0b135df89951abd52296adf97deb0723d", "shasum": "" }, "require": { @@ -423,8 +423,8 @@ "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.10", - "symplify/easy-coding-standard": "^12.0.8" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", "autoload": { @@ -481,20 +481,20 @@ "security": "https://github.com/mockery/mockery/security/advisories", "source": "https://github.com/mockery/mockery" }, - "time": "2023-12-10T02:24:34+00:00" + "time": "2024-03-21T18:34:15+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -502,11 +502,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -532,7 +533,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -540,20 +541,20 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", - "version": "v5.0.2", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", "shasum": "" }, "require": { @@ -564,7 +565,7 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -596,9 +597,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" }, - "time": "2024-03-05T20:51:40+00:00" + "time": "2024-07-01T20:03:41+00:00" }, { "name": "phar-io/manifest", @@ -720,16 +721,16 @@ }, { "name": "php-parallel-lint/php-parallel-lint", - "version": "v1.3.2", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/php-parallel-lint/PHP-Parallel-Lint.git", - "reference": "6483c9832e71973ed29cf71bd6b3f4fde438a9de" + "reference": "6db563514f27e19595a19f45a4bf757b6401194e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/6483c9832e71973ed29cf71bd6b3f4fde438a9de", - "reference": "6483c9832e71973ed29cf71bd6b3f4fde438a9de", + "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/6db563514f27e19595a19f45a4bf757b6401194e", + "reference": "6db563514f27e19595a19f45a4bf757b6401194e", "shasum": "" }, "require": { @@ -767,37 +768,42 @@ "email": "ahoj@jakubonderka.cz" } ], - "description": "This tool check syntax of PHP files about 20x faster than serial check.", + "description": "This tool checks the syntax of PHP files about 20x faster than serial check.", "homepage": "https://github.com/php-parallel-lint/PHP-Parallel-Lint", + "keywords": [ + "lint", + "static analysis" + ], "support": { "issues": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/issues", - "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.3.2" + "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.4.0" }, - "time": "2022-02-21T12:50:22+00:00" + "time": "2024-03-27T12:14:49+00:00" }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.4.3", + "version": "v6.6.0", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "6105bdab2f26c0204fe90ecc53d5684754550e8f" + "reference": "86e8753e89d59849276dcdd91b9a7dd78bb4abe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/6105bdab2f26c0204fe90ecc53d5684754550e8f", - "reference": "6105bdab2f26c0204fe90ecc53d5684754550e8f", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/86e8753e89d59849276dcdd91b9a7dd78bb4abe2", + "reference": "86e8753e89d59849276dcdd91b9a7dd78bb4abe2", "shasum": "" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "nikic/php-parser": "^4.13", - "php": "^7.4 || ~8.0.0", + "php": "^7.4 || ^8.0", "php-stubs/generator": "^0.8.3", - "phpdocumentor/reflection-docblock": "^5.3", + "phpdocumentor/reflection-docblock": "^5.4.1", "phpstan/phpstan": "^1.10.49", "phpunit/phpunit": "^9.5", - "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^0.11" + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.0", + "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" }, "suggest": { "paragonie/sodium_compat": "Pure PHP implementation of libsodium", @@ -818,9 +824,9 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.4.3" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.6.0" }, - "time": "2024-02-11T18:56:19+00:00" + "time": "2024-07-17T08:50:38+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -871,16 +877,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.59", + "version": "1.11.8", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e607609388d3a6d418a50a49f7940e8086798281" + "reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e607609388d3a6d418a50a49f7940e8086798281", - "reference": "e607609388d3a6d418a50a49f7940e8086798281", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", + "reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", "shasum": "" }, "require": { @@ -923,26 +929,22 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2024-02-20T13:59:13+00:00" + "time": "2024-07-24T07:01:22+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "10.1.14", + "version": "10.1.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b" + "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e3f51450ebffe8e0efdf7346ae966a656f7d5e5b", - "reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", + "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", "shasum": "" }, "require": { @@ -999,7 +1001,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.14" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.15" }, "funding": [ { @@ -1007,7 +1009,7 @@ "type": "github" } ], - "time": "2024-03-12T15:33:41+00:00" + "time": "2024-06-29T08:25:15+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1254,16 +1256,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.13", + "version": "10.5.28", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7" + "reference": "ff7fb85cdf88131b83e721fb2a327b664dbed275" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/20a63fc1c6db29b15da3bd02d4b6cf59900088a7", - "reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ff7fb85cdf88131b83e721fb2a327b664dbed275", + "reference": "ff7fb85cdf88131b83e721fb2a327b664dbed275", "shasum": "" }, "require": { @@ -1273,26 +1275,26 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.5", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-invoker": "^4.0", - "phpunit/php-text-template": "^3.0", - "phpunit/php-timer": "^6.0", - "sebastian/cli-parser": "^2.0", - "sebastian/code-unit": "^2.0", - "sebastian/comparator": "^5.0", - "sebastian/diff": "^5.0", - "sebastian/environment": "^6.0", - "sebastian/exporter": "^5.1", - "sebastian/global-state": "^6.0.1", - "sebastian/object-enumerator": "^5.0", - "sebastian/recursion-context": "^5.0", - "sebastian/type": "^4.0", - "sebastian/version": "^4.0" + "phpunit/php-code-coverage": "^10.1.15", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.1", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -1335,7 +1337,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.13" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.28" }, "funding": [ { @@ -1351,7 +1353,7 @@ "type": "tidelift" } ], - "time": "2024-03-12T15:37:41+00:00" + "time": "2024-07-18T14:54:16+00:00" }, { "name": "sebastian/cli-parser", @@ -1725,16 +1727,16 @@ }, { "name": "sebastian/environment", - "version": "6.0.1", + "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", - "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { @@ -1749,7 +1751,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -1777,7 +1779,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { @@ -1785,7 +1787,7 @@ "type": "github" } ], - "time": "2023-04-11T05:39:26+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { "name": "sebastian/exporter", @@ -2336,16 +2338,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.9.0", + "version": "3.10.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b" + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/d63cee4890a8afaf86a22e51ad4d97c91dd4579b", - "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017", "shasum": "" }, "require": { @@ -2412,20 +2414,20 @@ "type": "open_collective" } ], - "time": "2024-02-16T15:06:51+00:00" + "time": "2024-07-21T23:26:44+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/ec444d3f3f6505bb28d11afa41e75faadebc10a1", + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1", "shasum": "" }, "require": { @@ -2472,7 +2474,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.30.0" }, "funding": [ { @@ -2488,20 +2490,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "szepeviktor/phpstan-wordpress", - "version": "v1.3.3", + "version": "v1.3.5", "source": { "type": "git", "url": "https://github.com/szepeviktor/phpstan-wordpress.git", - "reference": "f7ff091331bc00c5688fe4ce0c4d51d06fa61553" + "reference": "7f8cfe992faa96b6a33bbd75c7bace98864161e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/szepeviktor/phpstan-wordpress/zipball/f7ff091331bc00c5688fe4ce0c4d51d06fa61553", - "reference": "f7ff091331bc00c5688fe4ce0c4d51d06fa61553", + "url": "https://api.github.com/repos/szepeviktor/phpstan-wordpress/zipball/7f8cfe992faa96b6a33bbd75c7bace98864161e7", + "reference": "7f8cfe992faa96b6a33bbd75c7bace98864161e7", "shasum": "" }, "require": { @@ -2516,7 +2518,8 @@ "php-parallel-lint/php-parallel-lint": "^1.1", "phpstan/phpstan-strict-rules": "^1.2", "phpunit/phpunit": "^8.0 || ^9.0", - "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^0.8" + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.0", + "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" }, "suggest": { "swissspidy/phpstan-no-private": "Detect usage of internal core functions, classes and methods" @@ -2548,9 +2551,9 @@ ], "support": { "issues": "https://github.com/szepeviktor/phpstan-wordpress/issues", - "source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v1.3.3" + "source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v1.3.5" }, - "time": "2024-02-26T13:55:50+00:00" + "time": "2024-06-28T22:27:19+00:00" }, { "name": "theseer/tokenizer", @@ -2604,16 +2607,16 @@ }, { "name": "yoast/phpunit-polyfills", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", - "reference": "c758753e8f9dac251fed396a73c8305af3f17922" + "reference": "4a088f125c970d6d6ea52c927f96fe39b330d0f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/c758753e8f9dac251fed396a73c8305af3f17922", - "reference": "c758753e8f9dac251fed396a73c8305af3f17922", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/4a088f125c970d6d6ea52c927f96fe39b330d0f1", + "reference": "4a088f125c970d6d6ea52c927f96fe39b330d0f1", "shasum": "" }, "require": { @@ -2621,7 +2624,9 @@ "phpunit/phpunit": "^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0" }, "require-dev": { - "yoast/yoastcs": "^2.3.0" + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "yoast/yoastcs": "^3.1.0" }, "type": "library", "extra": { @@ -2658,9 +2663,10 @@ ], "support": { "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", + "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy", "source": "https://github.com/Yoast/PHPUnit-Polyfills" }, - "time": "2023-06-06T20:28:24+00:00" + "time": "2024-04-05T16:36:44+00:00" } ], "aliases": [], diff --git a/tests/integration/src/Cases/Helpers/HaveIBeenPwnedTest.php b/tests/integration/src/Cases/Helpers/HaveIBeenPwnedTest.php index 5d7bd05..77e9163 100644 --- a/tests/integration/src/Cases/Helpers/HaveIBeenPwnedTest.php +++ b/tests/integration/src/Cases/Helpers/HaveIBeenPwnedTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace BlueChip\Security\Tests\Unit\Cases\Helpers; +namespace BlueChip\Security\Tests\Integration\Cases\Helpers; use BlueChip\Security\Helpers\HaveIBeenPwned; use BlueChip\Security\Tests\Integration\Constants; diff --git a/tests/integration/src/Cases/Modules/ExternalBlocklist/ManagerTest.php b/tests/integration/src/Cases/Modules/ExternalBlocklist/ManagerTest.php index f0c5fed..9ea30bd 100644 --- a/tests/integration/src/Cases/Modules/ExternalBlocklist/ManagerTest.php +++ b/tests/integration/src/Cases/Modules/ExternalBlocklist/ManagerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace BlueChip\Security\Tests\Unit\Cases\Modules\ExternalBlocklist; +namespace BlueChip\Security\Tests\Integration\Cases\Modules\ExternalBlocklist; use BlueChip\Security\Modules\Access\Scope; use BlueChip\Security\Modules\Cron\Jobs; diff --git a/tests/static-analysis/bootstrap.php b/tests/static-analysis/bootstrap.php index 920b32c..568373b 100644 --- a/tests/static-analysis/bootstrap.php +++ b/tests/static-analysis/bootstrap.php @@ -1,7 +1,6 @@ true, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => false, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -26,6 +27,7 @@ public static function provideUris(): array 'website-backup.zip', [ BuiltInRules::ARCHIVE_FILES => true, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => true, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -35,6 +37,7 @@ public static function provideUris(): array 'wp-config.php.back', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => true, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -44,6 +47,7 @@ public static function provideUris(): array 'script.php.old', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => true, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -53,6 +57,7 @@ public static function provideUris(): array 'some/important/file.tmp', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => true, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -62,6 +67,7 @@ public static function provideUris(): array 'wp-content/theme/dummy/styles.css', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => false, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -71,6 +77,7 @@ public static function provideUris(): array 'plugin/non-existent/image.png', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => false, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -80,6 +87,27 @@ public static function provideUris(): array 'wp-content/themes/dummy/script.js', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, + BuiltInRules::BACKUP_FILES => false, + BuiltInRules::PHP_FILES => false, + BuiltInRules::README_FILES => false, + ], + ], + 'ASP file' => [ + 'backend.asp', + [ + BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => true, + BuiltInRules::BACKUP_FILES => false, + BuiltInRules::PHP_FILES => false, + BuiltInRules::README_FILES => false, + ], + ], + 'ASPx file' => [ + 'login.aspx', + [ + BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => true, BuiltInRules::BACKUP_FILES => false, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -89,6 +117,7 @@ public static function provideUris(): array '_wp-config.php', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => false, BuiltInRules::PHP_FILES => true, BuiltInRules::README_FILES => false, @@ -98,6 +127,7 @@ public static function provideUris(): array 'humans.txt', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => false, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => false, @@ -107,6 +137,7 @@ public static function provideUris(): array 'wp-content/plugins/some-plugin/readme.txt', [ BuiltInRules::ARCHIVE_FILES => false, + BuiltInRules::ASP_FILES => false, BuiltInRules::BACKUP_FILES => false, BuiltInRules::PHP_FILES => false, BuiltInRules::README_FILES => true,