Ssrf in Adonisjs with Basic Auth
Ssrf 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 can expose internal services and bypass access controls that rely on IP-level or network-level restrictions. When an endpoint accepts a user-supplied URL and performs an outbound HTTP request, an attacker can supply a target that resolves inside the server or service mesh, such as http://169.254.169.254/latest/meta-data/ or internal Kubernetes services like http://kubernetes.default.svc. If the AdonisJS route relies on Basic Auth credentials stored in environment variables and passes those credentials to the outbound request, the SSRF can be used to leak metadata or pivot to authenticated internal APIs that would otherwise be unreachable from outside the network.
In AdonisJS, routes often use the HTTP client (based on @adonisjs/core and needle or similar) to call external services. If the target URL is not strictly validated and the request is made with Basic Auth headers derived from a configuration file or environment variables, an SSRF vulnerability arises because the attacker can force the server to make requests to internal endpoints using the application’s trusted credentials. For example, an attacker could supply a URL like http://127.0.0.1:8080/admin where 8080 hosts a database admin interface or a local metadata service. Because the request includes Basic Auth, the internal service may trust the request and return sensitive data or allow unintended operations, which the middleBrick scanner flags as a high-severity finding under Data Exposure and Internal Network Access.
The interaction with Basic Auth amplifies the impact: if the credentials are over-permissioned (e.g., a service account with read access to internal configuration or write access to internal queues), the SSRF can lead to data exfiltration or further compromise. MiddleBrick’s 12 security checks run in parallel and include Input Validation and Data Exposure tests that detect whether user-controlled URLs lead to outbound requests that include sensitive headers or credentials. The scanner also checks for SSRF patterns by correlating runtime behavior with the OpenAPI spec, ensuring that paths and parameters intended to be public are not making authenticated calls to internal origins. Remediation focuses on strict URL allowlisting, removing Basic Auth from outbound calls, and using a proxy with tightly scoped permissions.
Basic Auth-Specific Remediation in Adonisjs — concrete code fixes
To mitigate SSRF in AdonisJS when using Basic Auth, avoid passing Basic Auth credentials to outbound requests that accept user-controlled URLs. Instead, use environment-based credentials only for trusted services and validate targets rigorously. Below are concrete code examples showing a vulnerable pattern and a secure alternative.
Vulnerable pattern (do not use)
import { Http } from '@adonisjs/core/services'
import { Base64 } from '@adonisjs/core/helpers')
export default class ApiController {
async proxyCall() {
const targetUrl = this.request.input('url') // user-controlled
const username = Env.get('OUTBOUND_USER')
const password = Env.get('OUTBOUND_PASS')
const authHeader = `Basic ${Base64.encode(`${username}:${password}`)}`
// Dangerous: forwards user URL with trusted auth headers
const response = await Http.get(targetUrl, {
headers: { Authorization: authHeader }
})
return response.body
}
}
Secure remediation
- Validate and allowlist the target host: Only permit calls to known, internal hosts or a strict set of external endpoints.
- Do not forward Basic Auth to user-directed requests: Use alternative authentication mechanisms (e.g., API tokens scoped to specific services) or a backend proxy that injects credentials only for allowed destinations.
- Use an allowlist-based proxy endpoint: Create a controlled server-side proxy that only calls pre-approved URLs and injects credentials securely.
Secure example with host allowlist
import { Http } from '@adonisjs/core/services'
import { Base64 } from '@adonisjs/core/helpers')
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class ApiController {
async safeProxyCall({ request }: HttpContextContract) {
const targetUrl = request.input('url')
const allowedHosts = ['https://api.partner.com', 'https://internal.service.local']
// Ensure the target URL is under an allowed host
const url = new URL(targetUrl)
if (!allowedHosts.includes(url.origin)) {
throw new Error('Origin not allowed')
}
// Use a scoped token instead of Basic Auth when possible
const token = Env.get('PARTNER_API_TOKEN')
const response = await Http.get(targetUrl, {
headers: { Authorization: `Bearer ${token}` }
})
return response.body
}
}
Secure example with backend proxy (recommended for complex flows)
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class ProxyController {
async callPartner({ request, response }: HttpContextContract) {
const targetPath = request.input('path') // e.g., /v1/resource
const allowedPaths = ['/v1/resource', '/v1/status']
if (!allowedPaths.includes(targetPath)) {
return response.badRequest({ error: 'Path not allowed' })
}
// The backend proxy holds credentials and calls a fixed base URL
const baseUrl = 'https://internal.service.local'
const res = await fetch(`${baseUrl}${targetPath}`, {
headers: { Authorization: `Basic ${process.env.PROXY_BASIC_AUTH}` }
})
const data = await res.text()
return response.ok().body(data)
}
}
These approaches ensure that SSRF risks are reduced by preventing user-controlled URLs from reaching internal endpoints while still allowing necessary outbound communication. middleBrick’s checks for Input Validation and Data Exposure help confirm that such controls are effective in runtime behavior.
Related CWEs: ssrf
| CWE ID | Name | Severity |
|---|---|---|
| CWE-918 | Server-Side Request Forgery (SSRF) | CRITICAL |
| CWE-441 | Unintended Proxy or Intermediary (Confused Deputy) | HIGH |