Solving WordPress’s Pathological Plaintext Problem: Introducing Fortress Vaults&Pillars

At Snicco, we’ve been tirelessly vocal about a dangerous, often ignored practice in the WordPress community for far too long:

The negligent habit of storing sensitive data in plaintext in the WordPress database. A ticking time bomb, hiding in plain sight within countless WordPress sites. A problem continually brushed under the carpet by many in our ecosystem.

Why is this still happening?

Some vendors simply aren’t concerned enough. For others, the issue isn’t even on their radar.

And for the community – the feeling of being overwhelmed is all too familiar. Information overload can make it tempting to bury your head in the sand, hoping the problems will just disappear.

Recently, we’ve been peeling back the layers of some uncomfortable truths about WordPress Security.

But we’re not here to add to the confusion or fear. Instead, we’re committed to reversing this trend and offering you a powerful solution: Fortress Vaults & Pillars, and the best part? You can get access to it… for FREE.

A Chilling Tale And A Shimmer Of Hope: The $70k Stripe API Key Theft

A recent incident involving a WordPress Agency owner ignited a wave of concern throughout the WordPress community, jolting many into a harsh reality.

Here’s the story in brief:

The agency owner used Stripe as their payment processor and the AccessAlly LMS plugin on their site to facilitate transactions. A cybercriminal managed to access the agency’s Stripe API keys, proceeding to misuse them to commit a staggering $70,000 in financial fraud. Ultimately, Stripe tried to hold the agency accountable for the monetary loss.

The agency owner courageously shared their horrifying experience:

“[…] it is a huge, huge risk to your business. So not only has this been like a financial burden to me, it’s cost me about $10,000 and missed student payments, legal fees, bank fees costs to switching over my e-commerce website from Stripe to a merchant account…”

Shannon Matter: My Stripe Account Was Hacked and Stripe Said I Have To Repay $70K

While the specifics of how the hacker got their hands on the API keys remain speculative, the incident undeniably underscored the gravity of storing sensitive data in plaintext in the WordPress database.

Stripe, too, shares some of the blame, given their support for “God” API keys, which allow high-privilege actions, like creating a new Stripe-Connect Account, instead of mandating the use of their newer, restricted API keys.

Regrettably, storing API keys in plaintext is not an isolated practice – it’s disturbingly widespread across major players integrating with Stripe in WordPress, spanning E-Commerce, LMS, Membership, Donations, you name it.

SQL-Injection is a known attack vector that could expose these keys. Despite the potential risk, most vendors argue with some variation of:

“If there’s no SQLi, everything is secure; our plugin does not have SQLi vulnerabilities; hence, it’s not an issue. Right?”

The above is little more than wishful thinking, especially in the WordPress ecosystem where SQLi is still rampant.

Numerous major plugins had vulnerabilities that, if exploited, could have provided unauthorized access to the API keys. These cases are not isolated but a common occurrence across every major plugin category integrating with Stripe:

  • WooCommerce in July of 2021.
  • WooCommerce payments in March and June of 2023.
  • Easy Digital Downloads in January and May of 2023.
  • TutorLMS in May of 2023.
  • PaidMemberShip Pro in January of 2023.
  • GiveWP in January of 2023.

Our intention isn’t to blame plugin authors or point fingers – to our knowledge, most of these vulnerabilities have been promptly patched. Even WordPress Core isn’t immune to SQLi vulnerabilities, with the most recent one surfacing in January 2022. Vulnerabilities happen; it’s a part of software development.

However, these incidents should have served as a wake-up call, a pressing invitation for a thorough re-evaluation of the plugin’s threat model. And yet, despite fixing the immediate vulnerabilities, the broader, glaring risk of storing API keys in plaintext went largely unaddressed.

Every vendor should have had a moment of stark realization:

This vulnerability could have laid bare our users’ Stripe Keys to the world. We must radically reinforce our security practices to guard against future SQLi vulnerabilities, be it from our plugin or others on the site.

