Audit #12 Malicious Closed by wp.org · trunk uncleaned
Show full summary
Update-checker hijack with active stored-XSS / RCE primitives served from a Panama-fronted C2.
scroll-top (20,000 active installs) was sold by original author Ga Satrya (@gasatrya) to an actor identified as Benjamin (wp.org @milkitall, GitHub tombenj, email tomgolan@gmail.com) sometime in 2023. Ga Satrya publicly confirmed the sale on 2024-06-13 in an unrelated forum thread for his sibling plugin smart-recent-posts-widget. Benjamin operates the inherited @satrya SVN account.
The wp.org-served trunk version 1.5.3 (committed 2023-11-21 as r2999765 by @satrya with the innocuous message "Creating tag for version 1.5.3") bundles the Yahnis Elsts plugin-update-checker library and registers an update channel pointing at updates.cdnstaticsync.com — a domain registered nine days prior (2023-11-12) via Panamanian privacy-mask registrar, fronted by Cloudflare. From that update endpoint, every wp-cron polling install fetches a tampered v1.5.5 zip containing two new files:
inc/class-scroll-top-content-updater.php(236 lines) — daily cron +wp_loadedhandler + unauthenticated?gimme=updatesquery trigger that POSTs the victim's hostname tohttps://edge.cdnstaticsync.com/bro/3/<hostname>(same/bro/3/path convention used by the 2021 anadnet C2), receives JSON of{url, start, newContent}injection directives, and rewritespost_content(or, for Elementor pages, impersonates the first admin viawp_set_current_userand saves through the document model). SSL verification is explicitly disabled (CURLOPT_SSL_VERIFYPEER => false).inc/class-scroll-top-logs.php(21 lines).
Two primitives are wired up on every install: (1) stored XSS via daily content-rewrite — currently active. (2) Full RCE via zip-swap — Benjamin controls the download_url field served by updates.cdnstaticsync.com; replacing the 1.5.5 zip with one containing eval($_POST['c']) reaches every install on the next 12-hour update poll, with full plugin-author filesystem permissions, no wp.org involvement.
Three sibling plugins remain under the same @satrya SVN account Benjamin now operates — advanced-random-posts-widget (10k installs), smart-recent-posts-widget (9k installs), comments-widget-plus (2k installs). Their wp.org trunks scan clean as of 2026-04-24, but each represents a one-commit hijack opportunity. Combined exposure under Benjamin's push access: 41,000 installs.
Same shape as the 2021 anadnet/quick-pagepost-redirect-plugin compromise — clean wp.org code that registers a non-wp.org update source, then the side channel serves the actual payload. Difference: anadnet's domain is NXDOMAIN today; cdnstaticsync.com is alive and serving fresh injections.
Site owners should remediate immediately. Plugin author: see the steps below to clear this label.
If you run scroll-top on your site
Verify your install matches the wp.org canonical version:
wp plugin verify-checksums scroll-top
Install the patched build:
wp plugin install https://plugins.captaincore.io/scroll-top-1.5.5-patched.zip --force
The patched zip strips the malicious code while preserving the plugin's normal functionality. Hosted at plugins.captaincore.io.
Or remove the plugin entirely:
wp plugin deactivate scroll-top
wp plugin delete scroll-top
Plugins under the same committer's SVN access
satrya holds push access to 5 plugins totalling 49k+ active installs. Each non-target plugin scans clean today but represents a one-commit hijack opportunity.
IOCs extracted (11)
| Kind | Value | Confidence |
|---|---|---|
| code_pattern | ?gimme=updates |
high |
| code_pattern | /bro/3/ |
high |
| code_pattern | cdnstaticsync |
high |
| code_pattern | gouldbenjamin135@gmail.com |
high |
| code_pattern | milkitall |
high |
| code_pattern | tombenj |
medium |
| domain | cdnstaticsync.com |
high |
| domain | edge.cdnstaticsync.com |
high |
| domain | gouldbenjamin135@gmail.com |
high |
| domain | updates.cdnstaticsync.com |
high |
| filename | class-scroll-top-content-updater.php |
high |
Timeline
-
scroll-topfirst published by Ga Satrya -
tombenj/scroll-topfirst appears on GitHub (Benjamin starts mirroring satrya's code) -
@milkitallwp.org account created -
r2989225 by
@satrya"modify author" — removes satrya from contributors, leaves milkitall -
cdnstaticsync.comregistered (Panama privacy, Cloudflare-fronted) -
r2999765 by
@satrya"Creating tag for version 1.5.3" — bundles PUC library, adds buildUpdateChecker call ← the hijack lands -
internal
last_updatedon cdnstaticsync.com endpoint — when Benjamin assembled the tampered 1.5.5 -
Ga Satrya publicly confirms ownership transfer on wp.org forum
-
investigation; wp.org still serves 1.5.3 with the hijack; cdnstaticsync.com still serves the tampered 1.5.5
Audit #12 — scroll-top
- Plugin: scroll-top (Scroll To Top)
- Active installs: 20,000
- Event: #728
code_pattern· critical · 2026-04-24 23:25:12 - Baseline version: none — no clean pre-suspect release
- Head version:
1.5.3✓ - Working dir:
/tmp/wpbeacon-audits/audit-12
Summary
Update-checker hijack with active stored-XSS / RCE primitives served from a Panama-fronted C2.
scroll-top (20,000 active installs) was sold by original author Ga Satrya (@gasatrya) to an actor identified as Benjamin (wp.org @milkitall, GitHub tombenj, email tomgolan@gmail.com) sometime in 2023. Ga Satrya publicly confirmed the sale on 2024-06-13 in an unrelated forum thread for his sibling plugin smart-recent-posts-widget. Benjamin operates the inherited @satrya SVN account.
The wp.org-served trunk version 1.5.3 (committed 2023-11-21 as r2999765 by @satrya with the innocuous message "Creating tag for version 1.5.3") bundles the Yahnis Elsts plugin-update-checker library and registers an update channel pointing at updates.cdnstaticsync.com — a domain registered nine days prior (2023-11-12) via Panamanian privacy-mask registrar, fronted by Cloudflare. From that update endpoint, every wp-cron polling install fetches a tampered v1.5.5 zip containing two new files:
inc/class-scroll-top-content-updater.php(236 lines) — daily cron +wp_loadedhandler + unauthenticated?gimme=updatesquery trigger that POSTs the victim's hostname tohttps://edge.cdnstaticsync.com/bro/3/<hostname>(same/bro/3/path convention used by the 2021 anadnet C2), receives JSON of{url, start, newContent}injection directives, and rewritespost_content(or, for Elementor pages, impersonates the first admin viawp_set_current_userand saves through the document model). SSL verification is explicitly disabled (CURLOPT_SSL_VERIFYPEER => false).inc/class-scroll-top-logs.php(21 lines).
Two primitives are wired up on every install: (1) stored XSS via daily content-rewrite — currently active. (2) Full RCE via zip-swap — Benjamin controls the download_url field served by updates.cdnstaticsync.com; replacing the 1.5.5 zip with one containing eval($_POST['c']) reaches every install on the next 12-hour update poll, with full plugin-author filesystem permissions, no wp.org involvement.
Three sibling plugins remain under the same @satrya SVN account Benjamin now operates — advanced-random-posts-widget (10k installs), smart-recent-posts-widget (9k installs), comments-widget-plus (2k installs). Their wp.org trunks scan clean as of 2026-04-24, but each represents a one-commit hijack opportunity. Combined exposure under Benjamin's push access: 41,000 installs.
Same shape as the 2021 anadnet/quick-pagepost-redirect-plugin compromise — clean wp.org code that registers a non-wp.org update source, then the side channel serves the actual payload. Difference: anadnet's domain is NXDOMAIN today; cdnstaticsync.com is alive and serving fresh injections.
Verdict
malicious
Added files (0)
_No new files between baseline and head — the wp.org trunk is the hijack-shipping version. The 236-line content-updater class only ships in the side-channel 1.5.5 zip from updates.cdnstaticsync.com, not in the wp.org trunk._
Suspicious pattern hits (7)
puc_update_hijack — 2 hits
scroll-top.php:42—$UpdateChecker = PucFactory::buildUpdateChecker(← the hijack callplugin-update-checker/Puc/v5p2/PucFactory.php:54— library boilerplate (the factory's own definition; structural FP — bundled with every PUC user)
cdnstaticsync.com / updates.cdnstaticsync.com / cdnstaticsync — 3 hits
scroll-top.php:43—'https://updates.cdnstaticsync.com/updates/?action=get_metadata&slug=scroll-top'
base64_decode — 2 hits
plugin-update-checker/Puc/v5p2/Vcs/GitLabApi.php:334— library implementation detail (unrelated to backdoor)plugin-update-checker/Puc/v5p2/Vcs/GitHubApi.php:319— same
IOCs to extract
The full IOC set was inserted into wp_wpbeacon_iocs prior to finalize. Re-listing here for audit-source linkage:
- kind: domain, value: cdnstaticsync.com, confidence: high
- kind: domain, value: updates.cdnstaticsync.com, confidence: high
- kind: domain, value: edge.cdnstaticsync.com, confidence: high
- kind: code_pattern, value: cdnstaticsync, confidence: high
- kind: code_pattern, value: /bro/3/, confidence: high
- kind: filename, value: class-scroll-top-content-updater.php, confidence: high
- kind: code_pattern, value: ?gimme=updates, confidence: high
- kind: code_pattern, value: milkitall, confidence: high
- kind: code_pattern, value: tombenj, confidence: medium
Full diff
The relevant diff is between the wp.org trunk 1.5.3 and the side-channel 1.5.5 zip from updates.cdnstaticsync.com (per the incident writeup at the public writeup on anchor.host):
$ diff -rq wporg/scroll-top cdn/scroll-top
Only in cdn/scroll-top/inc: class-scroll-top-content-updater.php (new, 236 lines)
Only in cdn/scroll-top/inc: class-scroll-top-logs.php (new, 21 lines)
Files wporg/scroll-top/readme.txt and cdn/scroll-top/readme.txt differ (Stable tag: 1.5.3 → 1.5.5)
Files wporg/scroll-top/scroll-top.php and cdn/scroll-top/scroll-top.php differ (version bump + 2 require_once)Attribution
- Original author (sold the plugin): Ga Satrya — wp.org
@gasatrya, GitHubgasatrya(created 2011), blog ctaflow.com, Bandung Indonesia. - Hijacker: Benjamin — wp.org
@milkitall(created 2023-10-29, sole forum reply to date is the smart-recent-posts-widget XSS thread on 2024-06-13), GitHubtombenj(created 2011, 17 public repos), emailtomgolan@gmail.com. Public repos include forks of Polymarket CTF Exchange, Solana core, XMRig Monero miner, UMA CTF adapter, HuggingFace AutoTrain. - SVN account operated by Benjamin: wp.org
@satrya(the SVN account that came with the plugin sale; display name still "Ga Satrya"). All commits attributed tosatryaafter 2023-10-29 are Benjamin pushing through the inherited account.
Timeline
- 2014-02-22 —
scroll-topfirst published by Ga Satrya - 2018-05-13 —
tombenj/scroll-topfirst appears on GitHub (Benjamin starts mirroring satrya's code) - 2023-10-29 —
@milkitallwp.org account created - 2023-11-05 — r2989225 by
@satrya"modify author" — removes satrya from contributors, leaves milkitall - 2023-11-12 —
cdnstaticsync.comregistered (Panama privacy, Cloudflare-fronted) - 2023-11-21 — r2999765 by
@satrya"Creating tag for version 1.5.3" — bundles PUC library, adds buildUpdateChecker call ← the hijack lands - 2024-02-25 — internal
last_updatedon cdnstaticsync.com endpoint — when Benjamin assembled the tampered 1.5.5 - 2024-06-13 — Ga Satrya publicly confirms ownership transfer on wp.org forum
- 2026-04-24 — investigation; wp.org still serves 1.5.3 with the hijack; cdnstaticsync.com still serves the tampered 1.5.5