Automattic / Automattic/jetpack

Brute_Force_Protection: two deprecated static wrappers throw Error on PHP 8 (self:: to non-static methods)

Open Beginner friendly
#51,728 0 comments 0 reactions 0 assignees View on GitHub
Bug Needs triage
Dominant language
PHP
Stars
1.8k
Forks
898
Avg merge
1d 18h
Merged PRs (30d)
774

Description

### Impacted plugin

Jetpack, Protect

### Quick summary

**Two deprecated static wrappers in `Brute_Force_Protection` throw a fatal `Error` on PHP 8.**

In `projects/packages/waf/src/class-brute-force-protection.php`, two `static` methods deprecated in `waf-0.11.0` reach non-static methods through `self::`:

- `ip_is_whitelisted()` calls `self::ip_is_allowed()`, which is declared `public function`
- `is_current_ip_whitelisted()` calls `self::is_current_ip_allowed()`, which is declared `public function`

Both call `_deprecated_function()` first, so the clear intent is that they still work and merely warn. On PHP 8.0+ a static call to a non-static method is a fatal `Error` rather than a notice, so any caller still using the old names gets a crash instead of the deprecation path.

Confirmed present in `trunk` as of 2026-08-28, and in released Jetpack 16.1.2 (`jetpack_vendor/automattic/jetpack-waf/src/class-brute-force-protection.php`, lines 678 and 777).

Suggested fix, routing through the singleton as the rest of the class does:

```php
public static function ip_is_whitelisted( $ip ) {
_deprecated_function( __METHOD__, 'waf-0.11.0', __CLASS__ . '::ip_is_allowed' );
return self::instance()->ip_is_allowed( $ip );
}

public static function is_current_ip_whitelisted() {
_deprecated_function( __METHOD__, 'waf-0.11.0', __CLASS__ . '::is_current_ip_allowed' );
return self::instance()->is_current_ip_allowed();
}
```

Alternatively, remove the wrappers outright if the deprecation window since `waf-0.11.0` is considered closed. Leaving them in a state where they throw is the one outcome that helps nobody.

Found by static analysis while validating a PHP 8.x compatibility scanner against the 20 most-installed plugins on wordpress.org. Happy to open a PR if that's useful.

### Steps to reproduce

On PHP 8.0 or later, with Jetpack active:

1. From anywhere that runs during a request (a mu-plugin is enough), call:
`\Automattic\Jetpack\Waf\Brute_Force_Protection\Brute_Force_Protection::ip_is_whitelisted( '1.2.3.4' );`
2. The request dies with `Uncaught Error: Non-static method ...::ip_is_allowed() cannot be called statically`.
3. Same result for `Brute_Force_Protection::is_current_ip_whitelisted()`.

**Expected:** the call emits the deprecation notice from `_deprecated_function()` and returns the value from the new method, as the `@deprecated` docblocks imply.

**Actual:** fatal `Error` on PHP 8.0+.

Reduced to the essential shape, independent of WordPress:

```php
ip_is_allowed( $ip )` instead of `Brute_Force_Protection::ip_is_whitelisted( $ip )`
- `Brute_Force_Protection::instance()->is_current_ip_allowed()` instead of `Brute_Force_Protection::is_current_ip_whitelisted()`

That only helps people who control the calling code, though. The point of the deprecated wrappers is to cover callers who haven't been updated, and those are exactly the ones that break.

### Platform (Simple and/or Atomic)

_No response_

Contributor guide

Open the contributing guide

Research direction

Start in projects/packages/waf/src/class-brute-force-protection.php and inspect ip_is_whitelisted() and is_current_ip_whitelisted(), along with the corresponding allowed methods and singleton usage. Run the PHP 8.0+ reproduction from the issue; done means both deprecated wrappers emit their deprecation notice and return normally instead of throwing a fatal Error.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend, security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.