When news of the $70k fraud broke, it should have been the decisive, resounding alarm signaling the urgent need for change. Users, understandably concerned, reached out en masse to their plugin vendors with demands for change.

The outcry was so profound that we dared to hope it was finally, universally understood that change wasn’t just necessary but imperative…

The Post-Incident Aftermath:
Ignorance or Indifference?

Despite the shockwaves this incident sent throughout the WordPress community, the response from vendors was, at best, lukewarm. Rather than recognizing it as a severe threat demanding immediate attention, most dismissed it as an unfortunate anomaly — an isolated incident that didn’t reflect on the broader ecosystem.

In fact, the security practices concerning API keys (and other sensitive data) essentially remained unchanged.

Instead of listing all the vendors who chose to maintain the status quo, we’d like to highlight notable instances where vendors did step up:

  • As of version 5.0.0, FluentForms encrypts Stripe API keys in their Stripe Add-On.
  • … Are you a vendor that now securely stores Stripe keys? Reach out to us, and we’ll add you to this list.

This whole situation raises a critical question:

Was it ignorance? Were these vendors unaware of the security risks of storing API keys in plaintext? Did they fail to grasp the far-reaching implications if these keys were to fall into the wrong hands?

Or was it neglect? Were they cognizant of the risks but chose to ignore them? Was the cost or effort of implementing a more secure method deemed too high, or was the likelihood of a repeat occurrence considered too low to warrant action?

We found ourselves at a crossroads. Should we continue to wait and hope for the plugin vendors to step up, or should we take matters into our own hands?

The answer quickly became apparent. Driven by the realization that we had the expertise, understanding, and determination to build a solution that the WordPress community deserved, we couldn’t stand idly by.

A solution like Fortress Vaults & Pillars wouldn’t be necessary in an ideal world. Plugin vendors would prioritize security as much as functionality. However, idealism often falls by the wayside amid urgency and risks.

Recognizing the need for a solution to safeguard API keys and other sensitive data — without leaving it to the vendors’ whims or capabilities — we realized we could not stand on the sidelines. If the necessary improvements weren’t going to come from vendors, we resolved to be the catalyst for that change…

Inside Vaults & Pillars: How It Works

Vaults & Pillars is a brand new module of Fortress’s WordPress Security Suite, specifically designed to tackle the issue of sensitive data storage in WordPress.

Fortress Vaults

Vaults provide a secure, encrypted storage space within the local WordPress database for sensitive WordPress options. This includes information such as:

  • Stripe/Payment gateway keys.
  • SMTP/Transactional email keys.
  • Custom Plugin/Theme API Tokens.

These, if compromised, lead to serious security breaches.

Vaults are encrypted using Fortress’s Libsodium-based encryption protocol, and the encryption key is one of Fortress’s Secure Secrets. This guarantees that there is no way to recover the plaintext data short of the entire web server being compromised.

Fortress Pillars

Pillars, conversely, manage highly security-critical configuration flags and lock options that are pivotal for the integrity of your WordPress site. These aren’t stored in the database but are defined in the Fortress configuration and loaded into the WordPress environment upon initialization.

In WordPress, critical configuration settings are stored in the database for convenience. This practice, however, is a significant security risk if a vulnerability is exploited or an account is compromised. Consider the combination of the users_can_register option, which controls whether a WordPress site permits front-end user registration, and the default_role option, determining the default role for new users.

Hackers often manipulate these two settings, first enabling registration, then setting the default role to administrator, thereby taking over sites.

In more security-focused ecosystems, alterations to these settings would necessitate deploying a new version of the application. Fortress Pillars bring this level of robustness to WordPress.

Are you a developer wanting to delve deeper? Explore our comprehensive technical documentation for a more detailed explanation.

Why Vaults & Pillars is a Game Changer

The unique design of Vaults & Pillars enables seamless interaction with WordPress. While an option is stored encrypted (in a Vault) or immutable (as a Pillar), WordPress always receives the “real” value from Fortress. Effectively, Vaults & Pillars operates as a hidden translation layer between WordPress Options API and the database, ensuring the smooth operation of your site while significantly enhancing its security.

