Skip to content
Home ยป Blog ยป Computer Science ยป Web Development ยป WordPress ยป Hide your WordPress website from Matt Mullenweg

Hide your WordPress website from Matt Mullenweg

8 minute read

In case you didn’t know, all WordPress installations are configured to send HTTP requests to WordPress.org. This is expected since your WordPress websites, even the private ones or ones created in a localhost environment, access the public theme and plugin repositories for installing and updating versions, as well as updating WordPress core itself.

This was not a personal concern of mine because I believed that the WordPress.org website belonged to WordPress Foundation, the nonprofit organization, while WordPress.com, the commercial service website, belonged to Automattic, a privately owned business.

This has now become a concern because Matt Mullenweg, the CEO of Automattic and co-founder and director of WordPress Foundation, announced in the WordPress slack community that WordPress.org is his personal site. I am uncomfortable with this for a number of reasons, but the first one is that this automated connection requires me to inherently trust a private citizen whom I’ve never met with information that could potentially violate FERPA and HIPAA laws, personally identifiable information (PII). Not to mention that if this individual keeps a log of all this data, this makes them a desirable target for hackers.

So this is what prompted my own investigation into determining what information was being sent to WordPress.org and below are the results (version numbers in endpoint URLs may differ). I was going through the source code of WordPress core version 6.7.0.

For each request, I wrote a conclusion that is purely my professional opinion on what to do about it. This is the same recommendations I’ve given my clients. Additionally, I created a WordPress plugin that does exactly that and I’ve installed it on all of my sites, my clients’ sites, and my employer’s clients’ sites. It can block and/or anonymize site-specific information that is irrelevant to the purpose of the HTTP request and is available in my online shop.


Endpoint: https://api.wordpress.org/core/browse-happy/1.1/

Source: wp_check_browser_version() in /wp-admin/includes/dashboard.php

Documented purpose: Checks if the user needs a browser update.

Data sent:

  1. Current version of WordPress
  2. Domain and protocol
  3. User-agent string of user browsing the backend of WordPress, can be used to identify their computer operating system, browser, and the versions of both

My conclusion: This can be safely blocked. It is not necessary to send this information offsite. The usage of the function indicates that if it fails the browser check, it displays a message notifying the currently logged-in user to not use IE or to update their version of the browser. If this functionality is required, then it can be recreated locally using the browse-happy-notice filter.


Endpoint: http://api.wordpress.org/core/checksums/1.0/

Source: get_core_checksums() in /wp-admin/includes/update.php

Documented purpose: Gets and caches the checksums for the given version of WordPress.

Data sent:

  1. Current version of WordPress
  2. Domain and protocol
  3. Site’s locale (defaults to en_US)

My conclusion: To protect the integrity and security of the install, this HTTP request should not be blocked. However, it is safe to anonymize the site’s domain and protocol and only send the current version and locale for checking.


Endpoint: http://api.wordpress.org/core/credits/1.1/

Source: wp_credits() in /wp-admin/includes/credits.php

Documented purpose: Retrieves the contributor credits.

Data sent:

  1. Current version of WordPress core
  2. Domain and protocol
  3. Site’s locale

My conclusion: This can be safely blocked. It is not necessary to send this information offsite. The usage of this function is to display the contributors on the about page in the backend of WordPress. Have you ever viewed the “About” page and then clicked on the “Credits” tab? Neither have I until I did this investigation.


Endpoint: http://api.wordpress.org/core/importers/1.1/

Source: wp_get_popular_popular_importers() in /wp-admin/includes/import.php

Documented purpose: Returns a list from WordPress.org of popular importer plugins.

Data sent:

  1. Current version of WordPress core
  2. Domain and protocol
  3. Site’s locale

My conclusion: This can be safely blocked. The function includes a fallback list of importers if the request fails. The downside is that it may be only in English and not translated.


Endpoint: https://api.wordpress.org/core/serve-happy/1.0/

Source: wp_check_php_version() in /wp-admin/includes/misc.phpย 

Documented purpose: Checks if the user needs to update PHP.

Data sent:

  1. Current version of WordPress core
  2. Domain and protocol
  3. The value of the constant PHP_VERSION

My conclusion: This can be safely blocked. The usage of this function is to display notices when WordPress.org has deemed your version as not acceptable for WordPress to function optimally. Just be sure you are running modern versions of PHP and checking release notes for requirements when new versions of WordPress core are released.


Endpoint: https://api.wordpress.org/core/version-check/1.7/

Source: wp_version_check() in /wp-includes/update.php

Documented purpose: Checks WordPress version against the newest version. The WordPress version, PHP version, and locale is sent. Checks against the WordPress server at api.wordpress.org. Will only check if WordPress isn’t installing.

