Drupal penetration test scope

A Drupal penetration test is only as useful as its scope. This page explains what a test of a Drupal site should cover, what to leave to other controls, and what to confirm before you sign.

On this page

What a Drupal penetration test scope should cover

A Drupal penetration test should concentrate on five areas: exposed admin and user paths, custom modules, file upload handling, access bypass in Views and APIs, and outdated contributed code. If your team is preparing a Drupal site for a security test in a regulated setting, the written scope should name each of these areas, the hostnames and environments in play, and the roles (anonymous, authenticated, editor, administrator) the testers will use. Drupal core and most contributed code are licensed under the GNU General Public License, version 2 or later (GPL-2.0-or-later), and there is no paid edition of Drupal itself, so the risk a tester can find sits largely in your own configuration, custom code and the choice of contributed projects.

Start the scope with the paths an outsider can reach. Ask the tester to enumerate the login route, the user registration and password reset pages, and any administrative route exposed on the public internet, and confirm whether those paths are restricted by network rules, by role, or by both. Custom modules deserve the largest share of time because they are written for your site and have had the least external review. Include every custom module, custom controller, form and service in the inventory, and list the contributed modules that handle authentication, file handling and data export. Ask for a list of custom routes and the permissions attached to each one before testing begins.

File upload handling and Views access need explicit scope lines. Name every field that accepts uploads, the allowed extensions, the storage location and whether files are served from the web root. For Views and REST or JSON:API endpoints, the tester should check whether filters, contextual arguments and exposed fields respect the access rules that editors expect, since a view can expose unpublished or restricted content even when the page template does not. Finally, record the version of Drupal core and each contributed project in the scope, and compare them with the Drupal Security Team advisories before the test. Any module that is unsupported or behind on security releases should be a named finding area, not an afterthought.

Which parts of a Drupal site belong in scope

Login, registration, password reset and the account pages are the first places an outside tester probes, and they are where Drupal's built-in protections are most often misconfigured or disabled. The tester checks how the site responds to repeated failed logins, whether password reset and login messages reveal which usernames exist, whether public registration can assign roles it should not, and whether administrative routes are reachable from the public internet or only from approved networks.

  • Flood control and lockout: whether failed attempts are throttled per account and per address, and what happens after the threshold is reached.
  • User enumeration: whether error text, reset responses or timing differences confirm that an account exists.
  • Registration and role assignment: whether new accounts receive only the intended roles and whether approval steps can be bypassed.
  • Admin route exposure: whether /user/login and administrative paths are restricted at the web server, CDN or network layer.
  • Session handling: logout, idle timeout and session invalidation after a password change.

From your team, ask for the list of enabled authentication modules, any single sign-on integration, the role matrix and at least one test account for each role. Confirm also whether a web application firewall or reverse proxy sits in front of the site, because that changes what the tester can reach.

How the scope gets written and agreed

A written scope is the document that turns a general wish to "test the site" into work that can be priced, scheduled and judged afterward. It should name every target: the public hostname or hostnames, the admin paths such as /user/login and /admin, any REST or JSON:API endpoints, and the custom modules and themes in the codebase that the testers may read or exercise. It should also state which environment is in play. Testing production carries the risk of disrupting real editors and visitors, while testing a staging copy only tells you about that copy, so the scope needs to say whether staging mirrors production's modules, configuration, web server rules and CDN or WAF layer. Confirm that staging holds representative content and user roles before agreeing to test it.

The scope should also fix the testing window, the test accounts and the rules of engagement. Name the roles testers will hold (anonymous visitor, authenticated user, content editor, site administrator) and which of them will be supplied. Set the permitted hours, the rate limits for automated scanning, whether denial-of-service and social engineering are excluded, and who receives an emergency stop call. List the out-of-scope systems explicitly: the hosting control panel, the database server, the CDN account, the email provider and any third-party SaaS that the site calls, such as a CRM or payment gateway. Those systems usually belong to someone else and need that party's permission before any test touches them.

Because a penetration test is a point-in-time check, the scope should record the exact Drupal core version and the version of each contributed module and custom module in the tested build, along with the PHP version reported by the server. Ask for a software inventory, such as a Composer lock file export, before the test begins and attach it to the scope. Any update after the test date can change the findings, so agree in writing how retests will be handled. Scope size drives the quote and the timeline: the number of roles, custom modules, integrations and environments all change the effort, and DeployOpen works on a fixed-scope basis with deliverables and timelines agreed in writing before work starts.