Here’s why this is a game changer – Vaults & Pillars can secure ALL sensitive data from third-party plugins while retaining full functionality.
All this without requiring a single line of code modification in WordPress Core or plugins.

In the upcoming section, we’ll walk you through integrating Vaults & Pillars with an actual WordPress site.

Putting Vaults & Pillars to Work: A Step-by-Step Guide To Secure WooCommerce

In this walkthrough, we will unveil the capabilities of Vaults & Pillars by securing all of WooCommerce’s sensitive configuration data with just a few lines of JSON.

Before we dive in, let’s clarify the setup we’ll be using for this demonstration:

  • WordPress: 6.2.2
  • WooCommerce: 7.9.0
  • WooCommerce Stripe Gateway: 7.4.2

For authenticity, we will configure the WooCommerce Stripe Gateway to use real Stripe test keys (please note that these keys will have been invalidated by the time of publication).

Assessing the Insecure Status Quo

A screenshot of the WooCommerce
Payment Settings Tab that shows that Stripe has been configured succesfully.

Upon configuring the WooCommerce Stripe Gateway, the wp_options table contains a new row: the woocommerce_stripe_settings option.

A screenshot of TablePlus showing that the wp_options table contains a row with the option name "woocommerce_stripe_settings".

The option is a large multidimensional array, which WordPress stores serialized in the database. Let’s now inspect the option_value more closely using WP-CLI.

wp option list --search=woocommerce_stripe_settings --format=json --unserialize | jq '.[].option_value'

The above command generates the following output. Lines 8 and 12 raise an alarming issue – The sensitive Stripe Credentials are stored in plaintext.

{
  "enabled": "yes",
  "title": "Credit Card (Stripe)",
  "description": "Pay with your credit card via Stripe.",
  "api_credentials": "",
  "testmode": "yes",
  "test_publishable_key": "pk_test_51HFiwWH81jF8atYWxiXE8xOSg6tkkcGYACQ8eefrEwbzJJm0lRcu7DAFS1R9wjbjSAWbWYrgT6Q9MkTqYf68HaKK00pGQUgpLu",
  "test_secret_key": "sk_test_51HFiwWH81jF8atYW3aEvVtkxnYPKZ65jYiuJ96Ph3gIPOgoVfq8T0A23wgVFWiKFfRwPg09aC43QI0uSMsiAVuhF00IG2FdF0s",
  "publishable_key": null,
  "secret_key": null,
  "webhook": "",
  "test_webhook_secret": "whsec_qKt5Os1gO2Pebcn36qhxicw1ujXhLgP4",
  "webhook_secret": null,
  "inline_cc_form": "no",
  "statement_descriptor": "",
  "short_statement_descriptor": "",
  "capture": "yes",
  "payment_request": "yes",
  "payment_request_button_type": "buy",
  "payment_request_button_theme": "dark",
  "payment_request_button_locations": [
    "product",
    "cart",
    "checkout"
  ],
  "payment_request_button_size": "default",
  "saved_cards": "yes",
  "logging": "no",
  "upe_checkout_experience_enabled": "no"
}

These sensitive keys, if compromised, can be weaponized in a variety of harmful ways:

  • Commit financial fraud, as mentioned above.
  • Delete all your customers in Stripe.
  • Erase all your subscriptions.

The list goes on.

Equally sensitive is the Webhook Secret. This is a unique identifier that WooCommerce utilizes to verify that Stripe Webhooks are genuinely originating from Stripe. In the wrong hands, the Webhook Secret becomes a mask, transforming any intruder into Stripe in the eyes of your WooCommerce site.

It’s clear as day; this is a glaring security loophole.

We’ll now throw Vaults & Pillars into the mix.

Adding Vaults: Eight Lines of JSON Are All You Need

Eight lines of Fortress’s JSON configuration are all it takes to transform your WooCommerce site’s security with Vaults & Pillars.

