Version checks are an unnecessary user privacy abuse

I’m currently on /wp-admin/plugins.php?plugin_status=all&paged=1&s but every time I refresh your plugin is trying to send out the following to “https://gravityapi.com/wp-content/plugins/gravitymanager/version.php” as a “version check”. You are checking for updates EVERY TIME. Have you heard of caching?

Here’s the annoying part though. What you’re sending out is completely unnecessary for a version check. Why are you spying on all your customers? And if you are, are you GDPR compliant? Did you obtain permission from the user? How string is your encryption? Is your data encrypted at rest? Are you undergoing yearly security audits? What are your policies on data breaches?

I could ask a hundred more questions but none would get to the root of the matter: you are abusing people’s trust and are collecting information that does not belong to you, without notifying or asking for permission.

{
    "method": "POST",
    "timeout": 15,
    "headers": {
        "Content-Type": "application\/x-www-form-urlencoded; charset=UTF-8",
        "User-Agent": "WordPress\/5.8.2",
        "Referer": "https:\/\/REDACTED.com"
    },
    "body": {
        "of": "gravityforms",
        "key": "5e13d0e0d9afat989465abitch7f9efc6",
        "v": "2.5.15", // your plugin, sure, why not I suppose.
        "wp": "5.8.2", // yeah, maybe to notify if there's incompatibility.
        "php": "7.4.24", // what does this matter to you? WP runs.
        "mysql": "10.3.31", // again, none of your business.
        "version": "2", // beats me why you need to duplicate this.
        // list of all plugins installed, active or inactive, in my wordpress installation that's running on my server. Why the hell do you need this? How does this help you check for a new gravityforms version?!
        "plugins": "[{\"name\":\"Advanced Custom Fields PRO\",\"slug\":\"advanced-custom-fields-pro\",\"version\":\"5.11\",\"is_active\":true},{\"name\":\"Classic Editor\",\"slug\":\"classic-editor\",\"version\":\"1.6.2\",\"is_active\":true},{\"name\":\"Cloudflare\",\"slug\":\"cloudflare\",\"version\":\"4.7.0\",\"is_active\":true},{\"name\":\"Comment Rating Field Pro\",\"slug\":\"comment-rating-field-pro-plugin\",\"version\":\"3.5.8\",\"is_active\":false},{\"name\":\"EWWW Image Optimizer\",\"slug\":\"ewww-image-optimizer\",\"version\":\"6.3.0\",\"is_active\":true},{\"name\":\"Gravity Forms\",\"slug\":\"gravityforms\",\"version\":\"2.5.15\",\"is_active\":true},{\"name\":\"Gravity Forms + Salesforce: API\",\"slug\":\"gravityformssalesforce\",\"version\":\"1.6.0\",\"is_active\":false},{\"name\":\"Gravity Forms Mailchimp Add-On\",\"slug\":\"gravityformsmailchimp\",\"version\":\"5.0\",\"is_active\":false},{\"name\":\"Gravity forms pre populate add-on\",\"slug\":\"Gravity-Forms-Prepopulate-master\",\"version\":\"0.1\",\"is_active\":true},{\"name\":\"MainWP Child\",\"slug\":\"mainwp-child\",\"version\":\"4.1.8\",\"is_active\":false},{\"name\":\"Official StatCounter Plugin\",\"slug\":\"official-statcounter-plugin-for-wordpress\",\"version\":\"2.0.6\",\"is_active\":true},{\"name\":\"Pronamic Google Maps\",\"slug\":\"pronamic-google-maps\",\"version\":\"2.3.2\",\"is_active\":true},{\"name\":\"Query Monitor\",\"slug\":\"query-monitor\",\"version\":\"3.7.1\",\"is_active\":true},{\"name\":\"Really Simple SSL\",\"slug\":\"really-simple-ssl\",\"version\":\"5.1.3\",\"is_active\":false},{\"name\":\"Redirection\",\"slug\":\"redirection\",\"version\":\"5.1.3\",\"is_active\":true},{\"name\":\"Sucuri Security - Auditing, Malware Scanner and Hardening\",\"slug\":\"sucuri-scanner\",\"version\":\"1.8.30\",\"is_active\":false},{\"name\":\"WP-SpamShield\",\"slug\":\"wp-spamshield\",\"version\":\"1.9.21\",\"is_active\":false},{\"name\":\"WP No Category Base\",\"slug\":\"wp-no-category-base\",\"version\":\"1.1.1\",\"is_active\":true},{\"name\":\"Yoast SEO\",\"slug\":\"wordpress-seo\",\"version\":\"17.6\",\"is_active\":true}]",
        // nothing below is needed for a version check.
        "tn": "REDACTED", // you don't need my name
        "tu": "",
        "tv": "1.1",
        "ta": "REDDACTED.com", // you don't need my domain
        "tau": "https:\/\/READACTED.com\/", // no need for this either
        "im": false,
        "fc": 2,
        "ec": "345",
        "emc": "364",
        "api": 0,
        "emeta": 4455,
        "ed": 4455,
        "en": 86,
        "lang": "en_US"
    }
}

