Drupal 7 reached end of life on 5 January 2025. Since then the Drupal Security Team publishes no advisories or fixes for Drupal 7 core, contributed modules or themes, and drupal.org has wound down packaging, testing and update data. Your options are paid extended support, a migration to Drupal 11 or Backdrop CMS, a static archive, or retirement.
Every one of those options needs the same groundwork first: an honest inventory of the site, its modules, its custom code and the PHP version underneath it. This guide walks through what changed on the end of life date, why a Drupal 7 site gets riskier each month even if nobody touches it, what a vendor in the drupal.org extended support program can and cannot do for you, how the migration paths compare, and how to carry your own patches for an abandoned module without losing track of them.
Key takeaways
- The date is fixed. Drupal 7 security support ended on 5 January 2025; the June 2023 announcement called it "the final extension".
- No advisories does not mean no vulnerabilities. Drupal.org warned that Drupal 7 issues "may be disclosed in public" with no fix attached.
- The PHP ceiling is the hidden deadline. PHP 8.3 is the newest version Drupal 7 supports, PHP 8.4 will not get support, and PHP 8.3 security fixes end on 31 December 2027.
- Extended support buys time, not a future. A vendor in the drupal.org program typically covers core and listed contributed modules, not your custom code, unlisted modules, theme or hosting stack.
- Migrate to Drupal 11, not 10. Drupal 10 reaches end of life on 9 December 2026, the week Drupal 12 is scheduled.
- Backdrop CMS suits some sites. It is a Drupal 7 fork with a built in upgrade path and a four month minor release cycle.
- Hardening is a bridge. Removing the PHP filter module, restricting admin paths and filtering requests reduce exposure while you migrate; they do not replace patches.
- Every exception needs an end date. Without one, "for now" becomes five more years.
When did Drupal 7 reach end of life, and what stopped?
Drupal 7 was first released in January 2011. The drupal.org end of life page says the 5 January 2025 date marked 14 years since that original release. The end of life date moved several times along the way, which is part of why so many sites are still on it: every extension gave owners a reason to wait for the next one.
A dated timeline
| Date | Event | Source |
|---|---|---|
| January 2011 | Drupal 7.0 released | drupal.org end of life page (14 years before January 2025) |
| 25 February 2019 | PSA-2019-02-25 announces end of life for November 2021 and a paid Drupal 7 Vendor Extended Support (D7ES) program | Drupal security announcement |
| 2019 to 2023 | Later announcements push the date back; by mid 2023 it stands at "at least November 1, 2023" | Referenced in PSA-2023-06-07 |
| 7 June 2023 | PSA-2023-06-07 sets end of life at 5 January 2025 and calls it "the final extension" | Drupal security announcement |
| 1 August 2023 | Pre end of life policy changes take effect: some moderately critical and less critical Drupal 7 issues may be fixed in public, unsupported modules cannot regain support, no advisories for unsupported libraries such as CKEditor 4, no PHP below 5.6, no fixes for Windows only issues | PSA-2023-06-07 |
| 4 December 2024 | Drupal 7.103, the final release; its changelog entry reads "So Long, and Thanks for All the Fish" | Drupal 7 CHANGELOG.txt |
| 5 January 2025 | Drupal 7 end of life. No more security or compatibility updates from the community | drupal.org end of life page |
| 9 December 2026 | Drupal 10 end of life, the other deadline migrating teams need to know | Drupal core release schedule |
| 31 December 2026 | PHP 8.2 security support ends | php.net supported versions |
| 31 December 2027 | PHP 8.3 security support ends, the newest PHP that Drupal 7 supports | php.net supported versions, Drupal 7 PHP requirements |
What actually stopped on 5 January 2025
The June 2023 announcement listed what would happen at end of life. In plain terms:
- No more security advisories. The Drupal Security Team stopped providing support or advisories for Drupal 7 core, contributed modules and themes.
- Public disclosure becomes normal. The announcement warned that security issues for Drupal 7 "may be disclosed in public", which means a fix might never come and the description of the problem might arrive before any mitigation.
- No more core commits. The 7.x branch of core stopped receiving commits.
- Releases flagged as unsupported. Drupal 7 releases on project pages are marked as not supported, which is what update status checks and many external scanners read.
- Infrastructure winds down. Drupal.org stopped supporting Drupal 7 documentation navigation, automated testing and packaging. Tarball and zip packaging was switched off, and the announcement said archives may be removed.
- Tooling degrades. The announcement warned that some Drush functionality for Drupal 7 would stop working.
- Scanners flag you. In the announcement's words, "External vulnerability scans will flag Drupal 7 as insecure." Expect that line in your next penetration test or vendor questionnaire.
The end of life page frames the business side bluntly: continuing on Drupal 7 leaves a site exposed and can put compliance with frameworks such as PCI, HIPAA, FedRAMP and SOC 2 at risk. Those frameworks share a theme. NIST SP 800-53 has a dedicated control, SA-22 Unsupported System Components, whose answer is to replace unsupported components or document and justify alternative support. An auditor who sees Drupal 7 will ask which of those two you did.
The changes that started before the deadline
Teams often miss that the support model narrowed 17 months before the end of life date. From 1 August 2023, the June 2023 announcement said:
- Drupal 7 branches of contributed projects already marked unsupported would not be eligible for new maintainers and would not be marked supported again.
- The Security Team would not issue advisories for unsupported libraries that Drupal 7 contributed projects rely on. CKEditor 4 is the example the announcement gives.
- PHP versions lower than 5.6 stopped being supported for Drupal 7.
- Windows only security issues stopped getting Drupal 7 fixes.
- Drupal.org stopped building Drupal 7 distribution packages from Drush make files.
So a site that pinned a WYSIWYG editor library, or ran on Windows hosting, was already partly outside security coverage well before January 2025.
Who still runs Drupal 7, and how do you find it?
Drupal 7 lasted 14 years, and long lived platforms collect long lived sites. The typical remaining estates fall into a few categories:
- Universities and research groups: department, lab and event sites, often on a shared multisite built years ago.
- Public sector and agencies: program sites, consultations and archives where a procurement cycle or funding gap stalled the rebuild.
- Membership and association sites: custom registration, payment or directory modules nobody wants to rewrite.
- Campaign leftovers and intranets: sites never switched off, or assumed safe because they sit behind a VPN.
The common thread is that the remaining Drupal 7 sites are rarely anyone's main job. That makes finding them the first real task.
How to find Drupal 7 in your own estate
Only scan systems you own or are authorised to test. These checks are for building your own inventory.
On the server or in the code repository, three checks settle it:
# 1. The version constant in core (Drupal 7 keeps it in includes/bootstrap.inc)
grep -n "define('VERSION'" /var/www/site/includes/bootstrap.inc
# 2. The changelog shipped in the web root by Drupal 7 core
head -n 5 /var/www/site/CHANGELOG.txt
# 3. Drush 8, the Drush line that runs Drupal 7
cd /var/www/site && drush status
drush status prints the Drupal version, the PHP binary and version, the database driver and the site path, which is most of what the inventory needs in one line each.
From the outside, for sites you own, Drupal 7 core adds a generator meta tag and an X-Generator response header that start with "Drupal 7". A quick check across your own domain list:
while read -r host; do
gen=$(curl -s -m 10 -D - -o /dev/null "https://$host/" | grep -i '^x-generator:' | tr -d '\r')
echo "$host ${gen:-no X-Generator header}"
done < my-domains.txt
Absence of the header proves nothing, because some teams strip it, so pair the header check with the server side checks and with your hosting inventory. Also look at:
- Multisite directories. A single Drupal 7 codebase can serve dozens of sites from
sites/*/settings.php. Count those directories; each is a site with its own database and its own enabled modules. - Staging, test and old preview environments. These are frequently older than production and often public.
- DNS records pointing at old hosting. Subdomains for past campaigns, conferences and departments.
- Backups and database dumps sitting in web accessible directories.
Why a Drupal 7 site gets riskier every month
A site that does not change still decays, because everything around it changes. Four forces do most of the damage.
1. The PHP ceiling
The Drupal 7 PHP requirements page lists support for PHP 8.1 as of Drupal 7.92, PHP 8.2 as of Drupal 7.94 and PHP 8.3 as of Drupal 7.103. For PHP 8.4 it says: "No, will not get support". It also notes that the latest Drupal 7 version is recommended to get full PHP 8 support.
Now read that against the PHP project's own schedule. PHP.net says each branch gets two years of active support and then two years of critical security fixes only. As of 25 October 2026:
| PHP branch | Security support until | Drupal 7 support |
|---|---|---|
| 8.1 | Ended 31 December 2025 | Yes, from 7.92 |
| 8.2 | 31 December 2026 | Yes, from 7.94 |
| 8.3 | 31 December 2027 | Yes, from 7.103 |
| 8.4 | 31 December 2028 | No, will not get support |
| 8.5 | 31 December 2029 | Not listed |
That table is the hidden deadline for any Drupal 7 plan. If you stay on community Drupal 7, the newest PHP you can run stops getting security fixes at the end of 2027. If your site is on PHP 7.4 or 8.0 today, it is already on an unsupported runtime; our post on PHP 7.4 end of life risk and the one on PHP 8.1 and 8.2 support dates go deeper on what that means. Some extended support offerings advertise compatibility work for newer PHP versions; if that matters to your plan, get it in writing for a named PHP version rather than assuming it.
2. Abandoned contributed modules
Most Drupal 7 sites run dozens of contributed modules. Some had no active maintainer even before end of life, and the August 2023 rule meant an unsupported branch could not be adopted back into support. After January 2025 there is no community process at all. When someone finds a flaw in one of those modules, one of three things happens: an extended support vendor fixes it for its customers, someone posts a fix in a public issue or fork, or nothing happens. Your plan has to assume the third case for any module not explicitly covered by a contract.
3. Old front end libraries
Drupal 7 core shipped jQuery 1.4.4 and jQuery UI 1.8, and many sites rely on the jQuery Update contributed module to load a newer jQuery. Old JavaScript libraries carry their own published vulnerability history, separate from Drupal's. The same applies to WYSIWYG editors: the June 2023 announcement named CKEditor 4 as an example of an unsupported library that would get no Drupal advisories. Browser behaviour also moves on, and old admin JavaScript can quietly break in a current browser.
4. Hosting stacks that move on
Linux distributions and managed hosts retire PHP versions, MySQL and MariaDB versions, and old TLS configurations on their own schedules. A Drupal 7 site often ends up pinned to an old operating system image because "the site only works on this one", which turns one unsupported application into an unsupported server. Add Drush 8, the Drush line for Drupal 7, which the Drush project lists as end of life since January 2025, and the toolchain itself becomes a legacy island.
What kinds of risk show up in Drupal advisories?
Advisories for supported Drupal versions are the best guide to the flaws a Drupal 7 site will keep collecting, since much of the design carried forward. The drupal.org advisory list for October 2026 shows the usual categories:
- Cross site scripting (XSS). The most common category by far, usually in modules that render user or editor input, field formatters and themes.
- Access bypass. A module exposes content, files or actions to users who should not see them.
- Information disclosure. Private fields, file paths or configuration leak through a page, a feed or an API.
- Cross site request forgery (CSRF). An admin action can be triggered by a crafted link while an administrator is logged in.
- Remote code execution and PHP object injection. Rare, but the categories that matter most, because they turn a website flaw into a server compromise.
Each advisory carries a risk score from 0 to 25 built from six factors: access complexity, authentication required, confidentiality impact, integrity impact, exploit maturity and target distribution. The labels run from Not Critical (0 to 4) up to Highly Critical (20 to 25). Use the same six factors for your own triage after end of life. When a fix lands on the modern branch of a module you still run on Drupal 7, and the Drupal 7 code looks similar, that fix effectively describes your problem with no Drupal 7 patch attached: score it, then backport, mitigate or accept it. Our Drupal module vulnerability trends post looks at patterns across modules.
What does paid extended support cover, and what does it not?
The Drupal Association runs the Drupal 7 Extended Security Support Provider Program. The end of life page describes it as paid security coverage from "carefully vetted, certified vendors" for sites where migrating was not feasible in time, and links to a list of the vendors currently in the program. We will not name them here; the drupal.org partner page is the authoritative list, and the list has changed over time.
The program's original requirements, published with the 2019 announcement, give a sense of what the Association asked of vendors at the start: a track record of contributing to Drupal 7 in public issue queues, a commitment to stay in the program for a set period, a share of the core and module patch work, a member on the Drupal Security Team, a program fee, and a business that actually provides paid support to clients. The current program terms may differ, so treat those as history and read the current page and each vendor's contract.
What extended support typically covers
The details vary by contract, but offerings in this category usually include:
- Security fixes for Drupal 7 core, released to customers when a flaw is found.
- Security fixes for a defined list of contributed modules, usually the most widely used ones, sometimes with a way to request coverage for others.
- Compatibility work, for example keeping core working on newer PHP versions, where the vendor commits to it.
- Notification, so you hear about a problem and its fix at the same time rather than reading about it in public first.
What it does not cover
This is the part that catches teams in an audit:
- Your custom modules and custom theme. No vendor patches code it has never seen.
- Modules outside the covered list. If your site runs a niche module, ask before you sign whether it is in scope, and what happens when a flaw is found in something that is not.
- Front end libraries your theme or modules pull in, unless named.
- The hosting stack. PHP itself, the web server, the database, the operating system and the TLS configuration are separate supply chains with their own end of life dates.
- Content and configuration mistakes. Over privileged roles, open user registration, a text format that allows PHP, or a forgotten admin account are configuration problems, not missing patches.
- Compliance by itself. An extended support contract is evidence of "alternative sources for continued support", which is one of the options NIST SA-22 names. It is not evidence that the site is secure. Auditors usually want both the contract and a dated migration plan.
Questions to ask a vendor before signing
- Which Drupal 7 contributed modules are covered by name, and how is a module added?
- How are fixes delivered (patch files, a full core release, a private repository) and how quickly after a flaw is confirmed?
- Does the contract cover a specific PHP version, and which one?
- What is the end date of the offering, and what notice will you give before it ends?
- Are fixes shared upstream or with the public after a delay, or only with customers?
- What evidence do you provide for auditors (advisories, change logs, attestations)?
The honest summary: extended support turns an unbounded risk into a bounded one for a period of time. It is the right call when a migration is funded and scheduled but will not finish this quarter. It is the wrong call as a substitute for deciding.
What migration paths exist?
There are five realistic exits from Drupal 7. Most organisations with more than one site end up using two or three of them.
Path 1: migrate to modern Drupal with the Migrate API
Modern Drupal is not an in place upgrade from Drupal 7. You build a new Drupal 11 site and migrate content and configuration into it. Drupal.org's upgrade documentation says the Migrate API "provides services for migrating data from different sources to Drupal 9 (or later)", and the upgrade guide for Drupal 6 and 7 sites covers preparation, choosing an approach, the migrate modules, upgrading through the web browser, upgrading with Drush, known issues and customising migrations.
The pieces you will meet:
- Migrate, Migrate Drupal and Migrate Drupal UI in core. Together they read a Drupal 7 database and files directory and map users, taxonomy, content types, fields, nodes, comments, menus, files and much of the configuration into the new site.
- Contributed helper modules. Migrate Upgrade adds Drush support for upgrading from Drupal 6 or 7 (its 4.0.x branch works with Drupal 9 or later and Drush 9 or later), and Migrate Tools runs and manages the generated migrations.
- Your theme and custom code, which do not migrate. Drupal 7 themes are PHPTemplate; modern Drupal uses Twig. Custom modules need rewriting against the modern APIs.
With Migrate Upgrade installed on the new site, a common first move is to generate the migrations without running them, so you can review and edit them:
drush migrate-upgrade --legacy-db-url=mysql://user:pass@db-host/d7db \
--legacy-root=https://old.example.edu --configure-only
The database URL and site root are placeholders. The --configure-only option writes the migrations as configuration instead of running them; you then run, check and rerun them with Migrate Tools.
Which version to target. Drupal's core release schedule states that Drupal 10 "will reach end of life on December 9, 2026", that 10.6.x is the last Drupal 10 minor, and that Drupal 12 is planned for the week of 7 December 2026. A migration that starts in late 2026 should target the current Drupal 11 minor at the very least, and plan for an upgrade to Drupal 12 in its first year. Upgrades between modern major versions are incremental and far smaller than the jump from Drupal 7, but they are not free.
Effort. The content migration is usually the easy part. The work is in content model changes, the theme rebuild, custom module rewrites, and replacing contributed modules that have no modern equivalent.
Path 2: move to Backdrop CMS
Backdrop CMS is a fork of Drupal 7 that kept the Drupal 7 programming model while modernising parts of it. Backdrop's site says it "has a built-in upgrade path from Drupal 7", and its upgrade documentation says Backdrop was "designed from the outset to offer the fastest, easiest upgrade path from Drupal 7"; the upgrade itself runs through update.php.
What Backdrop documents about itself:
- Release cycle. Minor releases every four months, on 15 January, 15 May and 15 September, with a two week feature freeze before each. Patch releases ship as needed. Major releases, which may break APIs, happen every three years or more, and the release page says no major release is currently planned.
- Security process. Security releases ship after a fix is ready, with embargoed details and advance notice, "concurrent with Drupal when applicable".
- Upgrade steps. Research with a checklist, preparation (remove unused content and features Backdrop no longer supports), then
update.php. The documentation recommends keeping the old Drupal 7 site available for comparison. - Scale. At the time of writing, Backdrop's site lists version 1.35.2 and says it is used by more than 3,600 sites, with over 1,300 modules and add ons.
Where Backdrop fits. A brochure site, a departmental site or a small membership site that uses mainstream modules with Backdrop ports is a good candidate. Custom modules need porting, but the port is much closer to Drupal 7 code than a rewrite for modern Drupal. A large site that depends on many niche Drupal 7 modules without Backdrop equivalents gains less. Backdrop's community is smaller than modern Drupal's, so judge it like any dependency: release history, active contributors, security release speed and hosting support.
Path 3: static export and archive
Many Drupal 7 sites are finished: a past conference, a closed project, an old campaign. Export the rendered HTML to a static site and switch off PHP and the database. With no Drupal left, there is no Drupal module to exploit.
What to check before you export:
- Search, forms, logins and comments stop working. Replace them with nothing, with a hosted form, or with a note.
- Files linked from content need to be copied, and private files need a decision (publish, move behind access control or delete).
- Redirects from old paths should be preserved, for example as web server rules.
- Personal data in user profiles, webform submissions and comments should be reviewed under your retention policy before anything is archived.
Path 4: retire the site
Some sites should simply go. If analytics show little traffic and the content is out of date, archive the database privately for the retention period your records policy requires, publish a redirect to a current page, and remove the site and its DNS record. Retirement is the cheapest and lowest risk path and the one most often skipped.
Path 5: rebuild on a different platform
Some organisations leave Drupal for another content management system or a static site generator. That is a full rebuild; the inventory work below still applies.
Comparison: which Drupal 7 exit fits which site?
| Option | Cost | Effort | Remaining security risk | Audit evidence you can show |
|---|---|---|---|---|
| Migrate to Drupal 11 | High up front, normal running costs after | High: new theme, custom code rewrite, content model work | Low once live, on a supported core with monthly security windows | Supported version, advisories, update records |
| Move to Backdrop CMS | Medium | Medium: module ports and theme updates, same data model | Low to medium; depends on module coverage and community pace | Supported version on a published release cycle, Backdrop security notices |
| Extended support on Drupal 7 | Recurring fee, plus hardening work | Low now, deferred later | Medium: core and listed modules covered; custom code, unlisted modules and PHP ceiling not | Contract, vendor advisories, dated migration plan and risk acceptance |
| Static archive | Low | Low to medium: export, redirects, data review | Very low: no PHP or database exposed | Decommissioning record, static hosting configuration |
| Retire | Lowest | Low | None for the site; residual risk in old backups | Decommissioning record, DNS change, data retention record |
| Stay on community Drupal 7 with no support | Looks free | None now | High and growing; public disclosures with no fixes | Usually none that satisfies an auditor |
Two rules of thumb fall out of that table. First, if nobody edits the site, archive or retire it, whatever its size. Second, if the site matters enough to keep editing, extended support is only a bridge to one of the first two rows.
Step by step: inventory, harden and plan the move
This walkthrough assumes shell access to a Drupal 7 site you are responsible for, Drush 8, and a copy of the database. Run everything on a staging copy first. Take a full backup of code, files and database before changing anything.
Step 1: record the basics
cd /var/www/site
drush status > inventory/status.txt
php -v > inventory/php.txt
ls -d sites/*/ > inventory/sites.txt
Note the Drupal core version from drush status. If it is older than 7.103, the final Drupal 7 release, update core first, since it carries the last community fixes and PHP 8.3 compatibility.
Step 2: list enabled modules and themes
drush pm-list --status=enabled --type=module --no-core --format=csv > inventory/modules.csv
drush pm-list --status=enabled --type=theme --format=csv > inventory/themes.csv
For a multisite installation, repeat per site with drush -l example.edu pm-list ..., because each site can enable a different set.
Then separate contributed modules from custom ones. Custom modules usually live in sites/all/modules/custom or a similar folder, but check for modules with no project line in their .info file, which drupal.org packaging adds to contributed modules:
for info in $(find sites -name "*.info"); do
grep -q "^project = " "$info" || echo "custom or hand built: $info"
done
Step 3: build a component list you can keep
Turn the inventory into a structured list that can outlive the spreadsheet: module name, version, whether it is contributed or custom, whether its Drupal 7 branch was supported at end of life, whether it has a modern Drupal or Backdrop equivalent, and who owns it. Add front end libraries from sites/all/libraries and any theme vendor folders, with versions.
The most portable form for that list is an SBOM. A minimal CycloneDX JSON file for a Drupal 7 site might start like this:
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"metadata": {
"component": { "type": "application", "name": "example-dept-site", "version": "2026.10" }
},
"components": [
{ "type": "framework", "name": "drupal", "version": "7.103" },
{ "type": "library", "name": "views", "version": "7.x-3.29" },
{ "type": "library", "name": "jquery", "version": "1.4.4" }
]
}
The version numbers above are placeholders for illustration; use the ones from your own inventory. The value is not the format, it is that the list is now machine readable, versioned with the site, and can be checked against vulnerability data the same way as any other application.
Step 4: check the PHP version and plan the runtime
Compare php -v with the table earlier in this post. On PHP 8.1 or older, the site is on an unsupported runtime today. Moving up a PHP version on Drupal 7 is a project in itself:
- Update core to the latest Drupal 7 release first.
- Update every contributed module to its last Drupal 7 release, and check each module's issue queue for PHP 8 compatibility notes.
- Run the site on staging under the target PHP version with error logging on, and click through every content type, form, view and admin page. Deprecation notices in the logs are your to do list.
- Only then switch production.
Treat 31 December 2027, when PHP 8.3 security support ends, as the outer limit of any Drupal 7 plan unless a contract covers a newer PHP.
Step 5: remove the PHP filter module
Drupal 7 core includes the PHP filter module, which lets anyone with the right text format permission run PHP code from content. It is one of the most dangerous things a Drupal 7 site can have enabled, because it turns any compromised editor account into code execution on the server. Before you disable it, find out what uses it:
# Is it enabled?
drush pm-list --status=enabled | grep -i "php filter"
# Which text format uses the PHP evaluator, and which content uses that format?
drush sqlq "SELECT format, name FROM filter_format WHERE format IN (SELECT format FROM filter WHERE module = 'php' AND status = 1)"
drush sqlq "SELECT entity_type, bundle, entity_id FROM field_data_body WHERE body_format = 'php_code' LIMIT 50"
Check blocks and other text fields too; the table and format names above match a default install, and yours may differ. Rewrite each piece of content that relies on PHP into a small custom module or a plain text format, then disable the module:
drush pm-disable php -y
Disabling it without moving the content first will leave those pages showing raw code or nothing, so do the content work first.
Step 6: restrict admin paths
Most attacks on a content management system start at its login and admin pages. If editors work from known networks or through a VPN, restrict /user/login, /user/password, /admin and /node/add at the web server. A minimal example for nginx:
location ~ ^/(user/login|user/password|admin|node/add) {
allow 203.0.113.0/24; # office or VPN range
deny all;
try_files $uri /index.php?$query_string;
}
Drupal 7 also answers the same paths as index.php?q=admin style requests whether or not clean URLs are on, so restrict those query forms too and test both. Turn off open user registration unless the site needs it, review the list of administrator accounts, and remove anyone who has left.
Step 7: put rules in front of the site
A web application firewall or reverse proxy rule set cannot patch Drupal 7, but it can buy time:
- Block requests to files that should never be served:
CHANGELOG.txt,install.php,update.php,cron.phpwithout the cron key,.info,.module,.incand.sqlfiles. - Rate limit login, password reset and search.
- Block or challenge requests to forms that only editors use.
- Make sure
sites/default/filescannot execute PHP. Drupal 7 ships an.htaccessfor Apache; on nginx write the equivalent rule yourself.
The Drupal hardening guide covers file permissions, settings and server rules in more depth.
Step 8: write the migration plan with dates
Per site, record: the chosen exit (migrate, Backdrop, extended support as a bridge, archive, retire), the owner, the start date, the target date, and the date the Drupal 7 code and database will be deleted. Put the plan in the same place as your risk register. A plan without a deletion date tends not to finish.
How do you patch an unsupported module yourself?
Sooner or later a module your site depends on will have a known problem and no Drupal 7 fix. You can carry the fix yourself, as long as you do it in a way that can be tracked and repeated.
The method
- Confirm the problem applies. Read the advisory or public report for the modern branch of the module, then read the matching Drupal 7 code. Same function, same unsafe pattern? Then it applies.
- Fork into version control. Put the module's Drupal 7 code in your site repository (most Drupal 7 sites already commit contributed modules), or in a separate repository your build pulls from.
- Write the smallest fix you can. Backport the modern fix where the code matches. Where it does not, write the minimal change that closes the same hole: escaping output, adding an access check, adding a token check to a form or menu callback, or validating input.
- Save the change as a patch file next to the code, so the fix is reviewable and can be reapplied to a fresh copy:
cd sites/all/modules/contrib/examplemodule
git diff > ../../../../patches/examplemodule-7.x-2.4-access-check.patch
- Record it. Keep a
PATCHES.txtor equivalent listing each patch, why it exists, the date, and who reviewed it. Bump the module's version string in its.infofile with a local suffix, for example7.x-2.4+local1, so nobody mistakes your build for the original. - Test. Exercise the feature the fix touches and the permissions around it, on staging.
- Track it in the SBOM. CycloneDX has a
pedigreefield for exactly this: a component can record its ancestor (the original module and version) and the patches applied to it. Recording the patch there means a later scan, audit or migration sees the modified component for what it is.
{
"type": "library", "name": "examplemodule", "version": "7.x-2.4+local1",
"pedigree": {
"ancestors": [ { "type": "library", "name": "examplemodule", "version": "7.x-2.4" } ],
"patches": [ { "type": "backport",
"diff": { "url": "patches/examplemodule-7.x-2.4-access-check.patch" } } ]
}
}
- Offer it back. If the module's Drupal 7 issue queue is still readable, post the patch there so other sites benefit, without describing how to exploit the flaw. If you have an extended support vendor, send it to them.
When not to patch
Patch only what you understand. A fix that needs a redesign of how the module stores data or checks permissions means the module should be replaced. Every local patch is a fork you now maintain, so let the count feed your migration priority.
Common mistakes
- No end date on the exception. "We will migrate next year" without a date is the most common reason Drupal 7 sites live for years past end of life.
- Forgetting staging and old subsites. Production gets the attention; the 2019 staging copy on a public subdomain with a weak admin password gets compromised.
- Upgrading PHP without testing contributed modules. Core may work on PHP 8.3, but an old contributed module can throw fatal errors on a page nobody visits until a customer does.
- Assuming extended support covers everything. It covers what the contract lists. Custom modules, niche modules and the hosting stack are still yours.
- Disabling the PHP filter without moving content. Pages that used it break or leak code. Find and move the content first.
- Migrating to Drupal 10 in late 2026. It reaches end of life on 9 December 2026. Target Drupal 11.
- Archiving without a data review. A static export of a membership site can publish personal data that was behind a login.
- Keeping the old site running after the migration. Delete the old code and database on the date in the plan, after archiving what retention rules require.
- Local patches with no record. A patched module with the original version number confuses everyone, including your future self and any scanner.
FAQ
Is Drupal 7 still supported in 2026?
Not by the Drupal community. Drupal 7 reached end of life on 5 January 2025, and the Drupal Security Team no longer publishes advisories or fixes for Drupal 7 core, contributed modules or themes. Paid extended support is available from vendors listed in the Drupal Association's extended security support program.
What happens if I keep running Drupal 7?
The site keeps working until something around it changes, but new vulnerabilities will not get community fixes and may be disclosed in public. External scanners flag Drupal 7 as insecure, and audits will ask for a support contract or a replacement plan. Over time the PHP versions it supports also reach their own end of life.
What is the newest PHP version Drupal 7 supports?
PHP 8.3, from Drupal 7.103, according to the Drupal 7 PHP requirements page. The same page says PHP 8.4 will not get support. PHP 8.3 receives security fixes until 31 December 2027.
Can I upgrade Drupal 7 directly to Drupal 11?
Yes, by migration rather than in place upgrade. You build a new Drupal 11 site and use the core Migrate, Migrate Drupal and Migrate Drupal UI modules, or the Drush based tooling, to bring content and configuration across. Themes and custom modules need rebuilding.
Should I migrate to Drupal 10 or Drupal 11?
Drupal 11. Drupal 10 reaches end of life on 9 December 2026, and Drupal 12 is planned for the same week, so a migration finishing in 2027 should land on Drupal 11 or later.
What is Backdrop CMS?
Backdrop CMS is an open source content management system that began as a fork of Drupal 7. It offers a built in upgrade path from Drupal 7, ships minor releases every four months, and keeps much of the Drupal 7 programming model, which makes module and theme ports smaller than a rewrite for modern Drupal.
How much does Drupal 7 extended support cost?
It depends on the vendor, the number of sites and modules covered, and the term. Drupal.org lists the vendors in the program; contact them for pricing and compare contracts on covered modules, PHP versions, delivery method and end date rather than price alone.
Is Drupal 7 extended support enough for compliance?
Usually not on its own. Frameworks generally accept unsupported components only with documented alternative support and a plan. A contract plus hardening, monitoring and a dated migration plan is a far stronger position than a contract alone.
Where Safeguard fits, honestly
Safeguard does not patch Drupal 7 core, does not provide Drupal 7 extended support, and does not harden web servers. A web application firewall, a support contract and a migration project are all outside what it does. Where it helps is the inventory and supply chain part of the job. Safeguard's software composition analysis reads Composer manifests, and it can scan an SBOM file, so the CycloneDX list you built in step 3 can be scanned with safeguard scan --sbom and matched against vulnerability data. How many Drupal 7 contributed modules match depends on whether each one has an identifier in the vulnerability databases, and after end of life many Drupal 7 issues never get an advisory at all, which is exactly why the inventory matters. The platform also shows which projects contain a given component and version, so the jQuery or editor library you found on one site can be found on every other site that carries it.
For the destination, it is a more direct fit. A Drupal 11 or Backdrop site built with Composer has a lockfile, and Safeguard scans it like any other PHP project, with reachability analysis to rank findings and policies and gates to stop a known vulnerable version from shipping. Autonomous remediation can open upgrade pull requests for PHP dependencies, switched off by default until you turn it on.
A Drupal 7 site is the clearest case of upstream going quiet: the fixes have stopped, and a new site built to replace it starts pulling Composer and JavaScript packages on day one. The same discipline applies to both, knowing exactly which components you run and closing the gap between a published fix and your production build, which is what the options below are for.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.
3. Gold Registry: start from components that are already fixed
Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | Safeguard policies and gates in CI |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is a real Safeguard CLI session. It opens the interactive terminal, asks it to fix a vulnerable dependency in a repository, and shows it reading the finding and advisory, editing the manifest, and asking before any command that changes something. The same flow applies to the Composer project of a Drupal 11 or Backdrop site that replaces your Drupal 7 one.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with a device code, and scans from the terminal. That is the route for scanning a site repository, or the SBOM you built for a Drupal 7 estate, without sending the code anywhere first.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and chooses which tools Claude can use. A team planning a multi site migration can then ask, in plain language, which projects still carry a given library version, and get the answer from its own Safeguard data.
Click through it at your own pace, or open it full screen.
To try it on your own projects, download Safeguard or read the CLI documentation.
Quick check
Drupal 7 core runs on PHP 8.3. Does that mean a Drupal 7 site can stay on a supported runtime indefinitely?
No. Drupal.org says PHP 8.4 will not get Drupal 7 support, and PHP 8.3 gets security fixes only until 31 December 2027. After that, community Drupal 7 has no supported PHP version to run on.
Your extended support contract covers Drupal 7 core and a list of popular modules. What is still your responsibility?
Custom modules and the theme, any contributed module not on the list, front end libraries, PHP and the rest of the hosting stack, configuration such as roles and text formats, and a dated plan to leave Drupal 7.
Sources
- Drupal 7 end of life (drupal.org)
- Drupal 7 extended security support partners (drupal.org)
- PSA-2023-06-07: Drupal 7 end of life on 5 January 2025
- PSA-2019-02-25: Drupal 7 will reach end of life in November 2021
- Drupal security advisories
- Drupal security risk levels defined
- Drupal core release schedule
- Upgrading Drupal (drupal.org documentation)
- Drupal 7 PHP requirements
- PHP supported versions (php.net)
- Backdrop CMS
- Backdrop CMS release cycle
- Backdrop CMS: upgrading from Drupal 7
- Backdrop CMS: upgrade steps from Drupal 7
- Migrate Upgrade project (drupal.org)
- Drupal 7 CHANGELOG.txt, final 7.x release notes
- Drush install and Drupal compatibility
- NIST SP 800-53 Rev. 5 catalog (SA-22 Unsupported System Components), OSCAL JSON
- CycloneDX pedigree use case
Last reviewed: 25 October 2026.