Data sent:

  1. Current version of WordPress core
  2. Domain and protocol of site
  3. Domain and protocol of primary site in multisite installation
  4. Current version of PHP as determined by the constant PHP_VERSION
  5. Site’s locale
  6. Current version of the MySQL database connected to the install if found, “N/A” otherwise
  7. The version of the MySQL database at the time WordPress was installed.
  8. The value of the $wp_local_package global, when set
  9. Number of sites on this WordPress installation
  10. Number of users on this WordPress installation
  11. Whether this WordPress installation uses Multisite
  12. List of names of all PHP modules compiled and loaded (see get_loaded_extensions() for details)
  13. Operating system as determined by the constant PHP_OS
  14. bits as determined by the constant PHP_INT_SIZE
  15. If site supports WebP and AVIF images through the GD library (see gd_info() for details)
  16. If site supports WebP and AVIF images through Imagick
  17. Translation data outputted from wp_get_installed_translations(‘core’)
  18. Optional “extra stat”: stats if core download failed
  19. Optional “extra stat”: stats if a rollback occurred

My conclusion: This should not be blocked, but instead, modified to only pass the current version of WordPress core for the endpoint to determine if an update is needed. Everything else can be omitted or anonymized.


Endpoint: http://api.wordpress.org/events/1.0/

Source: get_events() in /wp-admin/includes/class-wp-community-events.php

Documented purpose: Gets data about events near a particular location.

Data sent:

  1. Current version of WordPress core
  2. Domain and protocol
  3. Partially anonymized IP address of user (see WP_Community_Events::get_unsafe_client_IP() for details), enough to identify users’ latitude and longitude coordinates, their nearest city, state, country, and timezone.

My conclusion: This can be safely blocked. This function is used to populate the list of events in the “WordPress Events and News” widget on the backend dashboard. If you don’t know what that widget is or you’ve never used it, then that’s why it can be blocked.


Endpoint: http://api.wordpress.org/patterns/1.0/

Source: get_items() in /wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php

Documented purpose: Search and retrieve block patterns metadata

Data sent:

  1. Current version of WordPress core
  2. Domain and protocol
  3. Locale

My conclusion: This should not be blocked, but instead, modified to omit or anonymize site-specific data.


Endpoint: https://api.wordpress.org/plugins/info/1.2/

Source: plugins_api() in /wp-admin/includes/plugin-install.php

Documented purpose: Retrieves plugin installer pages from the WordPress.org Plugins API.

Data sent:

  1. Current version of WordPress core
  2. Domain and protocol
  3. Locale

My conclusion: This should not be blocked, but instead, modified to omit or anonymize site-specific data.


Endpoint: https://api.wordpress.org/plugins/update-check/1.1/

Source: wp_update_plugins() in /wp-includes/update.php

Documented purpose: Checks for available updates to plugins based on the latest versions hosted on WordPress.org. Despite its name this function does not actually perform any updates, it only checks for available updates. A list of all plugins installed is sent to WP, along with the site locale. Checks against the WordPress server at api.wordpress.org. Will only check if WordPress isn’t installing.

Data sent: 

  1. Current version of WordPress core
  2. Domain and protocol
  3. Locale
  4. Translations for plugins
  5. List of all plugins installed on the site (including premium/custom plugins) with the following information about each one:
    1. Plugin name
    2. Plugin URI
    3. Version
    4. Description
    5. Author
    6. Author URI
    7. Text Domain
    8. Network
    9. Requires at least
    10. Requires PHP
    11. Update URI
    12. Requires Plugins
  6. List of all active plugins on the site

My conclusion: This should not be blocked, but instead, modified to only pass plugins with an empty value for “Update URI” and additionally filtered to exclude custom plugins. Everything else can be omitted or anonymized.


Endpoint: https://api.wordpress.org/secret-key/1.1/salt/

Source: Multiple places

Documented purpose: Returns a salt to add to hashes. Salts are created using secret keys.

Data sent: 

  1. Current version of WordPress core
  2. Domain and protocol

My conclusion: This should not be blocked, but instead, modified to omit or anonymize site-specific data.


Endpoint: http://api.wordpress.org/themes/info/1.2/

Source: themes_api() in /wp-admin/includes/theme.php

Documented purpose: Retrieves theme installer pages from the WordPress.org Themes API.

Data sent: 

  1. Current version of WordPress core
  2. Domain and protocol
  3. Locale

My conclusion: This should not be blocked, but instead, modified to omit or anonymize site-specific data.


Endpoint: https://api.wordpress.org/themes/update-check/1.1/

Source: wp_update_themes() in /wp-includes/update.php

Documented purpose: Checks for available updates to themes based on the latest versions hosted on WordPress.org. Despite its name this function does not actually perform any updates, it only checks for available updates. A list of all themes installed is sent to WP, along with the site locale. Checks against the WordPress server at api.wordpress.org. Will only check if WordPress isn’t installing.

Data sent: 

  1. Current version of WordPress core
  2. Domain and protocol
  3. Locale
  4. The currently active theme
  5. List of all installed themes (including premium/custom themes) with the following information about each one:
    1. Name
    2. Title
    3. Version
    4. Author
    5. Author URI
    6. Update URI
    7. Template (parent theme if child, slug otherwise)
    8. Stylesheet (slug)
  6. Locales used for themes

