Api Key Exposure in Adonisjs
How Api Key Exposure Manifests in Adonisjs
Api key exposure in Adonisjs applications typically occurs through several specific patterns that are unique to the framework's architecture and conventions. The most common scenario involves developers accidentally committing API keys to version control, particularly when using environment variables for configuration.
Adonisjs applications often structure API keys in the config/ directory, where developers might create files like config/services.js or config/api.js>. A typical vulnerable pattern looks like:
const Env = use('Env')
module.exports = {
apiKey: Env.get('API_KEY', 'default-key'),
secretKey: Env.get('SECRET_KEY', 'fallback-secret')
}
The critical vulnerability here is the use of fallback values. When the environment variable isn't set, the application defaults to hardcoded values, which often end up in production. This creates a situation where the API key is exposed both in the codebase and potentially in runtime logs.
Another Adonisjs-specific pattern involves the framework's service providers. Developers might create a service provider that initializes API clients with keys:
class ApiServiceProvider {
async boot () {
const apiKey = Env.get('API_KEY')
this.app.apiClient = new ApiClient(apiKey)
}
}
If this provider is registered in start/app.js and the environment variable isn't properly set, the application might throw errors or, worse, expose the key through error messages.
Middleware is another common attack vector. Adonisjs developers often create authentication middleware that logs API keys for debugging:
class ApiKeyLogger {
async handle ({ request }, next) {
const apiKey = request.header('x-api-key')
console.log('API Key:', apiKey) // Vulnerable logging
await next()
}
}
This pattern is particularly dangerous because it exposes the key in application logs, which might be stored in plaintext or sent to external logging services.
Adonisjs-Specific Detection
Detecting API key exposure in Adonisjs applications requires understanding the framework's specific patterns and conventions. The most effective approach combines static analysis with runtime scanning.
Static analysis should focus on the config/ directory and service provider files. Look for patterns like:
# Check for hardcoded API keys in config files
grep -r "apiKey\|secretKey\|API_KEY" config/ --include="*.js"
# Check for fallback values in environment variable usage
grep -r "Env.get('.*',.*)'" config/ --include="*.js"
Runtime detection involves monitoring the application's behavior. When an Adonisjs application starts, it loads all configuration files. If API keys are hardcoded or have fallback values, they'll be loaded into memory. Monitoring tools can detect these patterns by examining the application's configuration object after initialization.
The middleBrick API security scanner specifically detects API key exposure in Adonisjs applications through several mechanisms:
- Configuration file analysis: Scans
config/directory for hardcoded keys and fallback values - Environment variable validation: Checks if required API keys are properly configured without defaults
- Middleware inspection: Identifies logging patterns that might expose keys
- Service provider analysis: Examines how API clients are initialized
middleBrick's scanning process for Adonisjs applications takes approximately 5-15 seconds and requires no credentials or setup. Simply provide the API endpoint URL, and the scanner will test for exposed keys across all 12 security categories, including the specific Adonisjs patterns mentioned above.
The scanner also performs active testing by sending requests with common API key patterns to identify endpoints that might be vulnerable to key exposure through response headers or error messages.
Adonisjs-Specific Remediation
Remediating API key exposure in Adonisjs applications requires a systematic approach that leverages the framework's built-in features while following security best practices.
The first step is to eliminate fallback values in configuration files. Instead of providing defaults, explicitly require environment variables:
const Env = use('Env')
module.exports = {
apiKey: Env.getOrFail('API_KEY'),
secretKey: Env.getOrFail('SECRET_KEY')
}
The Env.getOrFail() method throws an exception if the environment variable isn't set, preventing the application from starting with insecure defaults.
For service providers, implement proper error handling and validation:
class ApiServiceProvider {
async boot () {
try {
const apiKey = Env.getOrFail('API_KEY')
this.app.apiClient = new ApiClient(apiKey)
} catch (error) {
throw new Error('API key not configured. Set API_KEY in environment variables.')
}
}
}
This approach ensures that the application fails fast if API keys aren't properly configured, rather than running with insecure defaults.
Middleware should never log sensitive information. Instead, use structured logging with proper redaction:
class ApiKeyLogger {
async handle ({ request }, next) {
const apiKey = request.header('x-api-key')
// Log only the presence, not the value
Logger.info('API key received', { keyPresent: !!apiKey })
await next()
}
}
For production deployments, implement environment-specific configuration validation. Adonisjs allows creating different configuration files for different environments:
// config/api.js
const Env = use('Env')
module.exports = ({
apiKey: Env.get('API_KEY')
})Then create environment-specific overrides in .env files and validate them during deployment:
// start/hooks.js
const { hooks } = require('@adonisjs/fold')
hooks.after.providersBooted(() => {
const Env = use('Env')
if (!Env.get('API_KEY')) {
throw new Error('API_KEY is required but not set in environment')
}
})
This hook ensures that the application won't start without the required API keys, preventing accidental exposure through default values.