This should be a simple GET to your public URL that spits out a version number. Then internally handle notifying the user of the new version. That’s it. That’s a version check.

Last note: At least have the decency to set a short timeout for the request. I got to this junk because I’m on a local dev env and I’m waiting 30+ seconds for your plugin to get on with it. Poor practices all around.

Hi Frank. I recommend sending this in with a support ticket for an official response:

https://www.gravityforms.com/open-support-ticket/technical/

Hi Frank. Version checks are standard practice for WordPress and many other plugins and themes, and we do cache the results. If you have other questions I recommend referring to our Privacy and our Terms and Conditions. Thank you.

Poor effort Chris. I get it, your company got caught red handed, and is now downplaying the blatant privacy invasion under the old adage “but everyone else is doing it”.

I don’t care about your privacy policy or your terms and conditions. There are other authorities on the internet which deemed even setting cookies as necessitating obtaining permission from the user. Are you telling me that collecting very private data under the cloak of a version check does not require obtaining permission?

Again, my point was and will always be: you’re abusing your power, you are despicable people, and you fail to inform people of what you actively collect from everyone’s servers. You were given trust enough to allow your code to run on servers which very easily could leak other important things like usernames and passwords since your plugin has access to everything wordpress has.

In fact, allow me the question: if “many other plugins” installed a rootkit on machines that do not belong to the company who developed the product, would you do it too, because it’s normalized?

Give it some more thought, come back with a reply that isn’t an insult to injury.

You seem to have a limited understanding of how the automatic update system AND licensing of Gravity Forms work and what is involved in delivering updates and enforcing licensing.

The version check is not a simple version check to determine if an update should be made available or not. It is much more complex than that and is not simply an update check. It is also part of our licensing system as Gravity Forms is a commercial product.

I’d be happy to break down why some of the information that is sent via the update check is sent and why it is necessary. Updates are much more advanced and complex than simply delivering an update if the current version number is higher than the installed version number. We don’t collect information just to harvest data. We collect information for advanced update delivery and licensing purposes.

First off you seem to be under the impression that update checks are triggered on every WordPress page load. This absolutely is not the case. The update checks are triggered by WordPress itself and only occur at certain points during the day. With millions of active Gravity Forms installs if every site was checking for updates on every single WordPress page load we would be DDoSing ourselves with all the incoming traffic from update checks. We most definitely aren’t doing this as it would be detrimental to our server health to do so. Update checks occur on a limited basis and not on every WordPress page load.

Second, the update checks are tied to a licensing system and are part of our license enforcement system. License enforcement determines if you are eligible for updates or not. So the update checks not just deliver updates but are also part of the license enforcement system. If your Gravity Forms license is only able to be utilized on a single site we would need to know it’s already being used on a single site in order to enforce said licensing. Again, Gravity Forms is a commercial product that involves software licensing to utilize.

As far as some of the information that you seem to think isn’t information we would have any need for… again, you have a limited understanding of what is involved in reliably delivering updates to millions of sites. It’s not simply based off version numbers.

I will use some of the examples in your post above where you question why we would need certain site information below…

WP Version: Why? For compatibility reasons. We need to make sure the version of WordPress you are running is compatible with the Gravity Forms update that is available. Otherwise if you execute an update and there is a compatibility issue it would lead to errors.

