← All audits

Audit #16 Benign

Media Cloud for Bunny CDN, Amazon S3, Cloudflare R2, Google Cloud Storage, DigitalOcean and more · 7k+ installs · baseline 1.0.0 → head 4.6.4 · suspect committer interfacelab · by austin · closed 2d ago

Actor: Interfacelab LLC (interfacelab)
Show full summary

Clean — no supply-chain anomaly. Full git-level audit of ilab-media-tools (Media Cloud by interfacelab) covering all 162 published versions back to 2016-07. Single committer for 8 years, zero detection events, zero IOC matches, zero suspicious patterns in plugin-own code. The 58 code-scan findings on current trunk are all in vendored dependencies (Symfony, AWS SDK, Google Cloud, Firebase JWT, Carbon, ShortPixel) and are well-known legitimate uses. No further action required.

Investigated — no compromise found.

Audit retained for the record. No action required.

Plugins under the same committer's SVN access

interfacelab holds push access to 1 plugin totalling 7k+ 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. 1.0.0 Last clean Last clean release before incident
  2. 🛑 Compromise window

    Malicious releases pushed during this window were deleted from SVN by the wp.org Plugin Review Team. Last malicious tag: 4.6.4.

  3. 1.0.1 PRT cleanup PRT cleanup release — incident closed
  4. 1.0.2 Clean Clean (post-cleanup)
  5. 1.0.3 Clean Clean (post-cleanup)
  6. 1.0.4 Clean Clean (post-cleanup)
  7. 1.0.5 Clean Clean (post-cleanup)
  8. 1.0.8 Clean Clean (post-cleanup)
  9. 1.0.9 Clean Clean (post-cleanup)
  10. 1.1.0 Clean Clean (post-cleanup)
  11. 1.1.1 Clean Clean (post-cleanup)
  12. 1.2 Clean Clean (post-cleanup)
  13. 1.2.1 Clean Clean (post-cleanup)
  14. 1.2.2 Clean Clean (post-cleanup)
  15. 1.2.3 Clean Clean (post-cleanup)
  16. 1.4.1 Clean Clean (post-cleanup)
  17. 1.4.2 Clean Clean (post-cleanup)
  18. 1.4.3 Clean Clean (post-cleanup)
  19. 1.4.4 Clean Clean (post-cleanup)
  20. 1.4.5 Clean Clean (post-cleanup)
  21. 1.4.6 Clean Clean (post-cleanup)
  22. 1.4.7 Clean Clean (post-cleanup)
  23. 1.4.8 Clean Clean (post-cleanup)
  24. 1.4.9 Clean Clean (post-cleanup)
  25. 1.5.0 Clean Clean (post-cleanup)
  26. 1.5.1 Clean Clean (post-cleanup)
  27. 1.5.2 Clean Clean (post-cleanup)
  28. 1.5.3 Clean Clean (post-cleanup)
  29. 2.0.1 Clean Clean (post-cleanup)
  30. 2.0.2 Clean Clean (post-cleanup)
  31. 2.0.3 Clean Clean (post-cleanup)
  32. 2.0.4 Clean Clean (post-cleanup)
  33. 2.0.5 Clean Clean (post-cleanup)
  34. 2.0.6 Clean Clean (post-cleanup)
  35. 2.0.7 Clean Clean (post-cleanup)
  36. 2.0.8 Clean Clean (post-cleanup)
  37. 2.0.9 Clean Clean (post-cleanup)
  38. 2.1.0 Clean Clean (post-cleanup)
  39. 2.1.4 Clean Clean (post-cleanup)
  40. 2.1.5 Clean Clean (post-cleanup)
  41. 2.1.6 Clean Clean (post-cleanup)
  42. 2.1.7 Clean Clean (post-cleanup)
  43. 2.1.8 Clean Clean (post-cleanup)
  44. 2.1.9 Clean Clean (post-cleanup)
  45. 2.1.10 Clean Clean (post-cleanup)
  46. 2.1.11 Clean Clean (post-cleanup)
  47. 2.1.14 Clean Clean (post-cleanup)
  48. 2.1.15 Clean Clean (post-cleanup)
  49. 2.1.16 Clean Clean (post-cleanup)
  50. 2.1.17 Clean Clean (post-cleanup)
  51. 2.1.18 Clean Clean (post-cleanup)
  52. 2.1.19 Clean Clean (post-cleanup)
  53. 2.1.20 Clean Clean (post-cleanup)
  54. 2.1.21 Clean Clean (post-cleanup)
  55. 2.1.22 Clean Clean (post-cleanup)
  56. 2.1.23 Clean Clean (post-cleanup)
  57. 2.1.30 Clean Clean (post-cleanup)
  58. 3.0.7 Clean Clean (post-cleanup)
  59. 3.0.8 Clean Clean (post-cleanup)
  60. 3.0.9 Clean Clean (post-cleanup)
  61. 3.1.0 Clean Clean (post-cleanup)
  62. 3.1.1 Clean Clean (post-cleanup)
  63. 3.1.2 Clean Clean (post-cleanup)
  64. 3.1.5 Clean Clean (post-cleanup)
  65. 3.1.6 Clean Clean (post-cleanup)
  66. 3.1.7 Clean Clean (post-cleanup)
  67. 3.2.0 Clean Clean (post-cleanup)
  68. 3.2.1 Clean Clean (post-cleanup)
  69. 3.2.2 Clean Clean (post-cleanup)
  70. 3.2.3 Clean Clean (post-cleanup)
  71. 3.2.4 Clean Clean (post-cleanup)
  72. 3.2.5 Clean Clean (post-cleanup)
  73. 3.2.6 Clean Clean (post-cleanup)
  74. 3.2.7 Clean Clean (post-cleanup)
  75. 3.3.0 Clean Clean (post-cleanup)
  76. 3.3.1 Clean Clean (post-cleanup)
  77. 3.3.2 Clean Clean (post-cleanup)
  78. 3.3.3 Clean Clean (post-cleanup)
  79. 3.3.4 Clean Clean (post-cleanup)
  80. 3.3.5 Clean Clean (post-cleanup)
  81. 3.3.6 Clean Clean (post-cleanup)
  82. 3.3.7 Clean Clean (post-cleanup)
  83. 3.3.8 Clean Clean (post-cleanup)
  84. 3.3.9 Clean Clean (post-cleanup)
  85. 3.3.10 Clean Clean (post-cleanup)
  86. 3.3.11 Clean Clean (post-cleanup)
  87. 3.3.12 Clean Clean (post-cleanup)
  88. 3.3.14 Clean Clean (post-cleanup)
  89. 3.3.18 Clean Clean (post-cleanup)
  90. 3.3.19 Clean Clean (post-cleanup)
  91. 3.3.20 Clean Clean (post-cleanup)
  92. 3.3.21 Clean Clean (post-cleanup)
  93. 4.0.2 Clean Clean (post-cleanup)
  94. 4.0.3 Clean Clean (post-cleanup)
  95. 4.0.5 Clean Clean (post-cleanup)
  96. 4.0.6 Clean Clean (post-cleanup)
  97. 4.0.7 Clean Clean (post-cleanup)
  98. 4.0.11 Clean Clean (post-cleanup)
  99. 4.1.0 Clean Clean (post-cleanup)
  100. 4.1.1 Clean Clean (post-cleanup)
  101. 4.1.4 Clean Clean (post-cleanup)
  102. 4.1.5 Clean Clean (post-cleanup)
  103. 4.1.6 Clean Clean (post-cleanup)
  104. 4.1.7 Clean Clean (post-cleanup)
  105. 4.1.8 Clean Clean (post-cleanup)
  106. 4.1.9 Clean Clean (post-cleanup)
  107. 4.1.12 Clean Clean (post-cleanup)
  108. 4.1.14 Clean Clean (post-cleanup)
  109. 4.2.0 Clean Clean (post-cleanup)
  110. 4.2.1 Clean Clean (post-cleanup)
  111. 4.2.2 Clean Clean (post-cleanup)
  112. 4.2.3 Clean Clean (post-cleanup)
  113. 4.2.6 Clean Clean (post-cleanup)
  114. 4.2.7 Clean Clean (post-cleanup)
  115. 4.2.8 Clean Clean (post-cleanup)
  116. 4.2.9 Clean Clean (post-cleanup)
  117. 4.2.10 Clean Clean (post-cleanup)
  118. 4.2.11 Clean Clean (post-cleanup)
  119. 4.2.18 Clean Clean (post-cleanup)
  120. 4.2.20 Clean Clean (post-cleanup)
  121. 4.2.21 Clean Clean (post-cleanup)
  122. 4.2.22 Clean Clean (post-cleanup)
  123. 4.2.23 Clean Clean (post-cleanup)
  124. 4.2.25 Clean Clean (post-cleanup)
  125. 4.2.26 Clean Clean (post-cleanup)
  126. 4.2.28 Clean Clean (post-cleanup)
  127. 4.2.29 Clean Clean (post-cleanup)
  128. 4.2.30 Clean Clean (post-cleanup)
  129. 4.2.31 Clean Clean (post-cleanup)
  130. 4.2.32 Clean Clean (post-cleanup)
  131. 4.2.33 Clean Clean (post-cleanup)
  132. 4.2.34 Clean Clean (post-cleanup)
  133. 4.2.35 Clean Clean (post-cleanup)
  134. 4.2.36 Clean Clean (post-cleanup)
  135. 4.2.37 Clean Clean (post-cleanup)
  136. 4.3.1 Clean Clean (post-cleanup)
  137. 4.3.2 Clean Clean (post-cleanup)
  138. 4.3.3 Clean Clean (post-cleanup)
  139. 4.3.4 Clean Clean (post-cleanup)
  140. 4.3.8 Clean Clean (post-cleanup)
  141. 4.3.11 Clean Clean (post-cleanup)
  142. 4.4.0 Clean Clean (post-cleanup)
  143. 4.4.3 Clean Clean (post-cleanup)
  144. 4.4.4 Clean Clean (post-cleanup)
  145. 4.4.5 Clean Clean (post-cleanup)
  146. 4.5.0 Clean Clean (post-cleanup)
  147. 4.5.2 Clean Clean (post-cleanup)
  148. 4.5.3 Clean Clean (post-cleanup)
  149. 4.5.5 Clean Clean (post-cleanup)
  150. 4.5.7 Clean Clean (post-cleanup)
  151. 4.5.8 Clean Clean (post-cleanup)
  152. 4.5.9 Clean Clean (post-cleanup)
  153. 4.5.10 Clean Clean (post-cleanup)
  154. 4.5.11 Clean Clean (post-cleanup)
  155. 4.5.14 Clean Clean (post-cleanup)
  156. 4.5.15 Clean Clean (post-cleanup)
  157. 4.5.17 Clean Clean (post-cleanup)
  158. 4.5.19 Clean Clean (post-cleanup)
  159. 4.5.21 Clean Clean (post-cleanup)
  160. 4.5.24 Clean Clean (post-cleanup)
  161. 4.5.25 Clean Clean (post-cleanup)
  162. 4.6.0 Clean Clean (post-cleanup)
  163. 4.6.1 Clean Clean (post-cleanup)
  164. 4.6.2 Clean Clean (post-cleanup)
  165. 4.6.4 Current Current release

