Audit #17 Benign
Show full summary
Suspect-shape but structurally unreachable — benign with one regression to flag. YARPP's version_info() matches the high-confidence catalog IOC unserialize_after_remote_call (@unserialize of wp_remote_post body, hardcoded endpoint, sslverify => false, no signature). The exact same shape that made content-egg's Admitad chain a 7-year latent RCE (audit #15). However, two independent failures make the chain dead code today: (1) the type-gate above the unserialize is always-true, blocking the call, and (2) the live yarpp.org/checkversion.php endpoint returns inert HTML rather than serialized PHP. The author is real and the domain is theirs. No active risk; one defensive regression worth flagging to the author.
Audit retained for the record. No action required.
Plugins under the same committer's SVN access
jeffparker holds push access to 1 plugin totalling 100k+ active installs.
Plugin version history
Every release on wp.org for this plugin, color-coded by relationship to the incident. The compromise window shows where the wp.org Plugin Review Team deleted the malicious tags from SVN — those versions cannot be re-downloaded today.
-
1.0Last clean Last clean release before incident -
1.0.1PRT cleanup PRT cleanup release — incident closed -
1.1Clean Clean (post-cleanup) -
1.5Clean Clean (post-cleanup) -
1.5.1Clean Clean (post-cleanup) -
2.0.3Clean Clean (post-cleanup) -
2.0.2Clean Clean (post-cleanup) -
2.0.1Clean Clean (post-cleanup) -
2.0Clean Clean (post-cleanup) -
2.0.4Clean Clean (post-cleanup) -
2.0.5Clean Clean (post-cleanup) -
2.0.6Clean Clean (post-cleanup) -
2.1Clean Clean (post-cleanup) -
2.1.1Clean Clean (post-cleanup) -
2.1.2Clean Clean (post-cleanup) -
2.1.3Clean Clean (post-cleanup) -
2.1.4Clean Clean (post-cleanup) -
2.1.5Clean Clean (post-cleanup) -
3.0b1Clean Clean (post-cleanup) -
3.0b2Clean Clean (post-cleanup) -
3.0b3Clean Clean (post-cleanup) -
3.0b4Clean Clean (post-cleanup) -
3.0b5Clean Clean (post-cleanup) -
3.0b6Clean Clean (post-cleanup) -
3.0b7Clean Clean (post-cleanup) -
2.1.6Clean Clean (post-cleanup) -
3.0.1Clean Clean (post-cleanup) -
3.0.2Clean Clean (post-cleanup) -
3.0.3Clean Clean (post-cleanup) -
3.0.4Clean Clean (post-cleanup) -
3.0.5Clean Clean (post-cleanup) -
3.0.6Clean Clean (post-cleanup) -
3.0.7b1Clean Clean (post-cleanup) -
3.0.7b2Clean Clean (post-cleanup) -
3.0.7Clean Clean (post-cleanup) -
3.0.8b1Clean Clean (post-cleanup) -
3.0.8b2Clean Clean (post-cleanup) -
3.0.8b3Clean Clean (post-cleanup) -
3.0.8b4Clean Clean (post-cleanup) -
3.0.8Clean Clean (post-cleanup) -
3.0.9Clean Clean (post-cleanup) -
3.0.10Clean Clean (post-cleanup) -
3.0.11Clean Clean (post-cleanup) -
3.0.12Clean Clean (post-cleanup) -
3.0.13Clean Clean (post-cleanup) -
3.0.14b1Clean Clean (post-cleanup) -
3.1b1Clean Clean (post-cleanup) -
3.1Clean Clean (post-cleanup) -
3.1.1Clean Clean (post-cleanup) -
3.1.2b1Clean Clean (post-cleanup) -
3.1.2Clean Clean (post-cleanup) -
3.1.3b1Clean Clean (post-cleanup) -
3.1.3b2Clean Clean (post-cleanup) -
3.1.3b3Clean Clean (post-cleanup) -
3.1.3Clean Clean (post-cleanup) -
3.1.4b2Clean Clean (post-cleanup) -
3.1.4b3Clean Clean (post-cleanup) -
3.1.4b4Clean Clean (post-cleanup) -
3.1.4Clean Clean (post-cleanup) -
3.1.5Clean Clean (post-cleanup) -
3.1.6Clean Clean (post-cleanup) -
3.1.7Clean Clean (post-cleanup) -
3.1.8Clean Clean (post-cleanup) -
3.1.9Clean Clean (post-cleanup) -
3.2b1Clean Clean (post-cleanup) -
3.2b2Clean Clean (post-cleanup) -
3.3Clean Clean (post-cleanup) -
3.3.1Clean Clean (post-cleanup) -
3.3.2Clean Clean (post-cleanup) -
3.3.3b1Clean Clean (post-cleanup) -
3.3.3b2Clean Clean (post-cleanup) -
3.3.3Clean Clean (post-cleanup) -
3.4b2Clean Clean (post-cleanup) -
3.4b3Clean Clean (post-cleanup) -
3.4b4Clean Clean (post-cleanup) -
3.4b5Clean Clean (post-cleanup) -
3.4b6Clean Clean (post-cleanup) -
3.4b7Clean Clean (post-cleanup) -
3.4b8Clean Clean (post-cleanup) -
3.4b9Clean Clean (post-cleanup) -
3.4b10Clean Clean (post-cleanup) -
3.4RC1Clean Clean (post-cleanup) -
3.4Clean Clean (post-cleanup) -
3.4.1b1Clean Clean (post-cleanup) -
3.4.1b2Clean Clean (post-cleanup) -
3.4.1b3Clean Clean (post-cleanup) -
3.4.1b4Clean Clean (post-cleanup) -
3.4.1b5Clean Clean (post-cleanup) -
3.4.1Clean Clean (post-cleanup) -
3.4.2b1Clean Clean (post-cleanup) -
3.4.3b1Clean Clean (post-cleanup) -
3.4.3b2Clean Clean (post-cleanup) -
3.4.3b3Clean Clean (post-cleanup) -
3.4.3Clean Clean (post-cleanup) -
3.4.4b1Clean Clean (post-cleanup) -
3.4.4b2Clean Clean (post-cleanup) -
3.4.4b3Clean Clean (post-cleanup) -
3.4.2Clean Clean (post-cleanup) -
3.4.4b4Clean Clean (post-cleanup) -
3.5b4Clean Clean (post-cleanup) -
3.5b5Clean Clean (post-cleanup) -
3.5Clean Clean (post-cleanup) -
3.5.1b1Clean Clean (post-cleanup) -
3.5.2b1Clean Clean (post-cleanup) -
3.5.1Clean Clean (post-cleanup) -
3.5.2b2Clean Clean (post-cleanup) -
3.5.2Clean Clean (post-cleanup) -
3.5.3b1Clean Clean (post-cleanup) -
3.5.3b2Clean Clean (post-cleanup) -
3.5.2b3Clean Clean (post-cleanup) -
3.5.3b4Clean Clean (post-cleanup) -
3.5.3Clean Clean (post-cleanup) -
3.5.4b2Clean Clean (post-cleanup) -
3.5.4b3Clean Clean (post-cleanup) -
3.5.4b4Clean Clean (post-cleanup) -
3.5.4Clean Clean (post-cleanup) -
3.5.5Clean Clean (post-cleanup) -
3.5.6b1Clean Clean (post-cleanup) -
3.5.6Clean Clean (post-cleanup) -
3.6b1Clean Clean (post-cleanup) -
3.6b2Clean Clean (post-cleanup) -
3.6b3Clean Clean (post-cleanup) -
3.6b4Clean Clean (post-cleanup) -
3.6b5Clean Clean (post-cleanup) -
3.6b6Clean Clean (post-cleanup) -
4.0b8Clean Clean (post-cleanup) -
4.0b9Clean Clean (post-cleanup) -
4.0Clean Clean (post-cleanup) -
4.0.1b1Clean Clean (post-cleanup) -
4.0.1b2Clean Clean (post-cleanup) -
4.0.1b3Clean Clean (post-cleanup) -
4.0.1Clean Clean (post-cleanup) -
3.0.2b1Clean Clean (post-cleanup) -
4.0.2b2Clean Clean (post-cleanup) -
4.0.2Clean Clean (post-cleanup) -
4.0.3b1Clean Clean (post-cleanup) -
4.0.3b2Clean Clean (post-cleanup) -
4.0.3b4Clean Clean (post-cleanup) -
4.0.3Clean Clean (post-cleanup) -
4.0.4b1Clean Clean (post-cleanup) -
4.0.4b2Clean Clean (post-cleanup) -
4.0.4b3Clean Clean (post-cleanup) -
4.0.4b4Clean Clean (post-cleanup) -
4.0.4b5Clean Clean (post-cleanup) -
4.0.4Clean Clean (post-cleanup) -
4.0.5b1Clean Clean (post-cleanup) -
4.0.5Clean Clean (post-cleanup) -
4.0.6b1Clean Clean (post-cleanup) -
4.0.6b2Clean Clean (post-cleanup) -
4.0.6b3Clean Clean (post-cleanup) -
4.0.6b4Clean Clean (post-cleanup) -
4.0.7b1Clean Clean (post-cleanup) -
4.0.6Clean Clean (post-cleanup) -
4.0.7Clean Clean (post-cleanup) -
4.0.8Clean Clean (post-cleanup) -
4.1Clean Clean (post-cleanup) -
4.1.1Clean Clean (post-cleanup) -
4.1.2Clean Clean (post-cleanup) -
4.2Clean Clean (post-cleanup) -
4.2.1Clean Clean (post-cleanup) -
4.2.2Clean Clean (post-cleanup) -
4.2.3Clean Clean (post-cleanup) -
4.2.4Clean Clean (post-cleanup) -
4.2.5Clean Clean (post-cleanup) -
4.3.1Clean Clean (post-cleanup) -
4.3.2Clean Clean (post-cleanup) -
4.3.3Clean Clean (post-cleanup) -
4.3.4Clean Clean (post-cleanup) -
4.3.5Clean Clean (post-cleanup) -
4.3.6Clean Clean (post-cleanup) -
4.4Clean Clean (post-cleanup) -
4.2.6Clean Clean (post-cleanup) -
4.5Clean Clean (post-cleanup) -
4.6Clean Clean (post-cleanup) -
5.0.0Clean Clean (post-cleanup) -
5.0.1Clean Clean (post-cleanup) -
5.1.0Clean Clean (post-cleanup) -
5.1.1Clean Clean (post-cleanup) -
5.1.2Clean Clean (post-cleanup) -
5.1.3Clean Clean (post-cleanup) -
5.1.4Clean Clean (post-cleanup) -
5.1.5Clean Clean (post-cleanup) -
5.1.6Clean Clean (post-cleanup) -
5.1.9Clean Clean (post-cleanup) -
5.1.8Clean Clean (post-cleanup) -
5.2.0Clean Clean (post-cleanup) -
5.2.1Clean Clean (post-cleanup) -
5.2.2Clean Clean (post-cleanup) -
5.3.0Clean Clean (post-cleanup) -
5.4.0Clean Clean (post-cleanup) -
5.5.0Clean Clean (post-cleanup) -
5.6.0Clean Clean (post-cleanup) -
5.7.0Clean Clean (post-cleanup) -
5.8.0Clean Clean (post-cleanup) -
5.9.0Clean Clean (post-cleanup) -
5.10.0Clean Clean (post-cleanup) -
5.10.1Clean Clean (post-cleanup) -
5.10.2Clean Clean (post-cleanup) -
3.2Clean Clean (post-cleanup) -
3.2.2Clean Clean (post-cleanup) -
3.2.2b1Clean Clean (post-cleanup) -
3.2.3b3Clean Clean (post-cleanup) -
3.2.1Clean Clean (post-cleanup) -
3.2.3b2Clean Clean (post-cleanup) -
3.2.1b1Clean Clean (post-cleanup) -
3.2.1b2Clean Clean (post-cleanup) -
3.2.1b4Clean Clean (post-cleanup) -
3.2.3b1Clean Clean (post-cleanup) -
3.2.1b3Clean Clean (post-cleanup) -
3.2b4Clean Clean (post-cleanup) -
3.2b3Clean Clean (post-cleanup) -
5.11.0Clean Clean (post-cleanup) -
5.12.0Clean Clean (post-cleanup) -
5.13.0Clean Clean (post-cleanup) -
5.14.0Clean Clean (post-cleanup) -
5.15.1Clean Clean (post-cleanup) -
5.15.2Clean Clean (post-cleanup) -
5.15.3Clean Clean (post-cleanup) -
5.16.1Clean Clean (post-cleanup) -
5.16.0Clean Clean (post-cleanup) -
5.17.0Clean Clean (post-cleanup) -
5.18.1Clean Clean (post-cleanup) -
5.18.2Clean Clean (post-cleanup) -
5.19.0Clean Clean (post-cleanup) -
5.20.0Clean Clean (post-cleanup) -
5.21.0Clean Clean (post-cleanup) -
5.22.0Clean Clean (post-cleanup) -
5.23.0Clean Clean (post-cleanup) -
5.1.7Clean Clean (post-cleanup) -
5.24.0Clean Clean (post-cleanup) -
5.25.0Clean Clean (post-cleanup) -
5.26.0Clean Clean (post-cleanup) -
5.27.0Clean Clean (post-cleanup) -
5.27.1Clean Clean (post-cleanup) -
5.27.2Clean Clean (post-cleanup) -
5.27.3Clean Clean (post-cleanup) -
5.27.4Clean Clean (post-cleanup) -
5.27.5Clean Clean (post-cleanup) -
5.27.6Clean Clean (post-cleanup) -
5.27.7Clean Clean (post-cleanup) -
5.27.8Clean Clean (post-cleanup) -
5.30.1Clean Clean (post-cleanup) -
5.30.2Clean Clean (post-cleanup) -
5.30.3Clean Clean (post-cleanup) -
5.30.4Clean Clean (post-cleanup) -
5.30.5Clean Clean (post-cleanup) -
5.30.6Clean Clean (post-cleanup) -
5.30.7Clean Clean (post-cleanup) -
5.30.8Clean Clean (post-cleanup) -
5.30.9Clean Clean (post-cleanup) -
5.30.10Clean Clean (post-cleanup) -
5.30.11Current Current release
Suspect-shape but structurally unreachable — benign with one regression to flag. YARPP's version_info() matches the high-confidence catalog IOC unserialize_after_remote_call (@unserialize of wp_remote_post body, hardcoded endpoint, sslverify => false, no signature). The exact same shape that made content-egg's Admitad chain a 7-year latent RCE (audit #15). However, two independent failures make the chain dead code today: (1) the type-gate above the unserialize is always-true, blocking the call, and (2) the live yarpp.org/checkversion.php endpoint returns inert HTML rather than serialized PHP. The author is real and the domain is theirs. No active risk; one defensive regression worth flagging to the author.
Plugin
| | | |---|---| | Slug | yet-another-related-posts-plugin (YARPP) | | Author | jeffparker | | Active installs | 100,000 | | Total downloads | 7,960,579 | | Added | 2008-01-02 | | Last update | 2024-11-11 (v5.30.11) | | Closed? | No |
The chain (still in source as of v5.30.11)
classes/YARPP_Core.php:2099-2118:
public function version_info( $enforce_cache = false ) {
if ( ! $enforce_cache && false !== ( $result = $this->get_transient( 'yarpp_version_info' ) ) ) {
return $result;
}
$version = YARPP_VERSION;
$remote = wp_remote_post(
"https://yarpp.org/checkversion.php?format=php&version={$version}",
array( 'sslverify' => false ) // ← TLS regression (added 2021-10-12)
);
if ( is_wp_error( $remote ) || wp_remote_retrieve_response_code( $remote ) != 200
|| ! isset( $remote['body'] )
|| ! is_array( $remote['body'] ) ) { // ← always-true: gate the unserialize never reaches
$this->set_transient( 'yarpp_version_info', null, 60 * 60 );
return false;
}
if ( $result = @unserialize( $remote['body'] ) ) { // ← IOC sink, unreachable
$this->set_transient( 'yarpp_version_info', $result, 60 * 60 * 24 );
}
return $result;
}Three suspicious patterns compounding: 1. Hardcoded HTTP-fetch with sslverify => false — TLS cert validation disabled on transport. 2. responseType=php — explicitly asks for PHP-serialized payload. 3. Error-suppressed @unserialize of remote body, no allowlist, no integrity check.
That's the classic content-egg shape (audit #15). Latent PHP Object Injection if the chain were reachable — any gadget chain (Symfony, Composer, Magento, etc.) becomes RCE on the WordPress site if the operator endpoint or any TLS-MITM path is ever hostile.
Why it's unreachable
Gate failure 1: ! is_array($remote['body']) is always true
wp_remote_post() returns an associative array where body is always a string — that's been WordPress's WP_Http contract since WP 2.7 (2008). So is_array($remote['body']) is false, ! is_array(...) is true, and the early-return on the next line always fires. The @unserialize line is never executed.
$ php -r '$remote = ["body" => "anything"]; var_dump(is_array($remote["body"]));'
bool(false)This looks like a programmer typo — the author probably intended ! is_array($remote) (defending against null/error responses) but wrote ! is_array($remote['body']), which inverted the meaning and accidentally made the chain dead. Whatever the intent, the practical effect is that version_info() has been silently returning false on every call for ~6 years.
Gate failure 2: live endpoint returns inert HTML
Probed 2026-04-30:
$ curl -X POST "https://yarpp.org/checkversion.php?format=php&version=5.30.11"
HTTP/2 200
content-type: text/html
content-length: 41
<html><body><h1>200 OK</h1></html></body>41 bytes of HTML. Even if the is_array gate were fixed, the body isn't serialized PHP — @unserialize($html) returns false, set_transient is never called, function returns false. No exploitation path.
yarpp.org itself 301-redirects to https://yarpp.com/, which serves the active brand site. The checkversion.php URL was preserved (returns harmless 200) presumably for the long tail of installs still polling it.
Git-level forensics
| Date | Tag | Event | |---|---|---| | 2008-01-02 | 1.0 | Plugin shipped — original version_info() already does wp_remote_post(http://yarpp.org/checkversion.php?format=php) + @unserialize($remote['body']). Live exposure begins. | | 2013-12-11 | 4.1-era | Function structure stable; ! isset($remote['body']) early-return added but no is_array typo gate yet. Still exposed. | | ≤ 2020-05-11 | v5.1.4 | Typo gate ! is_array($remote['body']) already present. Chain becomes unreachable at some commit between 2013-12 and 2020-05 (more precise bisection skipped). | | 2020-04-07 | v5.1.3 | URL switched from http:// to https:// (TLS introduced). | | 2021-10-12 | v5.27.6 | Regression: sslverify => false added by jeffparker. TLS cert validation disabled. (Doesn't change the exploit picture because the chain is already unreachable, but it's a defensive regression worth noting.) | | 2026-04-30 | v5.30.11 | Current state — chain unchanged, endpoint returns inert HTML. |
commit fd784c2 (2021-10-12) added sslverify => false to both the version_info() and optin_ping() calls. Likely the author was debugging a cert-chain issue from a host without proper CA bundles and committed the disable as a workaround.
Endpoint ownership
yarpp.org ↔ yarpp.com are both Jeff Parker's domains:
yarpp.org301 →yarpp.comyarpp.comserves an active YARPP brand site- wp.org profile
https://profiles.wordpress.org/jeffparker/shows display name "YARPP" — author identity matches domain
No "dangling-resource takeover" risk on the domain itself.
Threat model retrospective
If the typo gate had not existed (or were "fixed" by a future contributor), the exposure surface would have been:
- Anyone in a TLS-MITM position (since 2021-10-12, when
sslverify => falsewas added — before that, TLS was honored) yarpp.org's hosting provider, DNS provider, or any future buyer of the domain- Anyone who compromised the YARPP server hosting
checkversion.php
No public reports of in-the-wild exploitation. The gate has effectively neutralized the chain since v5.1.4 (May 2020) at the latest, and likely earlier.
Author intent assessment
jeffparker is the verified author of record (committer since 2013-09, member since [pre-2013]), with mitchoyoshitaka (Mitcho Erlewine, original co-author) as the prior committer 2012-2013, and mnelson4 as a brief 2021 contributor. No supply-chain-style changes — only routine maintenance. The code architecture is consistent with a 2008-era WordPress plugin that grew incrementally without a security retrofit. format=php was a standard PHP idiom of the era; the typo gate looks like an accidental defense rather than intentional gating.
Verdict
Benign — historical exposure (now closed). Same disposition as audit #15 (content-egg): suspect-shape chain matching a known IOC, with two independent failures making it unreachable. Difference from #15: YARPP's "gating" is an accidental typo rather than a deliberate throw, so the unreachability is fragile — a future contributor who "fixes" the always-true check could silently re-enable the sink.
Recommendations
To author (jeffparker): in priority order:
1. Switch the response format off ?format=php. Either change to ?format=json and use json_decode( wp_remote_retrieve_body($remote) ), or drop the version-check entirely (WordPress's own update API now handles this). Removes the IOC entirely. 2. Revert the sslverify => false regression added in v5.27.6 (commit fd784c2, 2021-10-12). If there's a TLS reason it was added, the right fix is updating the local CA bundle, not disabling validation. 3. Fix the always-true ! is_array($remote['body']) gate — but only after doing #1, otherwise this fix re-enables the IOC sink. The intent-likely guard is ! is_array($remote).
Cleanup status
cleanup_status = clean — no live exposure, no remediation needed for site owners. Author should land #1 + #2 above for hygiene; site owners running YARPP today are not at risk from this chain.