Scope options and when each fits

This table compares the main scope choices for a Drupal security test: authentication level, testing approach, target environment and infrastructure boundary. Read each row as a decision: what it reveals, what it misses, and when it fits your risk and timeline. Most regulated sites combine an authenticated grey-box test on a production-like target with a defined infrastructure boundary.

Scope optionWhen it fitsWhat it revealsWhat it misses
Unauthenticated (anonymous) testingPublic-facing sites where the first question is what an outsider can reachExposed admin paths, login and registration flaws, username enumeration, unprotected files and open endpointsAccess bypass inside roles, editor and admin workflows, and logic flaws behind sign-in
Authenticated testing with role accountsSites with editors, reviewers, members or customers who hold different permissionsViews and JSON:API access bypass, field-level exposure, unsafe text formats and privilege escalation between rolesFlaws that only appear for roles the tester was not given
Black-box testingWhen you want to simulate an outside attacker with no inside knowledgeBehavior a real attacker can observe, including headers, error pages and exposed contributed modulesCustom module logic, hidden routes and configuration that is not visible from the browser
Grey-box testing with code and role accountsSites with custom modules, custom entities or a bespoke access modelCustom access checks, file upload handling, query construction and version details of contributed codeIssues that depend on production data volume or infrastructure settings outside the application
Staging targetPre-release checks and environments that mirror production configuration closelyDefects before they reach users, with room for destructive tests such as file upload fuzzingDifferences in data, third-party connections, caching and CDN behavior that exist only in production
Production targetWhen staging does not match production or when edge controls must be tested as deployedReal caching, WAF rules, CDN behavior and live configurationRisk of disruption, so tests need agreed rules of engagement, test accounts and a stop condition
Site-only scopeWhen the Drupal application is the asset and infrastructure is covered by other reviewsApplication and module weaknesses, access control, input handling and contributed code exposureWeb server misconfiguration, database exposure, TLS settings and gaps in the CDN or WAF layer
Site plus infrastructure, database and CDN or WAFWhen the edge, hosting and data stores are part of the system you must defendChains such as a file path exposed by the web server, direct database reachability or a bypass around the WAFRequires written authorization for each component, hosting provider rules and more coordination time

Where Drupal security tests usually find problems

Drupal sites tend to fail security tests in a small set of places: custom code that bypasses the access system, data exposed through site builder tools, uploads, leftover administrative paths, outdated contributed code and loose site configuration. The cards below describe each area as a risk to test for, so the scope agreed before testing covers every one of them.

Custom code that skips access checks

Custom modules, controllers and services sometimes return entities, render arrays or query results without calling the entity access API or checking permissions on the route. Testers should request each custom route and AJAX callback as an anonymous user and as each authenticated role, and compare what is returned with what the role should see. Review every custom route definition for an access callback or permission requirement, and every direct database query for missing access tags.

Views exposing restricted content

Views can show unpublished nodes, restricted fields or related entities when filters, contextual arguments or relationships are configured without access controls. Testers should check each View with a public or low-privilege account, try the exposed filters and URL arguments with values for content they should not see, and confirm that the query respects node access and field-level permissions. Also check REST and JSON:API exports of the same Views, since they may expose data the page hides.

Unsafe file upload handling

Upload fields and media handling can accept executable scripts, double extensions, or files that the server then serves from a path that runs code. Testers should upload files with disallowed extensions, mismatched MIME types and embedded payloads to every upload field, including those in custom forms and API endpoints. Confirm that uploaded files land in private or non-executable directories, that the web server does not execute them, and that file size and count limits hold.

Reachable admin and update paths

Update scripts, install files, development tools and administrative routes sometimes remain reachable on production after a deployment. Testers should probe paths such as the update entry point, cron endpoints, and development or debugging tools from outside the network, and confirm that each returns a denial or is blocked at the web server. Compare the server's exposed routes with the list of routes the team intends to publish, and check that administrative logins are limited to approved networks where the design requires it.

Outdated contributed modules