Clean — no supply-chain anomaly. Full git-level audit of ilab-media-tools (Media Cloud by interfacelab) covering all 162 published versions back to 2016-07. Single committer for 8 years, zero detection events, zero IOC matches, zero suspicious patterns in plugin-own code. The 58 code-scan findings on current trunk are all in vendored dependencies (Symfony, AWS SDK, Google Cloud, Firebase JWT, Carbon, ShortPixel) and are well-known legitimate uses. No further action required.

Plugin

| | | |---|---| | Slug | ilab-media-tools | | Name | Media Cloud for Bunny CDN, Amazon S3, Cloudflare R2, Google Cloud Storage, DigitalOcean and more | | Author | interfacelab (Interfacelab LLC), member since 2014-01-02 | | Active installs | 7,000 | | Total downloads | 543,955 | | Added | 2016-07-12 | | Last update | 2024-04-09 (v4.6.4) | | Closed? | No — never closed by wp.org | | Plugin URI | https://github.com/interfacelab/ilab-media-tools | | Author URI | http://interfacelab.io |

Methodology — git repo built from full SVN history

Standard event-driven triage didn't apply here (zero open events for this slug), so audit was performed proactively against the full release history rather than a single suspect-version delta.

# 1. Enumerate all 164 SVN tags
svn ls https://plugins.svn.wordpress.org/ilab-media-tools/tags/

