HIGH stack overflowadonisjs

Stack Overflow in Adonisjs

How Stack Overflow Manifests in Adonisjs

In Adonisjs, a stack overflow vulnerability usually appears when user‑supplied data is processed with a recursive algorithm that has no depth limit. Common places include custom validation rules, model hooks, or middleware that walk through nested JSON objects. If an attacker can supply a payload with extreme nesting (e.g., 10 000 levels), the recursive function exhausts the Node.js call stack and the process crashes, leading to a denial‑of‑service.

The following example shows a custom validator rule that recursively validates a nested data field without any depth check:

// start/routes.js
Route.post('/users', 'UsersController.store').middleware(['validator:storeUser'])

// app/Validators/StoreUserValidator.js
const { schema, rules } = require('@ioc:Adonis/Core/Validator')
class StoreUserValidator {
  constructor () {
    this.schema = schema.create({
      profile: schema.object().members({
        // Vulnerable recursive walk
        data: schema.any({}, [
          rules.custom((value, _, { errorReporter, tip }) => {
            function walk (obj, depth) {
              // No depth limit – will overflow with deep input
              if (obj && typeof obj === 'object') {
                for (const k in obj) {
                  walk(obj[k], depth + 1)
                }
              }
            }
            walk(value, 0)
          })
        ])
      })
    })
  }
}
module.exports = StoreUserValidator

When a request like the following is sent, the walk function calls itself for each nested level:

{
  "profile": {
    "data": {
      "a": {
        "b": {
          "c": { … 10 000 levels deep … }
        }
      }
    }
  }
}

The Node.js process reaches the maximum call‑stack size, throws a RangeError: Maximum call stack size exceeded, and returns an empty or 500 response to the client.

Adonisjs-Specific Detection

middleBrick’s unauthenticated black‑box scan includes an Input Validation check that actively probes for stack‑overflow conditions. It sends a series of JSON payloads with increasing nesting depth (e.g., 10, 100, 1 000, 10 000 levels) to each discovered endpoint and measures the response.

If the scanner observes:

  • A sudden increase in response time (indicating deep recursion)
  • An empty response or HTTP 500 with a RangeError in the body (when error details are exposed)
  • The connection timing out after the default 5‑15 second window

it flags the endpoint as a potential stack‑overflow vulnerability and adds a finding with severity, remediation guidance, and the exact payload that triggered the condition.

Example CLI usage:

middlebrick scan https://api.example.com/users

The output will contain a section similar to:


[INPUT VALIDATION] Potential stack overflow detected
Severity: Medium
Payload: {"profile":{"data":{"a":{"b":{ … 10 000 levels … }}}}}
Remediation: Replace recursive traversal with an iterative approach or enforce a maximum depth.

Because middleBrick does not need agents, credentials, or configuration, the check runs automatically as part of the 5‑15 second scan.

Adonisjs-Specific Remediation

The fix is to replace the recursive walk with an iterative algorithm that uses an explicit stack (or queue) and enforces a maximum depth. This prevents the call stack from growing unbounded while still allowing validation of reasonably nested objects.

Revised validator using an iterative walk:

// app/Validators/StoreUserValidator.js
const { schema, rules } = require('@ioc:Adonis/Core/Validator')
function walkIterative (obj, maxDepth) {
  const stack = [{ obj, depth: 0 }]
  while (stack.length) {
    const { obj, depth } = stack.pop()
    if (depth > maxDepth) continue
    if (obj && typeof obj === 'object') {
      for (const k in obj) {
        stack.push({ obj: obj[k], depth: depth + 1 })
      }
    }
  }
}
class StoreUserValidator {
  constructor () {
    this.schema = schema.create({
      profile: schema.object().members({
        data: schema.any({}, [
          rules.custom((value, _, { errorReporter, tip }) => {
            const MAX_DEPTH = 100 // adjust per business needs
            walkIterative(value, MAX_DEPTH)
          })
        ])
      })
    })
  }
}
module.exports = StoreUserValidator

Alternative approaches that stay within Adonisjs’s ecosystem:

  • Use the built‑in schema.object() with schema.array() and schema.string() types, avoiding custom recursion altogether.
  • Leverage a third‑party validation library such as ajv (which supports maxDepth) and call it from a custom rule.
  • If the data shape is known, define a strict schema with schema.object().members() and let the validator reject unknown or excessively deep structures before any user code runs.

After deploying the fix, run middleBrick again to confirm that the finding disappears and the API returns a proper validation error (e.g., 422) instead of crashing.

Frequently Asked Questions

Can middleBrick detect a stack overflow in an Adonisjs API without any prior configuration?
Yes. middleBrick performs unauthenticated black‑box scanning and includes an Input Validation check that sends progressively deeper JSON payloads to each endpoint. If the response shows signs of deep recursion (timeouts, 500 errors, or error messages about call‑stack limits), it reports a potential stack‑overflow vulnerability.
What is the impact of a stack overflow vulnerability in an Adonisjs API?
An attacker can craft a request with deeply nested JSON that exhausts the Node.js call stack, causing the process to crash. This leads to a denial‑of‑service for that API instance, potentially affecting all users if the service is not restarted automatically. The vulnerability does not directly leak data, but it can be used to disrupt service availability.