Contributed modules with published advisories remain a common source of exposure, and a site can be current on core while still running a vulnerable project. Testers should compare the installed versions of core and every contributed project against the Drupal Security Team advisories and the project pages, and ask for the update history of each module. Include custom modules and themes in the review, because they fall outside the advisory feed and need their own dependency checks.

Misconfigured text formats and errors

Permissive text formats can allow script or unsafe markup in content entered by editors, and verbose error reporting can reveal file paths, database details and stack traces. Testers should submit test markup through each text format available to each role, and trigger errors on forms and routes to read the response. Confirm that the production error display is set to hide details, that unused formats are removed, and that the logs record failures without exposing them to visitors.

How to prepare a Drupal site for a penetration test

This sequence turns an unknown Drupal estate into a tested, documented baseline: known versions, a complete module inventory, usable test accounts, an agreed staging target and a clear record of which advisories are applied. The result is a test that spends its time finding real exposure rather than rediscovering known gaps.

  1. Confirm Drupal core and PHP versions

    Record the installed Drupal core version and the PHP version the web server actually runs, not the version in a deployment file. Drupal 10 requires PHP 8.1 or later and Drupal 11 requires PHP 8.3 or later, so a site on Drupal 11 with an older PHP runtime fails the requirement before testing starts. Also confirm the database engine and web server in use. The output is a one-page version sheet signed off by the platform owner, with any mismatch flagged for remediation before the test window.

  2. Export the contributed module inventory

    Generate a complete list of installed contributed modules, themes and custom code with their exact versions, using Composer lock data or a Drush command run against the live codebase. Include modules that are installed but disabled, since they can still expose routes or configuration. Compare the list against the project's Drupal.org pages to flag projects with no recent release. The check is complete when the inventory matches the deployed codebase byte for byte in a hash comparison, and the testers receive it before scoping.

  3. Check advisories for installed versions

    Review the Drupal Security Team advisories for every core and contributed version in the inventory. For each advisory that applies, either confirm the fix is deployed or write a documented exception with an owner, a compensating control and a review date. Testers should not spend time on known, already-published issues unless the purpose is to verify a fix. The check is complete when every installed project has an advisory status recorded against it.

  4. Provide role-based test accounts

    Create one test account for each role the site uses, such as anonymous, authenticated, content editor, site administrator and any custom roles tied to access rules. Assign only the permissions each role would have in production, and document the login path for each. Testers need these accounts to check access bypass in Views, REST and JSON:API endpoints, and they should not receive production credentials. The check is complete when each account logs in, and the role matrix shows which permissions each account holds.

  5. Agree the staging copy and data handling

    Prepare a staging environment built from a current copy of production code and configuration. Remove or replace personal data with synthetic records, and confirm that outbound email, payment and third-party integrations are disabled or pointed at sandboxes. The platform owner and the test lead should agree which environment is in scope and who can reach it. The check is complete when a smoke test confirms staging matches production configuration and that no live integration responds from the test network.

  6. Set rules of engagement

    Write the rules of engagement in a document signed by the client and the testing firm. It should cover permitted techniques, forbidden actions such as denial-of-service testing or destructive file operations, testing windows, contact points for emergencies, and how a critical finding is escalated during the test. Confirm the source IP ranges the testers will use so monitoring and any web application firewall can distinguish them. The check is complete when both parties have signed and the monitoring team has the test IP addresses.

  7. Record a baseline before testing begins

    Before the test starts, capture the baseline security configuration: security headers returned by the web server or CDN, the state of the Security Review checks, file permissions on the public files directory, and the list of text formats available to editors. Store the results with the other preparation records. This gives testers a reference point and lets the team tell later whether a finding is new or was present before testing. The check is complete when the baseline is saved with a date and the responsible engineer's name.

Safety rules for testing a live Drupal site

A penetration test on a production Drupal site can disrupt editors, lock out users or expose personal data if it runs without guardrails. The cards below set out the controls to agree in writing before the first request is sent, so the test finds weaknesses without creating new ones.

Avoid destructive payloads

Agree in writing which test classes are allowed against production, such as read-only checks for access bypass in Views and REST or JSON:API endpoints. Destructive payloads, bulk writes and anything that deletes nodes, users or files should run only against a staging copy. Ask the tester to log every request that changes state and to stop if a payload alters content unexpectedly.

Back up before testing