# 2. For each tag in version order: svn export → rsync into git workspace → commit with svn author + date → tag
# (full script at /tmp/build-ilab-git.sh)

# 3. Result: /tmp/wpbeacon-git-repos/ilab-media-tools — 162 commits, 162 tags, 167 MB

(One transient svn: E120108 connection error skipped tag 4.5.3; trunk = 4.6.4 was already represented so no double-count.)

Committer history

| committer_slug | first_rev | last_rev | commit_count | notes | |---|---|---|---|---| | interfacelab | r1453266 (2016-07-12) | r3067574 (2024-04-09) | 348 | sole human committer, member since 2014 | | plugin-master | r1453124 (2016-07-12) | r1453124 | 1 | wp.org SVN bootstrap commit, standard |

No transfers, no co-committer additions, no WPORG Plugins Team cleanup commits across 8 years.

Code-scan findings (current trunk, v4.6.4)

58 findings, 45 high-signal. Breakdown:

| Source | Count | Notes | |---|---|---| | lib/mcloud-symfony/ | ~25 | vendored Symfony components (cache, lock, var-dumper, http-foundation, http-kernel, dependency-injection, error-handler, debug, polyfill-mbstring, polyfill-intl-normalizer, var-exporter, routing, mime, messenger, http-client) — Mozart/PHP-Scoper namespaced | | lib/mcloud-aws/aws-sdk-php/ | ~7 | AWS SDK PHP — DecryptionTrait/V2, MetadataParserTrait, JsonParser, XmlParser, AbstractRestParser | | lib/mcloud-google/ | ~6 | Google Cloud SDK — cloud-storage SigningHelper + EncryptionTrait, protobuf Message, cloud-core test helpers | | lib/mcloud-firebase/php-jwt | 3 | Firebase JWT lib — base64_decode of PEM key/header/signature components | | lib/mcloud-nesbot/carbon | 2 | Carbon date library — Serialization trait + Mixin trait | | lib/mcloud-shortpixel/ | 1 | ShortPixel API client — base64_decode of original filename | | Plugin-own code | 2 | both benign — see below |

