Dangling Dns in Adonisjs with Cockroachdb
Dangling Dns in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
A dangling DNS entry occurs when a hostname resolves to an infrastructure no longer in use, and in AdonisJS applications connecting to CockroachDB it can create a window where the application unknowingly routes traffic to an unintended host. Because AdonisJS typically resolves hostnames at startup or connection time rather than on every request, a stale DNS record can persist in the runtime environment, especially when combined with CockroachDB’s distributed node topology and connection pooling. If a cluster node is decommissioned or a test environment is recycled, its DNS name may remain in service until TTL expires or the application reconnects, during which time the old hostname may resolve to a different, potentially untrusted service. This misdirection can expose the application to data exposure or injection via an unintended backend that does not enforce the same security policies as the intended CockroachDB cluster.
In AdonisJS, database configuration is often centralized in config/database.ts, and developers may reference a CockroachDB hostname via an environment variable without validating its provenance. For example, using a service discovery DNS name like cockroachdb-internal.mycompany.svc.cluster.local that later resolves to a different CockroachDB node or even a non-database service creates a path for unauthorized access or data leakage. Because AdonisJS does not inherently validate whether the resolved endpoint is the intended CockroachDB service, an attacker who can influence DNS (e.g., via a compromised internal resolver or a misconfigured external DNS) may redirect traffic to harvest credentials or inject malicious payloads. The risk is compounded if the application uses long-lived connections or connection reuse, as stale DNS caches may persist across deployments, particularly in containerized or serverless environments where DNS caching layers are opaque.
The LLM/AI Security checks in middleBrick specifically flag unresolved hostnames and unauthenticated endpoints that could be subject to manipulation, including scenarios where dangling DNS entries expose an LLM-integrated endpoint. When scanning an AdonisJS API that relies on CockroachDB, middleBrick’s runtime probes can detect whether a hostname resolves to an unexpected service during active testing, highlighting the discrepancy between expected and observed endpoints. This is a critical concern because it combines a common networking misconfiguration with the sensitivity of database traffic, increasing the likelihood of data exposure or injection. By correlating DNS resolution behavior with runtime findings, middleBrick provides prioritized findings and remediation guidance to ensure that endpoint identity is verified before sensitive queries are executed.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
To mitigate dangling DNS in AdonisJS when connecting to CockroachDB, use explicit connection parameters and avoid relying on mutable DNS aliases for production endpoints. Prefer IP addresses or fully qualified domain names with short TTLs and implement runtime validation to confirm that the resolved address matches an expected fingerprint or certificate. In AdonisJS, configure the database connection to include verification steps and avoid caching stale hostnames by forcing re-resolution on each connection cycle when necessary.
Below are concrete, syntactically correct AdonisJS configuration and code examples for connecting securely to CockroachDB. These examples assume you are using the @adonisjs/lucid ORM with the CockroachDB Postgres driver.
1. Explicit host and port in configuration
Define the host as an IP or a strict hostname with no ambiguous CNAMEs. Use environment variables for flexibility but validate their format.
// config/database.ts
import { Env } from '@ioc:Adonis/Core/Env'
export default {
connection: 'cockroach',
connections: {
cockroach: {
client: 'postgres',
host: Env.get('DB_HOST', '127.0.0.1'), // Prefer IP or exact FQDN
port: Env.get('DB_PORT', 26257),
user: Env.get('DB_USER', 'root'),
password: Env.get('DB_PASSWORD', ''),
database: Env.get('DB_NAME', 'cockroachdb'),
ssl: {
rejectUnauthorized: true,
},
},
},
} as DatabaseConfig
2. Runtime hostname verification
Before executing sensitive queries, verify that the resolved host matches an expected value. This example resolves a hostname and compares it to a known good fingerprint.
// start/hooks/verify-db-host.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import dns from 'node:dns'
import { lookup } from 'node:dns/promises'
export default class VerifyDbHost {
public async handle({ request, response, session }: HttpContextContract, next: () => Promise) {
const expectedHost = process.env.DB_HOST
if (!expectedHost) {
session?.flashNow('error', 'Database host is not configured')
response.badRequest({ error: 'Invalid configuration' })
return
}
try {
const resolved = await lookup(expectedHost, { all: true })
// Example fingerprint check: ensure at least one resolved address matches a known good list
const allowedIps = new Set(['10.0.0.5', '10.0.0.6'])
const hasValid = resolved.some((r) => allowedIps.has(r.address))
if (!hasValid) {
session?.flashNow('error', 'Database host resolved to unexpected address')
response.forbidden({ error: 'Host verification failed' })
return
}
} catch (error) {
session?.flashNow('error', 'Unable to resolve database host')
response.badRequest({ error: 'DNS resolution failed' })
return
}
await next()
}
}
3. Enforce SSL and certificate validation
CockroachDB requires strong SSL. Configure AdonisJS to reject unauthorized certificates and avoid fallback to unencrypted connections.
// config/database.ts (extended)
export default {
connection: 'cockroach',
connections: {
cockroach: {
client: 'postgres',
host: Env.get('DB_HOST'),
port: Env.get('DB_PORT'),
user: Env.get('DB_USER'),
password: Env.get('DB_PASSWORD'),
database: Env.get('DB_NAME'),
ssl: {
ca: Env.get('DB_CA_CERT_PATH'),
rejectUnauthorized: true,
},
},
},
}
4. Use connection options that limit exposure
Disable pooling or configure pool settings to reduce the chance of persistent connections to stale endpoints. This is particularly useful during deployments or DNS changes.
// config/database.ts
export default {
connection: 'cockroach',
connections: {
cockroach: {
client: 'postgres',
host: Env.get('DB_HOST'),
port: Env.get('DB_PORT'),
user: Env.get('DB_USER'),
password: Env.get('DB_PASSWORD'),
database: Env.get('DB_NAME'),
pool: {
min: 0,
max: 1,
afterCreate(client, done) {
client.query('SELECT 1', (err) => {
done(err, client)
})
},
},
ssl: {
rejectUnauthorized: true,
},
},
},
} as DatabaseConfig