Take a full database dump and a copy of the public files directory, and confirm the backup restores to a separate environment before testing starts. Record the Drupal core and contributed module versions at that moment so any change during the test can be compared against them. A backup that has never been restored is not a rollback plan.

Coordinate with the WAF

If a web application firewall, CDN rules or Drupal Steward sit in front of the site, tell the team who operates them and agree a test window and source IP addresses. Otherwise the test may trigger automated blocks that look like an attack, or a block may hide findings that the real attacker path would reach. Ask for the rule set and the logs so blocked requests can be reviewed afterwards.

Agree rate limits and flood control

Brute-force checks against login forms can trip Drupal's flood control and lock out real editors and administrators. Agree the maximum request rate, the number of login attempts per account, and the test accounts to use. Confirm which lockouts the team will clear and how, so testing does not become a denial of service against the people who run the site.

Handle personal data findings

Testers may reach user records, form submissions or uploaded documents that contain personal data. Agree in advance that they will not copy or export such data, will record only the minimum needed to prove the issue, and will report it through the agreed channel. Confirm the retention period for evidence and whether the findings must be handled under your data protection rules.

Plan the retest

Each finding should have an owner, a fix target and a retest scope before the report is closed. Retests should check the specific request that failed, plus adjacent paths the same module or view exposes. Confirm whether the retest is included in the fixed-scope agreement or needs a separate quote, and schedule it after the fix is deployed, not while the change is still in review.

Questions buyers ask about Drupal penetration test scope

What drives the cost and effort of a Drupal penetration test?

The main drivers are the size of the scope, the volume of custom code, the number of user roles and the number of integrations. A site with a stock core install, a few contributed modules and one anonymous and one editor role takes far less testing than a site with custom modules, custom Views exposed to the public, several role types and live connections to a CRM, identity provider and payment service. Each integration adds trust boundaries and credentials that have to be exercised. Ask the provider to price the test from a written scope that lists these items, and ask whether retesting after fixes is included. Fixed-scope engagements agree deliverables and timelines in writing before work starts, so the quote should follow directly from that list.

Can our own team run a Drupal penetration test internally?

Often yes for parts of the work, but the decision depends on the skills and independence you need. An internal team that knows the codebase can review custom modules, check Views access settings and verify file upload handling. An outside tester brings separation from the build team and fresh attacker techniques, which matters when auditors or internal policy expect independent testing. Many organizations combine the two: internal teams run configuration reviews and dependency checks between formal tests. Whichever route you choose, confirm who signs off on findings and who retests fixes, because a test without that closure step leaves the risk open.

What does the testing team need from our side before the test starts?

The tester needs a defined target, access and people to answer questions. Typically that means:

  • Read access to custom code, including custom modules, themes and any patches applied to contributed projects.
  • Test accounts for each role that can log in, such as anonymous, authenticated, editor and administrator, with known passwords.
  • A staging copy that mirrors production configuration and content structure, so tests do not touch live visitor data.
  • Named contacts for the application, infrastructure, the integrations and an escalation path if a test disrupts service.

Also agree the testing window, the source IP ranges that will send traffic, and whether scanning of the hosting platform is in or out of scope.

How long does preparation take for a Drupal penetration test?

No supplied duration applies to every site, so confirm the figure against your own scope. Preparation time grows with the same drivers that set the price: the number of roles to create and document, the amount of custom code to make available, how much a staging copy needs to be rebuilt to match production, and how many integrations need test credentials or sandbox endpoints. Scheduling matters too. Check whether your release calendar overlaps with Drupal's security release windows, since a site update during the test can change what is being tested. Ask the provider to list preparation tasks and owners in the written scope so you can see where your team's time goes.

Does a penetration test certify that our Drupal site is compliant?

No. A penetration test produces findings about the security of the site as tested at a point in time. It does not issue audit reports, attestations or certifications. Independent auditors and certification bodies make those determinations, and they decide what evidence they accept, including whether a test scope and tester independence meet their requirements. DeployOpen can prepare systems, controls and evidence for compliance assessments, but the assessment itself belongs to the auditor. Before buying a test for an audit, ask the auditor which test type, scope and report format they expect.

Does a penetration test replace applying Drupal security updates?