The two plugin-own findings — both benign

1. classes/Tools/Video/Driver/Mux/MuxAPI.php:204

$privateKey = base64_decode($signingKey['privateKey']);
return JWT::encode($options, $privateKey, 'RS256');

Standard JWT signing pattern. The Mux video service requires RS256-signed JWTs to generate playback URLs; the private key is stored base64-encoded in plugin settings and decoded at sign time.

2. classes/Utilities/Search/Replacer.php:88

$unserialized = (!is_serialized($data)) ? false : @unserialize($data);

Standard WordPress search-replace idiom — gated by is_serialized($data) (so unserialize is only called on input that is in fact serialized PHP), with @ to suppress notices on legacy malformed payloads. Used during media-cloud URL rewrites in serialized wp_postmeta rows.

Full-history attack-pattern sweep — all zero

Across all 162 commits, in plugin-own code (excluding lib/, external/Freemius/, vendor/):

| Pattern | Commits-with-match | |---|---| | eval(base64_decode(...)) | 0 | | eval(gzinflate(...)) | 0 | | create_function(...) | 0 | | preg_replace('/.../e', ...) | 0 | | @unserialize(file_get_contents(...)) | 0 | | @unserialize(wp_remote_retrieve_body(...)) | 0 | | extract($_GET/POST/REQUEST/COOKIE) | 0 | | include/require($_GET/POST/...) | 0 | | system/passthru/shell_exec($_...) | 0 | | str_rot13(base64_decode(...)) | 0 | | permission_callback => __return_true | 0 | | Catalog IOCs (fetch_ver_info, cdnstaticsync, analytics.essentialplugin, widgetlogic.org, puc_v[45]_Factory) | 0 |

Domain extraction (c2_http_call)

45 hostnames harvested by scan-deltas on 2026-04-30. All consistent with the documented feature set:

  • Cloud storage: amazon.com, amazonaws.com, amazonwebservices.com, backblazeb2.com, digitalocean.com, googleapis.com, gstatic.com, kinsta.com, wasabisys.com, wpengine.com
  • Image / video CDNs: imgix.com, imgix.net, imgur.com, imagify.io, kraken.io, shortpixel.com, tinify.com, mux.com
  • Plugin's own brand: mediacloud.press
  • Licensing: freemius.com
  • Email: mandrillapp.com, sendgrid.com
  • Misc legitimate: youtube.com, telegram.org, ifttt.com, ngrok.io, mcafeesecure.com, projecthoneypot.org, pwnedpasswords.com, amplitude.com, jsdelivr.net, ju.mp
  • Doc/spec references in vendor libs: php.net, ietf.org, freedesktop.org, europa.eu, unoosa.org, symfony.com, spatie.be, wp-cli.org, firephp.org, wildfirehq.org, web.path, your.site

No callbacks to dynamic-DNS hosts, no Russian/Chinese VPS IPs, no domains younger than the plugin.

Directory-add timeline (organic)

| Version | Date | Added | Reason | |---|---|---|---| | 1.0.0 | 2016-07-12 | classes/, helpers/, public/, vendor/, views/, ilab-media-tools.php, readme.txt, LICENSE, README.md, tools.json | initial layout | | 1.5.1 | 2017-09-11 | config/ | settings system | | 3.0.7 | 2019-07-17 | external/Freemius, composer.json, composer.lock, docs/ | Freemius licensing integration | | 3.3.14 | 2020-02-19 | keys/public.key | RSA pubkey for license verification (never modified after) | | 4.1.0 | 2020-08-28 | lib/ (mcloud-* namespaced vendoring) | switched from vendor/ to scoped lib/ | | 4.2.34 | 2021-06-16 | resources/ | misc assets | | 4.4.4 | 2022-10-07 | .gitattributes, .gitmodules | repo housekeeping |

Every directory addition aligns with documented feature work in changelogs.

Verdict

Benign — clean. Long-running, single-author plugin with no supply-chain shape, no obfuscation, no hidden endpoints, no IOC matches. WP Beacon's existing event-driven detection correctly fired zero alerts on this plugin.

Cleanup status

cleanup_status = clean — nothing to remediate. Audit recorded for catalog completeness.