Homekeyboard_arrow_right Wordpress Maintenancekeyboard_arrow_right Legacy Wordpress Code Security Risk
circle

We still get password resets from a client we left years ago

Developer holding a sticker that reads My Code Works I Have No Idea Why, representing the risks of unmaintained legacy WordPress code

Years ago, we built a custom competition entry and judging platform for a large organisation. The brief was straightforward: allow the public to register and submit entries through Gravity Forms, give a panel of judges secure backend access to review submissions, and provide a weighted scoring system that would determine the eventual winner.

We designed and developed the entire system on WordPress. The registration flow was powered by Gravity Forms, but the judging interface, scoring logic, and results management were all custom code. We wrote it specifically for their requirements and maintained the platform for many years after launch.

Over the years, staff change. New people come in, familiar faces move on, and eventually the organisation decides who they want to work with going forward. You are not always included in that decision, and that is how the industry works.

The emails that keep arriving

To this day, we receive password reset notifications and WordPress update notices from this organisation. Across what appear to be multiple subsequent builds of the site, including development server instances and new live environments.

Someone, at some point, rebuilt or duplicated the site. Then did it again. And again. Each time, our original administrator email address came along for the ride. Nobody ever removed it.

This means our credentials, or at least the email address tied to an account with elevated access, have been copied across multiple environments over a period of years. That alone is a problem. But it is what this reveals about their broader approach to security and code management that concerns us.

What this tells us about the code

If the team managing this system has been loose enough to leave a former developer’s email address attached to an administrator account across multiple builds, it raises a serious question: what else has been overlooked?

The custom code we wrote for the judging and scoring system was built many years ago. It was functional, tested, and fit for purpose when we delivered it. But that was then. WordPress, PHP, and the broader security landscape have changed significantly since then.

Custom code requires ongoing maintenance. It needs to be reviewed against current WordPress coding standards, tested for compatibility with newer PHP versions, and audited for vulnerabilities that may not have existed when the code was originally written. Based on the evidence that our login details have never been cleaned up, it is reasonable to conclude that the custom code itself has never been properly audited or updated either.

This is not an uncommon situation. We see it regularly when businesses engage us for WordPress security audits. Legacy code sits untouched in production environments for years, accumulating technical debt and security risk with every WordPress core update that rolls past it.

Why we never told them

When a client engagement ends, the responsibility for that website transfers entirely to the client and whatever team they bring in next. You deliver the project, hand over dox and credentials, and move on. The ongoing management of user accounts, security, and code maintenance became their concern from that point forward. We had no contractual relationship, no obligation, and no invitation to audit what they were doing after we left.

There is also a practical reality here. Reaching out to a former client to tell them their current development team has been negligent is an awkward conversation at best. It can come across as a sales pitch, a criticism of their chosen vendor, or an overreach from a party that is no longer involved. None of those outcomes are productive.

The first time a password reset email landed in our inbox, we noticed it. By the tenth time, it had become background noise. The emails kept arriving. We kept ignoring them. And every single one served as a quiet reminder that somewhere out there, a system we built years ago is still running, still unaudited, and still carrying credentials that should have been revoked the week we walked away.

Why legacy custom code is a security risk

There is a meaningful difference between a standard WordPress plugin and bespoke custom code. Plugins from the WordPress repository, when actively maintained, receive security patches, compatibility updates, and community review. Custom code receives none of that unless someone deliberately maintains it.

Here is what typically happens to unmaintained custom code over time:

Outdated PHP functions. PHP evolves. Functions that were standard practice five or six years ago may now be deprecated or removed entirely. Code that relies on these functions can break silently or, worse, introduce vulnerabilities when running on newer PHP versions.

Missing input sanitisation. Security best practices for handling user input in WordPress have become significantly more rigorous. Older custom code may not sanitise or escape data to current standards, creating potential injection points.

Hardcoded credentials and paths. Developers sometimes hardcode database credentials, file paths, or API keys during development. If the code was never refactored for production, those values may still be exposed.

