Formula Injection in Adonisjs with Api Keys
Formula Injection in Adonisjs with Api Keys — how this specific combination creates or exposes the vulnerability
Formula Injection occurs when user-controlled data is interpreted as executable logic or query language within a backend system. In AdonisJS, this risk can emerge when API keys or other identifiers are used to dynamically construct database queries, filesystem paths, or configuration lookups without proper validation or parameterization. AdonisJS applications often rely on API keys to gate access to routes or to scope data visibility, and if these keys are directly embedded into query building or template rendering, an attacker may manipulate the key to inject formulas, expressions, or path traversals.
Consider a scenario where an API key is used to filter records in a controller:
const ApiKey = use('App/Models/ApiKey')
async index ({ request, auth }) {
const { key } = request.get()
const records = await Database.table('reports')
.where('api_key', key)
.select('data')
return records
}
If the API key value is attacker-controlled and used directly in a WHERE clause without sanitization, an attacker may supply a key such as ' OR 1=1; --, potentially altering the logical intent of the query. In AdonisJS, which uses Lucid ORM, raw-like behavior can manifest when dynamic query building is driven by external input. Similarly, if the API key influences file paths for configuration or report exports, an input such as ../../../etc/passwd could lead to unintended file access through path traversal, especially if concatenated without validation.
The risk is compounded when OpenAPI specs are used to generate clients or documentation without runtime validation. An API key parameter defined as a simple string in a spec may be accepted by the runtime, but if the application uses the key to construct dynamic logic (e.g., evaluating tenant-specific rules stored as JSON), formula injection may occur. For example, if an application deserializes a rule string associated with a key and evaluates it using a custom interpreter, an attacker may supply a key that maps to a rule like value => value * 2; while(true) {}, leading to resource exhaustion or code execution depending on the interpreter design.
Another vector involves environment-based configuration. AdonisJS applications often load environment variables keyed by API identifiers. If an attacker can influence which key is used to read configuration, they may cause the application to load malicious settings or bypass intended access controls. For instance, supplying a key that resolves to a sensitive configuration namespace could expose internal endpoints or credentials if the application logic does not strictly validate key scope.
These patterns align with the broader OWASP API Top 10 category of Injection, where untrusted data is sent to an interpreter as part of a command or query. In the context of API keys, the key itself becomes the injection vector when the application treats it as trusted input rather than an opaque identifier.
Api Keys-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on strict validation, parameterization, and scoping. API keys should be treated as opaque identifiers and never used to dynamically construct queries, filesystem paths, or logic expressions.
1. Use parameterized queries with Lucid ORM
Always use query builder parameterization instead of string concatenation. In AdonisJS, this means relying on where clauses with bound values:
const ApiKey = use('App/Models/ApiKey')
async index ({ request }) {
const { key } = request.only(['key'])
// Validate format before use
if (!/^[a-f0-9]{32}$/.test(key)) {
throw new Error('Invalid API key format')
}
const records = await Database.from('reports')
.where('api_key', key)
.select('id', 'data')
return records
}
This ensures the key is treated as a literal value, not executable SQL.
2. Validate and scope API keys against a model
Check that the key exists in your database and enforce tenant or scope boundaries:
async validateKey (key) {
const apiKey = await ApiKey.query()
.where('key', key)
.where('status', 'active')
.preload('scopes')
.first()
if (!apiKey) {
throw new Error('Unauthorized')
}
return apiKey
}
Use the resolved model instance to gate access rather than using the raw key in logic.
3. Avoid key-based dynamic path construction
If you must associate keys with files, map them through a controlled lookup instead of concatenation:
const mapping = {
'a1b2c3d4e5f6g7h8': 'tenant-a/config.json',
'i9j0k1l2m3n4o5p6': 'tenant-b/config.json'
}
const configPath = mapping[key]
if (!configPath) {
throw new Error('Invalid key')
}
const config = await Env.get(configPath)
return config
This prevents path traversal and ensures only approved files are accessed.
4. Use strict schema validation for incoming key formats
Leverage Joi or AdonisJS validator schemas to enforce key structure, length, and character set:
const validator = use('Validator')
async store ({ request, response }) {
const schema = validator.compile({
key: 'string|required|alpha_numeric|exact_length:32'
})
const validation = await schema.validate(request.all())
if (validation.fails()) {
return response.badRequest(validation.messages())
}
// Proceed with safe key usage
}
5. Isolate key usage from evaluation contexts
Never evaluate API keys as code or embed them in templates that may be rendered with user data. If you need tenant-specific rules, store them as structured data and interpret them with a safe, sandboxed context — not direct evaluation.
6. Leverage middleware for key normalization and scoping
Use AdonisJS middleware to attach resolved tenant or scope data to the request, reducing the need to pass raw keys through multiple layers:
async handle ({ request, auth }, next) {
const key = request.header('X-API-Key')
const tenant = await this.validateKeyAndFetchTenant(key)
request.tenant = tenant
await next()
}
This centralizes validation and reduces repeated key handling in routes.
7. Monitor and rotate keys
Implement rotation policies and revoke compromised keys. Store keys with hashing where possible and audit access logs to detect misuse patterns.
By combining strict input validation, parameterized data access, and controlled mappings, you can mitigate formula injection risks associated with API keys in AdonisJS without relying on automatic fixes or runtime blocking.