Open Redirect in Adonisjs with Cockroachdb
Open Redirect in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
An Open Redirect in an Adonisjs application using Cockroachdb typically arises when a route accepts a user-supplied URL or path parameter and performs an HTTP redirect without strict validation. If the application stores or references redirect targets in Cockroachdb—such as campaign settings, tenant configurations, or feature flags—improper handling of those stored values can lead to unsafe redirects. For example, an attacker might manipulate a stored URL field in Cockroachdb through other means (e.g., compromised admin UI or injection) or supply a malicious redirect URL as a query parameter, and the Adonisjs route will redirect unauthenticated users to that location.
Consider a typical pattern where an Adonisjs route reads a redirect URL from a configuration record in Cockroachdb and uses it for post-login or post-action navigation. If the stored URL lacks validation, an attacker who can inject a malicious value into Cockroachdb can cause the application to redirect users to phishing sites. Even without direct database write access, an attacker can supply a crafted URL like https://evil.com to an endpoint expecting a relative path, and if the code directly uses that value with response.redirect(), the application will issue an external redirect.
The combination of Adonisjs routing and Cockroachdb data storage amplifies the risk when validation is limited to presence checks or simple string concatenation. For instance, using a dynamic value from a Cockroachdb row in a redirect without ensuring it is a relative path or a trusted absolute URL can bypass intended security boundaries. This becomes especially dangerous if the application uses the redirect to send users to an external provider and the stored URL can be poisoned through misconfiguration or secondary vulnerabilities.
Because middleBrick scans the unauthenticated attack surface and tests inputs that reach backend logic, it can detect endpoints where redirect parameters or stored configuration values lead to external locations without adequate allowlisting. The scanner checks for missing validation on HTTP redirects and highlights cases where user-influenced data—potentially sourced from Cockroachdb—can control the redirect target.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
To remediate Open Redirect issues when using Cockroachdb with Adonisjs, enforce strict allowlisting and treat stored URLs as untrusted input. Prefer relative paths for internal redirects and validate any external URLs against a strict set of allowed domains. Below are concrete code examples.
1. Validate and use relative redirects:
import { schema } from '@ioc:Adonis/Core/Validator'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class SessionsController {
public async store({ request, response, auth }: HttpContextContract) {
const body = request.validate({
schema: schema.create({
redirectTo: schema.string.optional([
// Only allow relative paths
(value, confirm) => {
if (value && !value.startsWith('/')) {
confirm('redirect_to_relative_path')
}
},
]),
}),
})
// Perform authentication...
await auth.authenticate()
// Use a safe relative default
const redirectTo = body.redirectTo || '/dashboard'
return response.redirect(redirectTo)
}
}
2. Validate external URLs against an allowlist when reading from Cockroachdb:
import { DateTime } from 'luxon'
import Database from '@ioc:Adonis/Lucid/Database'
import { schema } from '@ioc:Adonis/Core/Validator'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class CampaignsController {
public async show({ request, response, params }: HttpContextContract) {
const body = request.validate({
schema: schema.create({
campaignId: schema.number(),
}),
})
// Fetch campaign settings from Cockroachdb
const campaign = await Database.from('campaigns')
.where('id', body.campaignId)
.limit(1)
.select('redirect_url')
.first()
const allowedDomains = ['https://app.example.com', 'https://app.example.org']
const redirectUrl = campaign?.redirect_url
let safeUrl: string | null = null
if (redirectUrl) {
try {
const url = new URL(redirectUrl)
if (allowedDomains.includes(url.origin)) {
safeUrl = url.toString()
}
} catch {
safeUrl = null
}
}
return response.redirect(safeUrl || '/campaigns')
}
}
3. Use environment-based configuration for external destinations instead of storing arbitrary URLs in Cockroachdb:
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class OnboardingController {
public async finish({ response, authUser }: HttpContextContract) {
// After onboarding steps, redirect to a fixed, trusted destination
const target = `${process.env.APP_URL}/onboarding/complete`
return response.redirect(target)
}
}
These patterns ensure that redirects are constrained to known safe destinations, whether they are static routes or values retrieved from Cockroachdb. By validating origins and avoiding direct use of raw stored URLs, you eliminate the Open Redirect vector while preserving legitimate navigation flows.