No nonce verification. WordPress nonces protect against cross site request forgery. Older custom code may not implement nonce checks on form submissions or AJAX requests, leaving the application open to CSRF attacks.

Gravity Forms itself has had vulnerabilities. This is the plugin at the heart of the registration system we built. In November 2025, a critical vulnerability (CVE 2025 12974) was disclosed in Gravity Forms, allowing unauthenticated attackers to upload executable files through a legacy chunked upload mechanism. The flaw existed in all versions up to and including 2.9.21.1 and carried a severity score of 9 out of 10. If the organisation running our old system has not updated Gravity Forms, they could be running a version with a known, critical exploit, or one of the many addons it required could also be open to security issues.

The compounding problem of neglect

Each layer of neglect compounds the risk:

  1. Legacy custom code that has never been audited sits alongside the core WordPress installation.
  2. WordPress core may or may not be up to date. The update notices we receive suggest development environments are being spun up, but whether those updates are applied to production is unknown.
  3. Gravity Forms, as a premium plugin, requires an active licence for updates. If the licence has lapsed, the plugin may not have received critical security patches.
  4. Administrator accounts from former developers remain active, giving potential attackers additional credential targets.
  5. Development server URLs and configurations are being shared with external email addresses, leaking information about their infrastructure.

This is what technical debt looks like in practice. It is not theoretical. It is a former developer still receiving admin level notifications from a production system years after the engagement ended.

What should have happened

The fix for every single one of these issues is straightforward. None of it is expensive or technically complex. It simply requires someone to care enough to do it.

Audit all user accounts. After any developer handover, every user account in WordPress should be reviewed. Remove accounts that are no longer needed. Change passwords for any accounts that remain. This takes minutes.

Remove former developer email addresses. The admin email address in WordPress settings and any user accounts tied to previous developers should be updated immediately when the relationship ends.

Commission a code audit. Any custom code inherited from a previous developer should be professionally reviewed. At minimum, check for deprecated functions, missing sanitisation, hardcoded credentials, and compliance with current WordPress coding standards.

Update all software. WordPress core, all plugins including Gravity Forms, and the active theme should be updated to their latest versions. If a plugin licence has lapsed, renew it or replace the plugin.

Test in staging before deploying. The development server instances we keep hearing from suggest they are building new versions of the site. Good. But the fact that our email persists across these builds means the staging process is not including a security review.

Implement ongoing maintenance. A site that handles public competition entries and stores judge credentials is not a set and forget project. It needs regular updates, security monitoring, and periodic code review. This is exactly what WordPress maintenance plans are designed to deliver.

What this means for your business

If you have inherited a WordPress site from a previous developer or agency, ask yourself these questions:

  1. Do you know every user account that exists in your WordPress installation?
  2. Has the custom code on your site ever been reviewed by someone other than the original developer?
  3. Are all your plugins actively maintained and fully up to date?
  4. Could a former developer still receive password reset emails from your site?

If the answer to any of these is no, or if you are unsure, you have a problem. It may not be urgent today. But technical debt accrues interest, and in the context of website security, that interest is paid in data breaches, downtime, and reputational damage.

We recently wrote about what a routine WordPress backup revealed: five year old malware sitting quietly in a client’s site. Nobody knew it was there. The same pattern applies here. The risks are invisible until they are not.

Time to cross the t, and dot the i

To be clear, we had a great relationship with this organisation. We built something for them years ago and it served them well enough that they continue to use the underlying system. That is a compliment to the original work.

But the fact that we still receive their password reset emails in 2026 is not a quirk. It is a symptom. It tells us that nobody is really minding the shop. And when nobody is minding the shop, the code rots, the vulnerabilities accumulate, and one day, something breaks badly.

If your WordPress site is running on inherited code, particularly custom development work from a previous agency, get it audited. Remove old accounts. Update your software. Bring in someone who can look at what is running under the hood.

We would rather write about this as a cautionary tale than read about it as a breach notice.

Photo by RealToughCandy.com