Skip to content

Conversation

@faisalahammad
Copy link

@faisalahammad faisalahammad commented Feb 12, 2026

Summary

This PR fixes issue #1156 by enabling the existing EnqueuedResourceOffloadingSniff in the plugin-check ruleset. This allows Plugin Check to detect when plugins load external assets from third-party CDNs without user consent, which violates WordPress.org plugin guideline #7 (privacy requirements).

The fix is simple: Add the existing, fully tested sniff to the ruleset configuration file (just 5 lines of code).

Problem Description

What Was Happening

Plugin Check was not detecting when plugins loaded CSS and JS files from external CDN services like jsdelivr, unpkg, or bootstrapcdn. This is a violation of WordPress.org Plugin Guideline #7 which states:

Plugins may not track users without their consent.

Loading assets from external servers can expose user data (IP addresses, browsing behavior) to third parties without the user's knowledge or permission.

Example Code That Was Not Being Detected

// This code violates privacy guidelines but was not being flagged
wp_enqueue_script(
    'phone-input-js',
    'https://cdn.jsdelivr.net/npm/intl-tel-input@21.2.4/build/js/intlTelInput.min.js',
    array(),
    '21.2.4',
    true
);

wp_enqueue_style(
    'phone-input-css',
    'https://cdn.jsdelivr.net/npm/intl-tel-input@21.2.4/build/css/intlTelInput.css',
    array(),
    '21.2.4'
);

When plugin developers ran Plugin Check on code like this, they received no warnings or errors, even though the code violates privacy guidelines.

Root Cause

After investigating the codebase, I found that:

  1. The detection code already exists at phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/EnqueuedResourceOffloadingSniff.php
  2. It has comprehensive unit tests at phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/EnqueuedResourceOffloadingUnitTest.php
  3. It works perfectly when enabled directly
  4. The problem: It was never added to phpcs-rulesets/plugin-check.ruleset.xml, so Plugin Check never ran it

I verified this by running the sniff directly:

./vendor/bin/phpcs test-file.php --standard=PluginCheck \
  --sniffs=PluginCheck.CodeAnalysis.EnqueuedResourceOffloading

# Result: Successfully detected both CDN violations

Solution

What This PR Does

This PR adds the EnqueuedResourceOffloadingSniff to the plugin-check ruleset configuration file. No new code is written. We are simply enabling an existing, tested feature.

Changes Made

File: phpcs-rulesets/plugin-check.ruleset.xml

Before:

<!-- Check for discouraged functions. -->
<rule ref="PluginCheck.CodeAnalysis.DiscouragedFunctions"/>

</ruleset>

After:

<!-- Check for discouraged functions. -->
<rule ref="PluginCheck.CodeAnalysis.DiscouragedFunctions"/>