No. A test finds weaknesses at the time it runs, while Drupal security releases close known vulnerabilities as they are published. The Drupal Security Team publishes advisories with CVE identifiers and risk scores, and security releases come out on the third Wednesday of the month. A site can pass a test and still be exposed to an advisory published the following week. Keep a routine update process running between tests, and use a test to check whether your patch process works in practice, including how contributed modules with advisories are handled.

Should a penetration test include outdated contributed modules?

Yes, it should check them, but a test is a poor substitute for dependency management. Ask the tester to list installed core and contributed versions, compare them against published advisories and flag projects that are unsupported or no longer maintained. Confirm whether the tester will attempt exploitation or only report exposure, because that changes both the cost and the risk to your staging environment. Drupal 7 sites that cannot yet migrate may rely on extended security support from a listed provider, and the test scope should state that dependency on an outside provider so findings are read in context.

Limits to confirm before you sign

A penetration test is only as useful as the boundary drawn around it. The cards below cover the questions that most often separate what a provider tests from what a regulated buyer assumed was tested. Confirm each one in writing with the provider and against your own environment before the scope is signed.

Drupal versions and modules

Confirm the exact Drupal core version, the PHP version and every contributed module the test will cover. Drupal 7 security support ended on January 5, 2025, so a Drupal 7 target needs a clear answer on its extended support arrangement, and the Drupal Association's Extended Security Support Provider Program lists certified vendors for sites that cannot migrate yet. Ask the provider whether findings against an unsupported core will be reported as inherent risk or excluded from the scope.

Hosting, CDN and database

Decide whether the web server, the reverse proxy, the CDN, the database and the file storage are in scope, or only the Drupal application behind them. Testing the origin server often reveals misrouted admin paths or cache rules that expose authenticated pages, while testing only the edge can miss them. Ask who owns credentials for each layer and whether the tester may request changes to a production configuration.

Third-party sign-in integrations

Confirm whether the SAML or OpenID Connect sign-in path is in scope, including the identity provider configuration, claim mapping and the account creation behavior on first sign-in. The samlauth and OpenID Connect modules create or link accounts from external assertions, so a misconfigured trust relationship can grant access that the Drupal role model never intended. Ask whether the identity provider itself is excluded and who tests it.

Retest terms

Ask whether one retest of confirmed findings is included, how long after the report it can be requested, and whether the retest covers only the original findings or any new code shipped in the meantime. Clarify who verifies a fix, how a finding is closed, and whether a fix that depends on a contributed module update counts as resolved. Retest fees and their scope should appear in the written quote.

Your patch process

Ask how the test assesses your own update routine, not just the current release. Confirm whether the tester will review how you track Drupal core and contributed security advisories, which Wednesday security release windows you apply and how quickly high-risk advisories reach production. A clean result on today's code says little if the next advisory would wait weeks for a deployment, so ask for that review to be written into the deliverables.

Test window and data handling

Confirm the permitted test window, the environments that will be tested, and how test accounts and any personal data encountered are handled and deleted. Ask whether testing against production is allowed, who approves rate-limited or intrusive checks, and how the provider will protect report contents. These details belong in the rules of engagement, which should be agreed before the first request is sent.

How DeployOpen works on this

DeployOpen runs security testing as part of the same self-hosted Drupal work it plans and builds, inside your own infrastructure. The test scope is agreed in writing before any testing starts, so the boundaries, the access provided and the deliverables are clear to both teams.

How we scope

  • Agree in writing which hostnames, admin paths, user flows and custom modules are in the test.
  • List the contributed modules and their versions so outdated code is checked against advisories.
  • Confirm which Views, REST or JSON:API endpoints hold access rules that need bypass testing.

How we build

  • Test exposed admin and user paths, including login, registration and password reset flows.
  • Probe file upload handling for type checks, storage location and execution risks in custom code.
  • Try access bypass through Views filters, entity access and API routes with low-privilege accounts.

How we hand over

  • Deliver findings with reproduction steps, affected components and a suggested fix for each issue.
  • Map each finding to the module, configuration or custom code that needs changing.
  • Document what was tested, what was excluded and which items need retesting after fixes.

How we support

  • Support fixes and retesting as part of the agreed scope or a follow-on engagement.
  • Offer ongoing security testing and Drupal support as a retainer where your team wants continuity.
  • Confirm with your team how advisory response and patch windows will be handled after handover.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.