PHP Version: Why would we need this? Easy. For the same reasons we need the version of WordPress. To make sure the update we are delivering is compatible with the version of PHP your site is running.

MySQL Version: See PHP and WP above. Same reasons. Because WordPress is self-hosted and we have no control over the server environment we need to know information about the environment in order to be able to deliver updates reliably. If we deliver an update that isn’t compatible with your version of WordPress, PHP or MySQL this could pose serious issues for your site and result in downtime.

Admin name/email: This is so that we can notify the site admin if there is an issue or conflict with executing an automatic update. For example, if the update is unable to be run due to the fact there is a known conflict with the WP version, PHP version, MySQL version, any of the plugins they may be running, or any other factor we can automatically trigger a notification to the admin making them aware of the issue.

Plugins: Why would we need to know which plugins are you are running? So that we can make sure you don’t execute an update with a known conflict or compatibility issue with the Gravity Forms update that is being delivered. There are also times where there are version dependencies on updates. Meaning we may release a version of the Gravity Forms Stripe Add-On that requires the latest version of Gravity Forms itself to be already installed. We can’t do this without knowing the plugin information for the site requesting updates. And we can’t hardcode all the necessary plugin information within Gravity Forms as that would be an unreliable way to manage dependency and compatibility checks… It makes more sent to handle this check on the update server end where the most up to date information can be utilized to determine if the update can reliably be delivered.

Multisite: We are notified as part of the update check if a site is a multi-site/WPMU install as part of our license enforcement as WordPress Multi-Site is only supported by our Elite License tier.

Our automatic updates are also more advanced than simply delivering updates to all sites that check for updates. We have the capability to stagger the availability of updates if we choose to do so. Meaning we may make updates available to a smaller subset of users initially based on a variety of criteria such as which WordPress plugins or Gravity Forms Add-Ons they are also using.

For example we could decide for a major update that we only want to make it available to sites NOT running any Gravity Forms add-ons initially before rolling it out to all sites. Without knowing the plugin information when an update is requested… this would be impossible.

I’ve mentioned it multiple times now but it needs to be emphasized repeatedly that our automatic update system is much more intelligent than current Gravity Forms version number being lower than the automatic update Gravity Forms version number. Again, we are a commercial product and provide updates to millions of sites in a much more advanced way.

As for why we need information such as the web site URL and domain? Easy. Gravity Forms is a commercial product and licensing is done based on number of sites. We provide an interface for our customers to see which sites their Gravity Forms license is currently installed on and they have the ability to revoke a license on a site if they choose to do so. This allows customers to manage the web sites that their Gravity Forms license is being used on. This would be impossible if we didn’t have this information. This is part of the customer site management capabilities provided by the My Account section of the Gravity Forms web site itself. Which allows you to see all of your Gravity Forms licenses and manage the sites that are using those licenses. If we did not have this information we could not provide our customers with these capabilities.

Other information such as the language locale (ex. en_US) is for delivery of localization translation files. Gravity Forms and our Add-Ons are professionally translated and we provide a variety of translations which are delivered based on the site language that is configured. This is also how updates are delivered for the translation files so that they can be updated independent of the core Gravity Forms plugin or individual Add-Ons.

The update check payload is pretty much identical to what is used by WordPress itself when it checks for updates with the WordPress.org update server and what all commercial WordPress plugins and themes do in order to deliver updates to sites.

Automatic updates are NOT a simple version check. And in the complexities of licensing on top of this and more information is needed from a licensing standpoint.

The recurring theme here is Gravity Forms is a commercial product that our customers pay to utilize and the information that is included as part of the update and licensing API is information that we as a company have deemed necessary to provide a reliable product and a high level of service to our customers. With all of that being said we have a track record of well over a decade of doing just that.

2 Likes

Hello Carl,

Thanks for putting effort into your reply.

To sum up your reply: you simply beat around the bush until you finally caved in and said “this is a commercial product” - meaning you want to make sure no one steals from you. Which, by the way, is the most pathetic thing you could do when distributing source code. You will never prevent theft, you will only manage to make it harder for actual clients to do their thing.