The comprehensive technical documentation for the same can be found here.

{
  "vaults_and_pillars": {
    "option_vaults": {
      "woocommerce_stripe_settings.test_secret_key": {},
      "woocommerce_stripe_settings.test_webhook_secret": {}
  }
}

Next, we employ the Fortress CLI to encrypt all Vaults using the following command:

wp snicco/fortress vnp options:seal-all
Screenshot of the Fortress CLI with a command to encrypt all Vaults.

Now, let’s peek once again at the contents of the woocommerce_stripe_settings option.

wp option list --search=woocommerce_stripe_settings --format=json --unserialize | jq '.[].option_value'

We have now removed any trace of the highly sensitive Stripe Credentials. The respective sub-settings are now Vaults, indicated by them starting with FORTRESS_VAULT.

{
  "enabled": "yes",
  "title": "Credit Card (Stripe)",
  "description": "Pay with your credit card via Stripe.",
  "api_credentials": "",
  "testmode": "yes",
  "test_publishable_key": "pk_test_51HFiwWH81jF8atYWxiXE8xOSg6tkkcGYACQ8eefrEwbzJJm0lRcu7DAFS1R9wjbjSAWbWYrgT6Q9MkTqYf68HaKK00pGQUgpLu",
  "test_secret_key": "FORTRESS_VAULT|MUIEAD0AhOZnwky83hGEMDhLZEeNhowkQ9aYIT66R15HtRE9btXjyev6LIH79nmDHdlqvQQaKc46WokNJjn3RrEcR6K3qTZTUImLjVJgZXumoZTAaiCjLN4iZLxe1EBPsOfs24ckzj-e98MjUWDHfCTYG0T7Xzs5Qz2JQdLI-qGAxdwq6WC9qQ2qJUcBpFulL-5Xxs3yxojJGVTJj4THHb8AMkikh9OxwS3WXC5NDnwvdbQdYlcELF9WG4JX2jUxB0nJZ69kIcf4MRVD9RuYHlQuFGQVYeIzGPS6Oa307xNvN_5KpHkSlZxsAy4qx9M3",
  "publishable_key": null,
  "secret_key": null,
  "webhook": "",
  "test_webhook_secret": "FORTRESS_VAULT|MUIEAPL6WefPSdkPFPNTxNpNOCAtL1Hc4B2ucq2s2RKvTYTDRrsqnKXg6ZEsnS3eQFG3puHlaJ2Qz6YkMcORG6wzYQR3_2iYoOR90iivbUTR7rzPXi_BI6kbXEqDfys6w260agf4HRABChR2ubgqJnKEcG2E2cOEjPJ_hXWkzOAkUgweDJ8BcA5yAZDMZQq_DuEYMWSIEjEhQ6y2f9Zlims80gLFbUhX198=",
  "webhook_secret": null,
  "inline_cc_form": "no",
  "statement_descriptor": "",
  "short_statement_descriptor": "",
  "capture": "yes",
  "payment_request": "yes",
  "payment_request_button_type": "buy",
  "payment_request_button_theme": "dark",
  "payment_request_button_locations": [
    "product",
    "cart",
    "checkout"
  ],
  "payment_request_button_size": "default",
  "saved_cards": "yes",
  "logging": "no",
  "upe_checkout_experience_enabled": "no"
}

How can this system still function correctly without the API keys?

Well, let’s conduct a live test and see what unfolds!

A screenshot of the Woocommerce Checkout page with a virtual product just before clicking the Buy Now button.
Here’s a WooCommerce product we created for this experiment. We’re about to purchase it using Stripe’s test credit card.
A screenshot of the WooCommerce Order Received page signaling that the order completed.
Voila! The order was successfully processed on WooCommerce.
A screenshot of the Stripe Dashboard with the new payment signaling that the order completed.
And just like that, the payment confirmation appears on our Stripe dashboard.

Despite the absence of API keys in the database, everything operates smoothly. It’s as if the keys never changed, and the beauty of it? Not a single line of WooCommerce code had to be altered.

mindblown
Intrigued about how this magic unfolds behind the scenes? Dive deeper into our developer docs to learn more.

There’s one final detail we need to address, and it’s a significant one.

Unfortunately, WooCommerce permits anyone with the manage_woocommerce capability to view the Stripe Keys directly in the admin dashboard.

Screenshot of the WooCommerce Edit Account keys modal, which still shows all plaintext secrets.
Access this screen by navigating to WooCommerce > Settings > Payments > Stripe > Settings > Edit Account Keys.

This includes the Shop Manager role. The last thing you’d want is someone with managerial access to your store having the keys to the proverbial kingdom — especially when those keys could be used to ruin your business.

Time for a quick fix.

With Vaults & Pillars, we can tap into a handy WordPress hook, allowing us to selectively alter and sanitize the option’s “real” value. We can create a simple must-use plugin to scrub those secrets clean when fetched for the admin dashboard UI.

<?php
/*
 * Plugin Name: No Insecure Stripe Keys.
 */
declare(strict_types=1)

use Snicco\Enterprise\Fortress\VaultsAndPillars\Core\Event\ReturningOptionRuntimeValue;

add_action(ReturningOptionRuntimeValue::class, function (ReturningOptionRuntimeValue $event) :void {

    // Only process to the relevant option.
    if ('woocommerce_stripe_settings' !== $event->option_name){
        return;
    }

    // Only customize for GET requests that retrieve keys in the admin dashboard.
    if (
        $_SERVER['REQUEST_METHOD'] !== 'GET'
        || !str_starts_with($_SERVER['REQUEST_URI'],'/wp-json/wc/v3/wc_stripe/account_keys')
    ){
        return;
    }

    $real_secret_key = $event->wordpress_runtime_value['test_secret_key'];
    $real_webhook_secret = $event->wordpress_runtime_value['test_webhook_secret'];

    $event->wordpress_runtime_value['test_secret_key'] = substr($real_secret_key, 0, 10).'_XXXXXXXXXXXXXXXXXXXXXXXX';
    $event->wordpress_runtime_value['test_webhook_secret'] = substr($real_webhook_secret, 0, 10).'_XXXXXXXXXXXXXXXXXXXXXXXX';
});
Screenshot of the WooCommerce Edit Account keys modal, which now, after adding a custom snippet, only shows sanitized Stripe keys.
Now, only the first ten characters of the “real” key are visible. The rest of the secrets are hidden behind placeholder values.

Voila! We’ve just implemented enterprise-grade encryption on the site, and it took less than five minutes. Your business-critical information is now safe and secure without compromising functionality.

Adding Pillars to Prevent Zero-Day Exploits

It’s easy to overlook the seemingly trivial settings that lie buried in your WordPress admin dashboard. Yet, as innocent as they may seem, they can form gaping loopholes in your site’s defenses.

Case in Point: User Registration Control:

  • users_can_register: Controls whether the WordPress site allows user registration in the front end.
  • default_role: The default role for new users without an explicitly assigned one.

The combination of these two options is a known weak spot, exploited by hackers to gain control of sites.

The current defaults are as follows:

Sreenshot of the WordPress Admin dashboard, showing the "Membership" and "New User Default Role" setting.

They state that nobody can register publicly, and new users will be subscribers unless assigned a different role.

But ask yourself: How often have you changed these settings in your typical WordPress project, especially in a live production environment?

The answer is most likely “no.” So why leave this vulnerability open?

As recently as May 2023, a vulnerability within Elementor Pro allowed this loophole to be widely abused.

Let’s fix this by adding two Pillars to the Fortress configuration:

{
  "vaults_and_pillars": {
    "option_vaults": {
      "woocommerce_stripe_settings.test_secret_key": {},
      "woocommerce_stripe_settings.test_webhook_secret": {}
    },
    "option_pillars": {
      "users_can_register": {
        "value": "0"
      },
      "default_role": {
        "value" : "subscriber"
      }
    }
  }
}

Let’s now attempt to update the above options on the WordPress Settings page:

Sreenshot of the WordPress Admin dashboard, showing the "Anyone can register" and "New User Default Role" settings.

The "Anyone can register" option is now turned on and the default role is set to administrator. We're about to save the settings.
Sreenshot of the WordPress Admin dashboard, showing the "Anyone can register" and "New User Default Role" settings after our attempt to update the protected settings.

The update did not go through and a dismissable warning message is shown.
The update does not go through, and a dismissable warning message is shown.

This behavior isn’t limited to the admin dashboard. Even an attacker with direct write access to your site’s database can still not modify these options. That’s the power of immutable Fortress Pillars.

Are you a developer wanting to delve deeper? Explore our comprehensive technical documentation for a more detailed explanation.

“Okay, this is fantastic, but what about performance?”

You might instinctively think that introducing an encryption layer could slow down the retrieval of options using WordPress’s Option API functions like get_option, update_option, and so on.

Surprisingly, not only does it not slow down, but it may even speed things up! Here’s why:

1. Smart, Selective Encryption:

Take a look at the stored woocommerce_stripe_settings option:

{
  "enabled": "yes",
  "title": "Credit Card (Stripe)",
  "description": "Pay with your credit card via Stripe.",
  "api_credentials": "",
  "testmode": "yes",
  "test_publishable_key": "pk_test_51HFiwWH81jF8atYWxiXE8xOSg6tkkcGYACQ8eefrEwbzJJm0lRcu7DAFS1R9wjbjSAWbWYrgT6Q9MkTqYf68HaKK00pGQUgpLu",
  "test_secret_key": "FORTRESS_VAULT|MUIEAD0AhOZnwky83hGEMDhLZEeNhowkQ9aYIT66R15HtRE9btXjyev6LIH79nmDHdlqvQQaKc46WokNJjn3RrEcR6K3qTZTUImLjVJgZXumoZTAaiCjLN4iZLxe1EBPsOfs24ckzj-e98MjUWDHfCTYG0T7Xzs5Qz2JQdLI-qGAxdwq6WC9qQ2qJUcBpFulL-5Xxs3yxojJGVTJj4THHb8AMkikh9OxwS3WXC5NDnwvdbQdYlcELF9WG4JX2jUxB0nJZ69kIcf4MRVD9RuYHlQuFGQVYeIzGPS6Oa307xNvN_5KpHkSlZxsAy4qx9M3",
  "publishable_key": null,
  "secret_key": null,
  "webhook": "",
  "test_webhook_secret": "FORTRESS_VAULT|MUIEAPL6WefPSdkPFPNTxNpNOCAtL1Hc4B2ucq2s2RKvTYTDRrsqnKXg6ZEsnS3eQFG3puHlaJ2Qz6YkMcORG6wzYQR3_2iYoOR90iivbUTR7rzPXi_BI6kbXEqDfys6w260agf4HRABChR2ubgqJnKEcG2E2cOEjPJ_hXWkzOAkUgweDJ8BcA5yAZDMZQq_DuEYMWSIEjEhQ6y2f9Zlims80gLFbUhX198=",
  "webhook_secret": null,
  "inline_cc_form": "no",
  "statement_descriptor": "",
  "short_statement_descriptor": "",
  "capture": "yes",
  "payment_request": "yes",
  "payment_request_button_type": "buy",
  "payment_request_button_theme": "dark",
  "payment_request_button_locations": [
    "product",
    "cart",
    "checkout"
  ],
  "payment_request_button_size": "default",
  "saved_cards": "yes",
  "logging": "no",
  "upe_checkout_experience_enabled": "no"
}

Vaults & Pillars takes a strategic approach to encrypting multi-dimensional arrays. Instead of blindly encrypting everything, which could become a performance bottleneck, especially with the large arrays some WordPress plugins store in single database rows, it targets only the truly sensitive information.

This selective encryption significantly reduces the input length and, thus, the time needed for encryption and decryption. When coupled with the Libsodium PHP extension, known for its rapid performance, the process becomes so efficient that the time spent in the encryption layer becomes negligible.

2. Effective Multi-Layered Caching

By default, WordPress’s get_option implementation triggers two cache hits per call to get_option.

Vaults & Pillars only needs one cache hit per request per call to get_option.

The term “cache hits” refers to calls to the WordPress Object Cache. The actual impact depends on the Object Cache plugin being used; it could be a call to Redis/Memcached or ideally an in-memory index lookup.

After an option is retrieved and decrypted once, subsequent calls to get_option with the same option name are instantly returned from an in-memory key-value “cache”.

Benchmark Insights: A Performance Breakdown

Our benchmark testing demonstrated the following:

  • First Call to get_option: Virtually no difference in performance.
  • Consecutive Calls to get_option: Retrieving a Fortress Vault is up to 26% faster.

These differences might seem minuscule, but they can add up, especially when plugins re-fetch the same option dozens of times. The cumulative gains could be significant in a production scenario where the Object Cache might be a Redis or Memcached instance deployed on a different server.

View the complete benchmark here.

Get FREE Access to Vaults & Pillars

Vaults & Pillars is released, production-ready, and already available to all existing customers as part of Fortress.

So how can you get access for free? And why would we even consider giving this groundbreaking technology away at no cost?

Many companies claim to be on a mission to enhance the security of the WordPress ecosystem, with various degrees of substance behind that claim. We have always believed in showing, not telling. Our commitment is evident in:

  1. Disclosing and fixing security vulnerabilities in the open-source
    wp login command. Although it’s technically a competitor to Fortress’s Passwordless Login CLI, we contributed major security protocols and ideas to the open-source package. Despite many hosting companies (our primary target audience) using it for their SSO functionality, we believe in giving back.

  2. Publishing industry-leading security research, each piece taking months to research, write, and edit. We peel back the layers of misinformation in WordPress Security without direct monetary gain and often in the face of criticism from established players wielding a much louder megaphone.

  3. Fixing the entire WordPress 2FA space by disclosing and fixing vulnerabilities in 20+ products. It took months of our time, but it was worth it. Virtually every single WordPress 2FA product now, to some degree, runs on our code or protocols. We’ve secured the entire ecosystem, even if it meant sharing Fortress’s 2FA security protocols.

Giving away Vaults & Pillars perfectly aligns with our mission. It’s a solution to a problem that nobody else is addressing.

But we need your help to achieve this, and we invite you to join us on this vital mission….

Extracting Vaults & Pillars from the Fortress Runtime is far from a simple task. Currently, Fortress is tightly integrated into each hosting company’s server setup, and Vaults & Pillars is just one feature of this complex system. Unlike plug-and-play solutions, turning it into a standalone product would mean extensive codebase refactoring and a complete overhaul of the distribution infrastructure.

We’d need to automate this process to make it repeatable and reliable on every commit/release, ensuring it remains aligned with the main product. In short, it’s a mammoth undertaking that requires significant time, effort, and resources. We are willing to take on this challenge but won’t embark on this journey lightly. It must be a mission that resonates with the community, which is why we have set the following goal…

1,000 Vaults & Pillars Enthusiasts by September 1st, 2023

To turn Vaults & Pillars into a free standalone product, we need to see the WordPress community’s real desire for enhanced security.
We’re still a small company and can’t just assign someone to a task with an uncertain outcome. Every team member plays a crucial role, and diverting resources is a significant decision.
That’s why we’re setting an ambitious yet achievable goal: 1,000 Vaults & Pillars enthusiasts by September 1st, 2023.

It’s an ambitious yet achievable goal, and by reaching it, we’ll know that our mission resonates with you and that the time and resources required will be well-spent.

Bonus for the first 100 people:

For the first 100 to show their support, we offer an exclusive bonus: a recorded deep-dive of configuring Vaults & Pillars featuring real-life examples of user-voted plugins. You’ll see how to secure your favorite plugins chosen by the community and get the plug-and-play configuration to secure your site instantly.

Share this initiative with your network, and let’s build a safer WordPress together. Your voice matters, and it could be the one that turns the tide.

Vaults&Pillars Interest

By submitting this form, you consent to receive marketing communications from us. Rest assured, your data will not be shared with anybody, and you may unsubscribe anytime.


8 responses

  1. Jérémy Franck

    Interesting article, but I *really* don’t appreciate the bullshit emotional blackmail at the end.

    Release it for free, or don’t if you don’t have the means to.
    Ask people to share because better security benefits the whole WordPress community, not because of you’re trying to leverage FOMO.

    And in both cases, whether this is free or not, wouldn’t proper documentation and a configuration guide be the most basic requirement for this to be a serious solution? If you’re recording a deep dive, wouldn’t it be the least you can do to share this resource to all the people who have access to the plugin, so they can configure their site properly? (and not just the first 100)

    Truly a big turnoff for me. If you don’t have the resources to release it for free, that’s understandable. You must have spent a lot of work on this, and not every developer (or team) can invest that amount of work into a pro bono initiative (I’d love to live in such a world, but I understand it might not be possible).

    But don’t pretend “that you need to see if there’s interested”. There’s a whole INDUSTRY built around WordPress security (something you know very well, given the info in the article + the featured article on the homepage + you whole business positioning)
    Playing coy when you very well know there’s interest seems disingenuous and manipulative — not exactly the qualities I’d like associated with my security solution/vendor.

    So, great job on the work itself, would truly appreciate you releasing it for free (or priced in a way that makes it accessible to small website owners and not only huge agencies), but please consider a different approach on how you’re marketing this article / initiative. I would gladly share the article if this point was resolved.

    1. Hey Jérémy,

      We have ~7k words of documentation on this feature that we linked in multiple places in the article.

      Playing coy when you very well know there’s interest.

      We know for a fact that people fall into one of three categories here:

      – It’s completely over their heads. Probably 90%
      – They roughly understand that this is a systemic issue, but sadly, rather stick their heads in the sand. Probably 4.99%
      – People that understand that this is insanely valuable Software. You probably fall into this one. 0.01%

      1. Jérémy Franck

        That adds up to 95% 😉
        But I get your point. Again, I don’t have a problem with the article as a whole, or the wall behind it, nor with the fact that you can’t just make this available for free to everyone on a whim.
        Just the phrasing.

        With that being said… I appreciate you taking the time to answer. It’s making me think that the intention is more genuine than I initially assumed. And, well… you know what they say about assuming. I’m sorry I did.

        So, how can I support this initiative? (other than possibly offering an alternative to a few sentences from the last paragraph for you to consider 🙃)

        1. No worries, it might not have been apparent.

          “So, how can I support this initiative?”

          You can share this post with your WordPress network, whether that be Twitter, Facebook groups, etc.

          Best,

          Calvin

  2. I appreciate the detailed writeup. I’m guessing that any PHP code added to the website has access to the encrypted values. Is that correct, or is there something else in play here?

    Even if so, protecting against SQL injection spilling the beans is a good step to enhance security.

    1. Correct, PHP always has to have access; otherwise, all features will stop working (as long as they are implemented in PHP).

      “Even if so, protecting against SQL injection spilling the beans is a good step to enhance security.

      Correct, or, if you store secrets in the wp-config.php file, against all types of file disclosure vulnerabilities.

      Hardcoded secrets in wp-config.php is just yet another plaintext storage mechanism…

      Pillars also protect against many unauthenticated option update vulnerabilities.

      As always, in security. LAYERS, LAYERS, and more LAYERS.

  3. So I signed up & confirmed. I expected to “get the plug-and-play configuration to secure your site instantly” when I confirmed.

    So far nothing. When will this instantly happen?

    1. Hey Robin,

      “Instantly, after/if we extract out the free version”

      Best,

      Calvin