HIGH ssrf server sideadonisjsbasic auth

Ssrf Server Side in Adonisjs with Basic Auth

Ssrf Server Side in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability

Server Side Request Forgery (SSRF) in an AdonisJS application that uses HTTP Basic Authentication creates a scenario where an attacker can force the server to make authenticated requests to internal or external endpoints. Because AdonisJS typically handles authentication at the route or middleware layer, developers may assume that routes guarded by Basic Auth are safe from SSRF. This is not always the case when the application performs outbound HTTP calls using user-controlled data without proper validation or network segregation.

Basic Auth credentials are often stored in environment variables or configuration files and used by an HTTP client (such as axios or AdonisJS’s native HttpClient) to access protected resources. If an attacker can influence the target URL of these outbound requests—through query parameters, request body fields, or headers—they can direct the server to make authenticated requests to internal services (e.g., http://127.0.0.1:3306, metadata services like 169.254.169.254, or internal APIs). Because the request includes valid Basic Auth headers, the backend service may trust and process the request, leading to data exposure, internal network scanning, or SSRF-based pivoting.

The risk is amplified when the application uses Basic Auth for internal microservices or administrative endpoints and does not enforce strict network-level controls. For example, an endpoint like /api/proxy that accepts a URL parameter to fetch external data and adds Basic Auth headers to the outbound call can be abused to scan internal infrastructure. An SSRF scan via middleBrick against such an endpoint would flag the unauthenticated attack surface and highlight that user input directly influences outbound HTTP destinations, even when the incoming request is protected by Basic Auth.

In AdonisJS, common patterns that lead to SSRF include using HttpClient.get() with user-supplied URLs, constructing webhook URLs from request data, or dynamically setting proxy or API endpoints based on input. Even when routes are protected by Basic Auth middleware, the server-side request chain may still execute with the same credentials, bypassing intended access boundaries. This means that authentication protects the entry point but does not mitigate the impact of a maliciously crafted outbound request.

Real-world examples include CVE-2021-23352-like patterns where internal metadata is reachable and CVE-2022-22965-style scenarios where SSRF leads to cloud instance metadata exposure. Because Basic Auth transmits credentials in an encoded (not encrypted) form unless used over TLS, additional risks arise if credentials are reused across internal and external services. middleBrick’s LLM/AI Security and Data Exposure checks help identify whether outbound calls leak credentials or sensitive data, while its Input Validation and Property Authorization checks highlight insufficient validation of user-supplied URLs.

Basic Auth-Specific Remediation in Adonisjs — concrete code fixes

To mitigate SSRF in AdonisJS when using Basic Auth, ensure that outbound HTTP requests never rely on user-controlled URLs and that network boundaries are enforced. Below are concrete remediation steps with code examples.

1. Avoid dynamic URLs in HTTP clients

Do not pass user input directly into HttpClient.get() or axios. Instead, use a strict allowlist of destinations.

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

export default class ProxyController {
  public async fetchExternal(ctx: HttpContextContract) {
    const { target } = ctx.request.qs()

    // ❌ Dangerous: user-controlled URL
    // const response = await axios.get(target, { auth: { username, password } })

    // ✅ Safe: allowlist of allowed hosts
    const allowedHosts = ['https://api.example.com', 'https://data.service.com']
    const selected = allowedHosts.includes(target) ? target : allowedHosts[0]

    const response = await axios.get(selected, {
      auth: {
        username: process.env.BASIC_USER,
        password: process.env.BASIC_PASS,
      },
    })

    return response.data
  }
}

2. Use environment-bound credentials and disable proxying

Do not forward authentication headers to user-provided endpoints. Instead, use fixed credentials scoped to a specific service and avoid proxying user requests entirely.

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

export default class DataController {
  public async getInventory(ctx: HttpContextContract) {
    // ✅ Fixed destination with environment-bound Basic Auth
    const response = await axios.get('https://internal.service.local/inventory', {
      auth: {
        username: process.env.INVENTORY_USER,
        password: process.env.INVENTORY_PASS,
      },
      timeout: 5000,
    })
    return response.data
  }
}

3. Validate and sanitize hosts using a URL parser

If you must accept a URL, parse it and enforce host and scheme restrictions.

import { URL } from 'url'

export function validateOutboundUrl(input: string): string | null {
  let parsed: URL
  try {
    parsed = new URL(input)
  } catch {
    return null
  }

  if (!['https:'].includes(parsed.protocol)) {
    return null
  }

  const allowedHosts = new Set(['api.example.com', 'data.example.com'])
  if (!allowedHosts.has(parsed.hostname)) {
    return null
  }

  return parsed.toString()
}

4. Apply network-level controls and disable outbound to private IPs

Use container or runtime policies to prevent connections to private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). This complements application-level fixes and reduces the impact of a potential SSRF vulnerability.

5. Use middleware to enforce authentication scope

Ensure that Basic Auth is applied only where necessary and does not implicitly authorize outbound calls.

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { middleware } from '@ioc:Adonis/Core/BodyValidator'

export const basicAuth = async (ctx: HttpContextContract, next: () => Promise) => {
  const auth = ctx.request.auth()
  if (!auth || auth.username !== process物的 BASIC_USER || auth.password !== process.env.BASIC_PASS) {
    ctx.response.unauthorized('Invalid credentials')
    return
  }
  await next()
}

Frequently Asked Questions

Can SSRF occur in AdonisJS routes protected by Basic Auth?
Yes. Protecting an endpoint with Basic Auth does not prevent SSRF if the server makes outbound HTTP requests using user-controlled URLs. The server may still send authenticated requests to internal or external destinations, exposing internal services or metadata.
What is the most effective mitigation for SSRF with Basic Auth in AdonisJS?
Do not use user-supplied URLs for outbound requests. Use a strict allowlist of destinations, bind credentials to a specific service, and validate hosts using a URL parser. Disable outbound connectivity to private IP ranges where possible.