Yes, it is a commercial product, but that does not imply rights to steal information from paying customers in the name of revenue loss prevention. Since you threw some mud at wordpress, try reading up on rule #7 of plugin publishing.

  1. I’m an admin of my own site, I run my own server or at the very least rent web space from a company. You need to notify me and ask for my permission to pull data from my server, because that data is not yours, not part of your plugin.
  2. The version check is really as simple as it sounds, and I’ve already explained it - it seems it didn’t quite stick. It is absolutely possible to have version checks without collecting and storing data that does not belong to you.
  3. You don’t need WP version, PHP version, MySQL version, my name or email, or a full list of plugins both active and inactive. That’s a big hole in your explanation by the way, if you only wanted to make sure it’s not going to bump into plugin X which runs on my site, you only need active plugins, not ALL. And if all you want to do is notify the admin of incompatibilities, you already know how to do that: dashboard notifications. They work really well, because I’m actually in the middle of interacting with my site. You also don’t have to worry about your emails ending up in my spam folder, and so on. Who are we kidding here? You just want a leg up if you were to ever need to take some kind of legal action against someone who steals. But anywho, I played your game, gave you alternatives.

How would you do all the fancy updating your speak of? To quote you, “Simple!” You just let the information flow the other way. You still have to maintain a list of incompatible addons and server software version, so there is 0 extra effort to simply push them to the client rather than sucking in information you don’t own to provide the same functionality. Ask your developers, they’ll tell you.

  1. If your plugin didn’t check for updates at every page load of the specific URL I pasted, I would have not bothered to edit your source code to make it quit. Every refresh took me 30 seconds. That’s just insane. You need to rethink your timeouts - if a reply wasn’t received from your server in 2-3 seconds, then just let it be. Better luck next time, don’t waste people’s time.

In closing: what you consider absolutely necessary, and that certain things would be impossible without the current system is unfortunately just a bit of ignorance on your part. Which is fine, we all live and learn.

To address your main point: fear of not being solvent if you give up the tight leash on your client’s stolen data.

It’s bullshit. Wake up and smell the roses. If I were trying to hack up your plugin and distribute it for free, there’s nothing to stop me. You didn’t encrypt your source code, it’s freely editable. You think a simple sed + regex pattern would be terrible effort to stop your plugin from calling home? Seriously, you need to re-evaluate how you do this. Yes, it sucks, I know. But remember, many people like your product and use it. They need you to stay solvent because they either don’t have the skill to code up your plugin or they just don’t want to put in the effort. Whatever the case, it’s those people you need to be worried about. You need to make them comfortable, show them that you appreciate them as much as they do you. If you’re collecting data behind their backs while attempting some weak excuse like “our version checks are advanced and exactly the same as wordpress.org”, you’re going the wrong way.

Yes, it’s a product you pay for. Yes, everyone should make money to put food on their family’s table. But you can make that money by robbing banks, too, you know. Keep it simple, stop snooping on the people who pay you in the hopes that you might catch an occasional abuse or theft which you cannot afford to take legal action against - I’m not saying you’re poor, I’m saying it’s a terrible investment to sue a developer who makes $15/hr.

Simple activation code, once, nice and easy, now you have the site that the plugin was activated on, and you let the dev know that you’ll be collecting this and that information as part of the activation process. Be extra nice, and push back a hash from your server which hopefully isn’t where you store payment history, account email and passwords. That way your plugin just adds &hash=uniquehashhere in the GET request for the version check. Then your server can tell the product it has however long until it loses premium features or if it should turn them off because the account was closed or what have you.

Again, all these suggestions require a level of respect towards your customers that in the past decade and then some you have not even considered. Maybe it’s time.

I didn’t beat around the bush. I stated clearly numerous times in my reply that this is a commercial product. However, I also clearly explained how and why our update system works the way it does in my detailed response above. I explained how this information improves our ability to deliver updates in a wide variety of situations and scenarios. It’s clear that it doesn’t matter what our response is that you won’t be satisfied. I’m closing out this thread as at this point I’ve explained exactly how our automatic update and licensing system works. The name calling, cursing, and derogatory comments are unproductive and are against our community guidelines (FAQ - Gravity Forms). There are a wide variety of alternative form solutions to utilize. Maybe it’s time for you to do so.