HIGH mass assignmentadonisjsbasic auth

Mass Assignment in Adonisjs with Basic Auth

Mass Assignment in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability

Mass assignment occurs when an API binds incoming request fields directly to a model or database record without explicit allowlisting. In Adonisjs, this typically happens when using merge in controllers to apply request body to an ORM instance, for example user.merge(request.body). If the request is authenticated only by Basic Auth, the server may trust the authenticated identity but still accept any field name the client sends. An attacker authenticated with a low-privilege Basic Auth credential can therefore add or overwrite sensitive fields such as is_admin, role, or permissions if the controller does not restrict which keys are accepted.

Adonisjs does not perform automatic schema-based filtering; developers must explicitly define which fields are updatable. When Basic Auth is used, authorization checks often focus on the username and password, while the application may inadvertently permit the authenticated user to supply values for sensitive columns. For example, a PATCH /users/:id endpoint that calls user.merge(request.body) without a permitlist enables BOLA/IDOR and mass assignment in one call: the endpoint locates the user by route parameter, confirms the provided HTTP Basic credentials, then merges all body fields into the record. This combination means authentication proves identity, but does not limit what can be changed.

Real-world impact resembles issues tracked under common attack patterns such as CVE-2021-21342 (improper neutralization of special elements), where mass assignment in a REST layer led to privilege escalation. In Adonisjs, if the User model contains fields like isVerified or role, and these are not guarded, an authenticated attacker can modify them simply by including the keys in JSON or form-encoded payloads. The vulnerability is not in Basic Auth itself, but in the unchecked binding of request properties to the model, especially when route-level ownership checks are incomplete.

To detect this during scanning, middleBrick runs checks for Property Authorization and BOLA/IDOR alongside input validation, and maps findings to OWASP API Top 10 and PCI-DSS controls. If your API uses Basic Auth, ensure each update operation specifies a strict permitlist (e.g., only email or profileBio), and validate ownership of the resource before applying changes.

Basic Auth-Specific Remediation in Adonisjs — concrete code fixes

Remediation centers on explicit field allowlisting and strict ownership verification before applying any updates. Avoid generic merges and instead pick only the fields you intend to support. Below are concrete, working Adonisjs examples that combine HTTP Basic Auth with safe mass assignment prevention.

Example 1: Safe update with permitlist

import { schema } from '@ioc:Adonis/Core/Validator'

const userUpdateSchema = schema.create({
  email: schema.string.optional(),
  profileBio: schema.string.optional(),
})

export default class UsersController {
  public async update({ request, params, auth }) {
    const payload = await request.validate({ schema: userUpdateSchema })
    const user = await auth.getUserOrFail()

    // Ensure the authenticated user can only update their own account
    if (user.id !== params.id) {
      throw new Error('Unauthorized')
    }

    // Apply only the allowed fields
    user.merge(payload)
    await user.save()

    return user
  }
}

Example 2: Using route-level auth with Basic Auth and permitlist

import { schema } from '@ioc:Adonis/Core/Validator'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

const safeFieldsSchema = schema.create({
  email: schema.string.optional(),
})

export default class ProfileController {
  public async updateProfile({ request, auth }: HttpContextContract) {
    const payload = await request.validate({ schema: safeFieldsSchema })
    const user = await auth.getUserOrFail()

    // Only permitted fields are merged; no attacker-controlled keys like is_admin can pass
    user.merge(payload)
    await user.save()

    return user
  }
}

Example 3: Controller-level guard with ownership check

import { schema } from '@ioc:Adonis/Core/Validator'

const minimalProfileSchema = schema.create({
  displayName: schema.string.optional(),
})

export default class AccountController {
  public async update({ request, params, auth }) {
    const payload = await request.validate({ schema: minimalProfileSchema })
    const user = await auth.getUserOrFail()

    if (String(user.id) !== String(params.id)) {
      throw new Error('Forbidden')
    }

    // Explicitly set allowed fields instead of merging raw body
    user.displayName = payload.displayName
    await user.save()

    return user
  }
}

These patterns ensure that even when credentials are verified via Basic Auth, only explicitly permitted fields can be changed. Combine this with route-level ownership checks and schema validation to close the mass assignment vector. middleBrick can highlight missing permitlists and weak authorization mappings in scans, and the Pro plan supports continuous monitoring to catch regressions when endpoints evolve.

Related CWEs: propertyAuthorization

CWE IDNameSeverity
CWE-915Mass Assignment HIGH

Frequently Asked Questions

Can an authenticated user still exploit mass assignment if the endpoint uses Basic Auth but no validation?
Yes. If the controller merges request.body without a permitlist, any field the attacker sends will be applied, including sensitive attributes like is_admin or role, regardless of the authentication method.
Does middleBrick test for mass assignment when Basic Auth is present?
middleBrick checks Property Authorization and input validation independently of authentication mode. It flags endpoints where user-supplied fields can reach models without explicit allowlisting, helping you identify mass assignment risks even when Basic Auth is used.