<!-- Check for external CDN asset loading (privacy guideline #7). -->
<rule ref="PluginCheck.CodeAnalysis.EnqueuedResourceOffloading">
    <severity>7</severity>
</rule>

</ruleset>

That's it! Just 5 lines of XML configuration.

How It Works

The EnqueuedResourceOffloadingSniff works by:

  1. Detecting WordPress asset enqueue functions during static code analysis:

    • wp_enqueue_script()
    • wp_register_script()
    • wp_enqueue_style()
    • wp_register_style()
  2. Extracting the source URL from the second parameter ($src)

  3. Checking against known CDN patterns using the OffloadingServicesTrait, which includes over 20 known CDN services:

  4. Reporting an error when external CDN usage is detected

Special Cases Handled

  • Google Fonts are allowed: The pattern uses a negative lookahead to allow fonts.gstatic.com since Google Fonts are commonly used and generally accepted
  • PHP 8.0+ named parameters: Fully supported and tested
  • Case-insensitive matching: Works with BOOTSTRAPCDN.COM or cdn.jsdelivr.net

Testing

Test 1: Code From Issue #1156

I created a test file with the exact code reported in the issue:

Before this PR:

./vendor/bin/phpcs test-file.php --standard=phpcs-rulesets/plugin-check.ruleset.xml

# Result: No errors found

After this PR:

./vendor/bin/phpcs test-file.php --standard=phpcs-rulesets/plugin-check.ruleset.xml

# Result:
FOUND 2 ERRORS AFFECTING 2 LINES
--------------------------------------------------------------------------------------------------
 21 | ERROR | Found call to wp_enqueue_script() with external resource. Offloading scripts to
    |       | your servers or any remote service is disallowed.
 30 | ERROR | Found call to wp_enqueue_style() with external resource. Offloading styles to your
    |       | servers or any remote service is disallowed.

Both violations are now properly detected!

Test 2: Existing Unit Tests

The sniff already has comprehensive unit tests that verify detection of multiple CDN services:

./vendor/bin/phpcs --standard=PluginCheck \
  phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/EnqueuedResourceOffloadingUnitTest.1.inc

# Result:
FOUND 3 ERRORS AFFECTING 3 LINES
--------------------------------------------------------------------------------------------------
  5 | ERROR | Found call to wp_enqueue_script() with external resource... (cdn.jsdelivr.net)
 13 | ERROR | Found call to wp_enqueue_style() with external resource... (bootstrapcdn.com)
 22 | ERROR | Found call to wp_register_script() with external resource... (googleusercontent.com)

All existing tests pass correctly!

These test results match the expected errors defined in the unit test file, confirming the sniff is working as designed.

Test 3: Edge Cases

The existing unit tests cover important edge cases:

  • ✅ Named parameters (PHP 8.0+)
  • ✅ Different function types (enqueue vs register)
  • ✅ Different asset types (scripts vs styles)
  • ✅ Case sensitivity (uppercase domain names)
  • ✅ Multiple CDN services

Why This Approach

I considered three potential solutions:

Option 1: Enable Existing Sniff (This PR)

  • Effort: 5 lines of XML
  • Risk: Very low
  • Maintenance: Zero (uses existing code)
  • Coverage: 20+ CDN services
  • Tests: Already exist and pass
  • Selected

Option 2: Create New Runtime Check

  • Effort: 200+ lines of new code
  • Risk: Medium-high
  • Maintenance: Ongoing
  • Rejected: Duplicates existing functionality

Option 3: Hybrid Approach (Both Static and Runtime)

  • Effort: Significant
  • Risk: Medium
  • Rejected: Overkill for the issue

Option 1 is clearly the best choice because it is simple, uses proven code, requires no new maintenance, and solves the reported issue completely.

Impact

Benefits

  • ✅ Plugin authors will now see errors when they load assets from external CDNs
  • ✅ Helps prevent privacy guideline violations before plugin submission
  • ✅ Improves WordPress.org plugin quality and user privacy
  • ✅ No performance impact (static analysis)

Risk Assessment

  • Breaking Changes: None
  • Backward Compatibility: Full (existing checks unchanged)
  • Performance Impact: Negligible (one additional sniff)
  • Risk Level: Very low (enabling existing, tested code)

Related Files

  • Sniff Implementation: phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/EnqueuedResourceOffloadingSniff.php
  • Helper Trait: phpcs-sniffs/PluginCheck/Helpers/OffloadingServicesTrait.php
  • Unit Tests: phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/EnqueuedResourceOffloadingUnitTest.php
  • Test Data: phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/EnqueuedResourceOffloadingUnitTest.1.inc

Checklist

  • Code follows WordPress coding standards
  • Changes are minimal and focused
  • Existing tests pass
  • Solution addresses the reported issue
  • No new dependencies added
  • No breaking changes
  • Documentation is clear

Closes

Fixes #1156

… external CDN usage

This commit enables the existing EnqueuedResourceOffloadingSniff in the
plugin-check ruleset to detect when plugins load external assets from
third-party CDNs without user consent, addressing a privacy guideline
violation (WordPress.org guideline WordPress#7).

The sniff already existed and was fully functional with comprehensive
unit tests, but was not included in the plugin-check.ruleset.xml file.
This simple addition now ensures PCP will flag CDN usage from jsdelivr,
unpkg, cloudflare, bootstrapcdn, and 20+ other known CDN services.
@github-actions
Copy link

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: faisalahammad <faisalahammad@git.wordpress.org>
Co-authored-by: davidperezgar <davidperez@git.wordpress.org>
Co-authored-by: shameemreza <shameemreza@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PCP does not detect external CDN asset loading (privacy guideline violation)

1 participant