‹ Publications

The Department for Education 'Register of Training Providers' Vulnerability Disclosure

Reported and resolved through the Department for Education vulnerability disclosure programme. Published with coordinated timing after remediation.

October 9, 2026

Vulnerability disclosure

ControlPlane’s AI security research team identified a set of authorisation gaps in the Department for Education’s Register of Training Providers, which manages government-funded training providers and apprenticeships across England. The application used a well-regarded authorisation library, but several administrative actions didn’t invoke the authorisation check, allowing a standard, non-administrative staff account to perform actions intended for administrators only.

Once reported, the Department for Education confirmed the issues and remediated them. Severity was assessed as High, CVSS 8.3 (CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H), classified under CWE-862 (Missing Authorisation), with elements of CWE-639 and CWE-269 (Privilege Escalation).

Background

The service is built on Ruby on Rails and uses the Pundit authorisation library, which is a sound choice, but it is not automatic, as a controller enforces a rule only if it explicitly calls authorize on the record. When that call is omitted, the framework performs the requested database operation without a permission check.

The finding

Several destructive and administrative actions omitted the authorisation call, and one policy was incomplete:

  • Delete actions for providers and for user accounts were performed directly, without an authorisation check.
  • The user-update policy prevented editing deleted records and stopped a user from editing their own record, but contained no check that the actor was an administrator. Because the active attribute was editable, a standard staff account could deactivate an administrator’s account.
  • The activity listing did not scope its results to the caller, returning audit records across the whole organisation.

ControlPlane validated the findings non-destructively on a staging environment that ran the same code as production, using a standard non-administrative test persona.

Root cause

Adopting a robust authorisation library can create a false sense of safety if its conventions are not enforced. The library only protects the actions that call it; the gaps here were actions that never did, plus a policy that checked the wrong things. Nothing failed loudly, and the operations simply proceeded. This is the most prevalent category of OWASP web risk, A01:2025 Broken Access Control.

Potential impact

Taken together, the gaps meant a low-privileged staff account could deactivate or soft-delete administrator accounts, removing the ability to manage the service; soft-delete registered providers and staff accounts by iterating through the listing; and read internal audit records containing staff names and civil-service email addresses.

Coordinated disclosure and remediation

The Department for Education audited the controller tree and added explicit authorisation checks to all delete, archive, restore, and API-client management actions; restricted the user-update policy to administrators; and scoped the audit listing to the caller. The fix addressed not only the reported actions but the surrounding family of actions with the same weakness.

Disclosure timeline (dates only):

DateEvent
2026-06-26Report submitted through the DfE VDP
Engagement on HackerOne
2026-07-10Resolved: authorisation checks added across the affected controllers and policies

Responsible testing and data handling

Testing followed a minimum-necessary approach as per GC3’s vulnerability disclosure policy: verification was non-destructive, conducted with a standard test persona on a staging environment, and limited to what was required to demonstrate each issue. Audit data accessed during validation was not retained, and any test changes were reversed.

The broader lesson

Three practices prevent this class of flaw:

  1. Make authorisation impossible to forget. Frameworks that support a “verify authorised” guard turn a silent omission into a loud test failure; enable it, and back it with linting in continuous integration.
  2. Write policies against roles, not just record state. “Is this record still active?” and “is this caller an administrator?” are different checks.
  3. Scope every listing to the caller. By default, index and search actions should return only what the caller is entitled to see at the query layer.

About this work

ControlPlane is an AI-native cybersecurity consultancy specialising in cloud native security, secure software supply chains, and the assurance regimes that regulated organisations depend on. We review how applications are built and how they behave, so that an entire class of mistakes becomes structurally hard to repeat. If you run services where trust is non-negotiable, we would be glad to talk.