HIGH spring4shelladonisjsjwt tokens

Spring4shell in Adonisjs with Jwt Tokens

Spring4shell in Adonisjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

Spring4Shell (CVE-2022-22965) is a remote code execution vulnerability in Spring MVC and Spring WebFlux applications that exploit data binding against untrusted request data when the application runs on vulnerable versions of Spring Framework (5.3.0–5.3.17 and 5.2.0–5.2.19). In an AdonisJS context where you accept HTTP requests that ultimately route into a Spring-based microservice or integration layer, and you protect access with JWT tokens, the token itself does not mitigate the exploit if the request reaches a vulnerable Spring component.

The presence of JWT tokens in AdonisJS changes the threat model but does not prevent exploitation. AdonisJS can validate and attach claims from a JWT to the request (e.g., attaching user identity to the auth context), then forward the request—headers, parameters, and body—to downstream services that may include Spring endpoints. If an attacker crafts a request with malicious parameter names such as class.module.classLoader.defaultAssertionStatus and the request passes through to a Spring service that is unpatched and reachable, the data-binding mechanism can trigger remote code execution regardless of the JWT’s validity.

In a typical AdonisJS application using JWT middleware, the token is verified before your route handler runs. For example, AdonisJS middleware might decode a JWT and attach the payload to ctx.auth.user. However, this occurs after the request has already entered the Node.js runtime and, if your application proxies or calls a Spring service (for example via HTTP client), the original untrusted parameters are still included in the proxied request. The JWT protects authorization within AdonisJS, but it does not sanitize or neutralize malicious input that is forwarded to an external Spring component that is vulnerable to Spring4Shell.

Additionally, if AdonisJS itself hosts endpoints that parse JSON payloads and those payloads contain nested objects crafted to exploit Spring’s data binding when the payload is later processed by a vulnerable Spring service, the vector remains exploitable. Attack patterns such as injecting malicious class references via POST body fields or manipulating multipart form fields can be introduced in the body of requests authenticated by JWT tokens. Therefore, while JWT tokens in AdonisJS provide identity and access control, they do not prevent an attacker from delivering exploit payloads to Spring components if the API surface includes routes that forward or mirror data to those components.

To assess this risk in practice, scanning an AdonisJS endpoint that uses JWT tokens with middleBrick will test the unauthenticated attack surface and also include authenticated checks when tokens are supplied. This includes evaluating whether malicious parameters can propagate to downstream services and identifying exposures such as SSRF or improper input validation that could enable Spring4shell-style attacks even when JWT protection is in place.

Jwt Tokens-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on strict input validation, avoiding forwarding of untrusted data to vulnerable runtimes, and ensuring JWT usage does not create a false sense of security. When AdonisJS proxies or forwards requests to external services (such as Spring APIs), you must sanitize and strictly limit what is passed downstream. Below are concrete code examples for secure JWT-based request handling and safe request forwarding in AdonisJS.

First, validate and normalize the JWT payload in your auth middleware. Use strong schema validation for claims and avoid reflecting untrusted input into downstream requests.

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

export default class AuthMiddleware {
  protected schema = schema.create({
    token: schema.string.optional({}, [
      rules.regex(/^eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\.?[a-zA-Z0-9_-]*$/),
    ]),
    // Only allow expected claims when forwarding or enriching requests
    user_id: schema.number.optional(),
    scopes: schema.array.optional().members(schema.string()),
  })

  public async handle({ request, response, auth }, next) {
    const payload = await request.validate({ schema: this.schema })
    if (payload.token) {
      const token = payload.token
      // Verify token with your provider (pseudo-code)
      const user = await verifyJwt(token)
      request.authUser = user
    }
    await next()
  }
}

async function verifyJwt(token: string): Promise {
  // Use a trusted JWT library and validate issuer, audience, expiry
  // Return normalized user object with only required claims
  return { id: 1, scopes: ['read', 'write'] }
}

Second, when forwarding requests from AdonisJS to a Spring service, explicitly allow-list fields and headers instead of forwarding the entire request. This prevents malicious parameters from reaching vulnerable Spring data-binding endpoints.

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { ApiClient } from '@ioc:Extra/ApiClient'

export default class UserController {
  public async updateProfile({ request, auth, response }: HttpContextContract) {
    const safeBody = request.only(['email', 'displayName'])
    const headers = {
      'Authorization': `Bearer ${auth.user?.token}`,
      'X-Request-ID': request.id(),
    }
    // Explicitly avoid forwarding untrusted or unknown fields
    const resp = await ApiClient.post('/spring-service/users/' + auth.user?.id, {
      body: safeBody,
      headers,
    })
    return response.send(resp)
  }
}

Third, apply input validation and transformation before any outbound call. Reject or sanitize fields that could be used in data binding exploits (e.g., class-related parameter names) even when a JWT is present.

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

const safeUpdateSchema = schema.create({
  email: schema.string.optional({}, [rules.email()]),
  displayName: schema.string.optional({}, [rules.minLength(1), rules.maxLength(120)]),
  // Explicitly block dangerous patterns that could be exploited by downstream services
  // e.g., reject fields commonly leveraged in Spring4shell-like probes
  class: schema.optional(schema.string({}, [rules.notIn(['class', 'module', 'classLoader'])]), {
    trim: true,
    escape: true,
  }),
})

export async function validateSafeInput(ctx: HttpContextContract) {
  const validated = await request.validate({ schema: safeUpdateSchema })
  // Use validated data only
  return validated
}

Finally, use middleBrick to scan your AdonisJS endpoints—particularly those that forward requests or accept user input—so you can identify weaknesses such as missing validation, exposed parameters, or SSRF risks that could facilitate exploitation even when JWT tokens are enforced.

Frequently Asked Questions

Does a valid JWT token prevent Spring4shell exploitation when requests are proxied from AdonisJS?
No. JWT tokens provide authentication and authorization within AdonisJS but do not sanitize or block malicious payloads that are forwarded to downstream services. If a vulnerable Spring component receives a request with malicious parameter names, it can still be exploited regardless of the JWT.
How can middleBrick help detect risks related to JWT-protected endpoints in AdonisJS?
middleBrick scans the unauthenticated attack surface and, when you provide a token, also evaluates authenticated behavior. It checks whether malicious parameters can propagate to external services and surfaces findings such as SSRF, improper input validation, and exposure of sensitive data, helping you identify paths that could lead to Spring4shell-style attacks despite JWT usage.