My conclusion: This should not be blocked, but instead, modified to only pass themes with an empty value for “Update URI” and additionally filtered to exclude custom and premium themes. Everything else can be omitted or anonymized.


Endpoint: https://api.wordpress.org/translations/core/1.0/

Source: translations_api() in /wp-admin/includes/translation-install.php

Documented purpose: Retrieve translations from WordPress Translation API.

Data sent: 

  1. Current version of WordPress core
  2. Domain and protocol
  3. Locale

My conclusion: This can be safely blocked if the site is only using American English. Otherwise, it should be modified to omit or anonymize site-specific data.


Endpoint: https://api.wordpress.org/translations/plugins/1.0/

Source: translations_api() in /wp-admin/includes/translation-install.php

Documented purpose: Retrieve translations from WordPress Translation API.

Data sent: 

  1. Current version of WordPress core
  2. Domain and protocol
  3. Locale
  4. Plugin slug
  5. Plugin version

My conclusion: This can be safely blocked if the site is only using US English. Otherwise, it should be modified to omit or anonymize site-specific data and continue to block for premium/custom plugins.


Endpoint: https://api.wordpress.org/translations/themes/1.0/

Source: translations_api() in /wp-admin/includes/translation-install.php

Documented purpose: Retrieve translations from WordPress Translation API.

Data sent: 

  1. Current version of WordPress core
  2. Domain and protocol
  3. Locale
  4. Theme slug
  5. Theme version

My conclusion: This can be safely blocked if the site is only using American English. Otherwise, it should be modified to omit or anonymize site-specific data and continue to block for premium/custom themes.

Related Post Module Attributes Before

array(29) {
  ["post_type"]=>
  bool(false)
  ["post_id"]=>
  string(5) "22724"
  ["exclude"]=>
  string(2) "on"
  ["title"]=>
  string(27) "You might also like…"
  ["description"]=>
  string(0) ""
  ["max"]=>
  string(1) "4"
  ["post_ids"]=>
  string(0) ""
  ["exclude_ids"]=>
  string(0) ""
  ["is_series"]=>
  string(0) ""
  ["featured_term"]=>
  string(0) ""
  ["exclude_terms"]=>
  string(0) ""
  ["exclusive"]=>
  string(0) ""
  ["order"]=>
  string(4) "DESC"
  ["show_image"]=>
  string(2) "on"
  ["image_size"]=>
  string(6) "medium"
  ["menu_order_label"]=>
  string(0) ""
  ["show_order_label"]=>
  string(2) "on"
  ["show_date"]=>
  string(2) "on"
  ["show_meta_keys"]=>
  string(2) "on"
  ["show_modified"]=>
  string(0) ""
  ["show_author"]=>
  string(0) ""
  ["show_categories"]=>
  string(0) ""
  ["show_primary_category"]=>
  string(0) ""
  ["show_description"]=>
  string(0) ""
  ["show_reading_time"]=>
  string(2) "on"
  ["show_cta"]=>
  string(2) "on"
  ["cta"]=>
  string(9) "Read more"
  ["autoplay"]=>
  string(0) ""
  ["allow_sticky"]=>
  string(0) ""
}

Related Post Module Attributes

array(29) {
  ["post_type"]=>
  bool(false)
  ["post_id"]=>
  string(5) "22724"
  ["exclude"]=>
  string(2) "on"
  ["title"]=>
  string(27) "You might also like…"
  ["description"]=>
  string(0) ""
  ["max"]=>
  string(1) "4"
  ["post_ids"]=>
  string(0) ""
  ["exclude_ids"]=>
  string(0) ""
  ["is_series"]=>
  string(0) ""
  ["featured_term"]=>
  string(0) ""
  ["exclude_terms"]=>
  string(0) ""
  ["exclusive"]=>
  string(0) ""
  ["order"]=>
  string(4) "DESC"
  ["show_image"]=>
  string(2) "on"
  ["image_size"]=>
  string(6) "medium"
  ["menu_order_label"]=>
  string(0) ""
  ["show_order_label"]=>
  string(2) "on"
  ["show_date"]=>
  string(2) "on"
  ["show_meta_keys"]=>
  string(2) "on"
  ["show_modified"]=>
  string(0) ""
  ["show_author"]=>
  string(0) ""
  ["show_categories"]=>
  string(0) ""
  ["show_primary_category"]=>
  string(0) ""
  ["show_description"]=>
  string(0) ""
  ["show_reading_time"]=>
  string(2) "on"
  ["show_cta"]=>
  string(2) "on"
  ["cta"]=>
  string(9) "Read more"
  ["autoplay"]=>
  string(0) ""
  ["allow_sticky"]=>
  string(0) ""
}

Nobody has commented on this yet, be the first!

Your email address will not be published. Required fields are marked *