AI Pentesting

CVE-2026-71508: Mass Assignment Bug Rewrites Salary

Amartya | CodeAnt AI Code Review Platform
Sonali Sood

Founding GTM, CodeAnt AI

CVSS 6.5 · Mass assignment on payroll fields (CWE-915) · Fixed in Dolibarr 24.0.0

The form that updates your profile won't let you touch your own job title, yet leaves the salary field wide open, and then hands you back a receipt with the salary line blanked out, so it looks like nothing happened at all.

The attack in six steps

  1. The profile-update route copies your fields onto your record: standard API behaviour.

  2. It blocks a short list of obvious secrets: but salary, bonus and cost rates aren't on it. (this is the break)

  3. Send a new salary for your own account: from a user with zero payroll permissions.

  4. The write succeeds, but the reply hides it: the response omits the field it just changed, so a quick security test looks like nothing happened.

  5. Read the database before and after: the only way to see the new number is really there.

  6. It flows into the official payroll export: an employee rewrote their own pay. → payroll tampering.

Payroll is one of the few things inside a company everyone agrees has to be locked down. What each person earns, salary, bonus, the internal rates used to cost their time, sits behind a permission that only HR and finance are meant to hold. Dolibarr's own interface, the screen a human actually sees, respects that boundary completely.

This is what happens underneath that respectable interface. The route that saves your own profile will quietly write a new salary onto your own account, and then hand you back a receipt with that exact change hidden, so a casual API security test would swear nothing had happened.

It's a mass assignment vulnerability, the same family as the admin-takeover finding elsewhere in this series, but with a nastier twist: this one covers its own tracks.

The short block-list that forgot the important fields

When you save your profile, the route takes the fields you sent and writes them onto your record. It does try to be careful. It keeps out a short list of obviously dangerous fields. But a block-list is only ever as good as its imagination, and this one's imagination stopped short. Salary, bonus and the internal cost and daily rates, the four fields that actually decide what someone is paid, were not on it.

So an ordinary user, holding no payroll permission at all, edits their own profile and includes a new salary. The route writes it. There is no check that this particular field belongs to a locked-down part of the system. It is simply another field in the pile, and the pile gets written.

This is the core of the CWE-915 mass-assignment issue: the API accepts fields based on what has not been explicitly blocked rather than limiting the request to fields the caller is actually authorized to modify.

The silence that hides it

Here is what makes this one genuinely sneaky. The reply you get back is run through a "cleaner" whose job is to strip sensitive fields before sending anything out. So the response leaves the salary line blank, not because the write failed, but because the reply is not allowed to show it.

The effect is that a quick API penetration test looks like a clean rejection. You send a new salary, the answer comes back with no salary in it, and every instinct says "nothing changed." The write succeeded, the receipt just doesn't mention it. That gap between what happened and what the response admits is exactly where a bug like this hides for a long time.

Following the number all the way through

Because the response gives nothing away, the only way to catch the full impact was to stop trusting it. We read the database directly, before and after: the new salary was really there, written by an account with zero payroll rights. Then we followed that number where it counts, into the official payroll export, the report finance actually uses, and there it was too.

That is the difference between "a field can be set" and "an employee can rewrite their own pay and have it flow into the payroll run." The first is a curiosity. The second is the finding.

For Dolibarr security testing, that distinction matters. A penetration test cannot stop at whether an API returns 200 OK or 403 Forbidden. It has to establish what the request actually changed, what permissions the caller had, and where that changed data flows next.

What actually closes this

The fix in 24.0.0 stops treating payroll fields as ordinary profile fields. They now require the permission that actually governs pay, rather than riding in on a routine self-profile update, and the change is no longer hidden from the very response that would let someone notice it.

Two lessons are stacked on top of each other here. A block-list of "dangerous fields" is the wrong shape for anything sensitive, it fails silently the moment someone adds a new field and forgets to list it, while an explicit allowlist of what a caller may set fails safe instead. And hiding a value in the response is not the same as protecting it in the database. A write you cannot see in the reply is still a write, which is exactly the kind of gap that turns an ordinary employee into an insider threat without them ever touching a credential that wasn't theirs.

For developers and security teams, this is also a reminder that API authorization testing needs to cover individual fields, not just endpoints. An endpoint can have authentication and authorization checks in place and still expose a sensitive field through mass assignment, and payroll fraud built this way leaves no broken lock for anyone to notice, only a field that was never supposed to be writable in the first place.

The fix

Upgrade to Dolibarr 24.0.0, that closes this finding. Want to know where your own app disagrees with itself? Start with a free CodeAnt pentest.

Back to all nine findings in the Dolibarr research series

FAQs

Start Your 14-Day Free Trial

AI code reviews, security and quality trusted by modern engineering teams.

Table of Content
No headings found on page
Ship clean & secure code faster

Get Pentest Report

NO CC REQUIRED