HIGH phishing api keysadonisjs

Phishing Api Keys in Adonisjs

How Phishing API Keys Manifests in Adonisjs

Phishing attacks that target API keys often start with a convincing fake login page or a deceptive email that tricks a developer into entering credentials for a service that issues keys (e.g., a payment gateway, a cloud provider, or an internal auth server). Once the attacker obtains the key, they can abuse any Adonisjs endpoint that trusts that key as a bearer token or as a secret stored in environment variables.

In an Adonisjs codebase, the most common places where a stolen key becomes useful are:

  • Controller methods that read Env.get('API_KEY') and forward it to downstream services.
  • Middleware that logs the full request object (including Authorization headers) to a file or external logging service.
  • Error handlers that return stack traces or configuration dumps when debug is enabled in production.
  • Routes that expose configuration via a health‑check or debug endpoint (e.g., /env or /config) without proper authentication.

For example, a developer might accidentally commit a .env file containing API_KEY=sk_live_.... If the repository is public, an attacker can harvest the key and then use it to call any Adonisjs route that trusts the key, such as a webhook endpoint that forwards payments to a third‑party API. Because Adonisjs does not automatically redact secrets from logs or error output, the key can also leak through log aggregation services when an error occurs and the framework prints the request context.

These patterns are not unique to Adonisjs, but the framework’s conventions — Env.get for configuration, the default Logger middleware, and the exceptionHandler — make it easy to introduce the vulnerability if developers are not aware of the data‑flow.

Adonisjs-Specific Detection

Detecting whether an Adonisjs application is leaking or improperly handling API keys involves both static inspection of the codebase and dynamic scanning of the running API. The following checks are practical:

  • Search for Env.get calls that are directly returned in a response.
  • Look for logging middleware that logs ctx.request.headers() without redacting the Authorization header.
  • Verify that config/app.js has debug: false in production and that the exceptionHandler does not expose err.message or err.stack to the client.
  • Check for any route that returns the contents of process.env or a configuration object (common in ad‑hoc debug controllers).

Dynamic testing with middleBrick complements these checks. By submitting the base URL of your Adonisjs API, middleBrick performs unauthenticated black‑box scans that include the “Data Exposure” and “Unsafe Consumption” categories. If an API key is reflected in a response body, header, or error message, middleBrick will flag it as a finding with severity “high” and provide the exact endpoint and HTTP status where the leak occurred.

Example CLI usage:

# Install the middleBrick CLI (npm package)
npm i -g middlebrick
# Scan your Adonisjs API
middlebrick scan https://api.example.com

The output will be a JSON report that you can pipe into CI pipelines. In a GitHub Action, you would add:

name: API Security Scan
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run middleBrick scan
        uses: middlebrick/action@v1
        with:
          api-url: https://staging.example.com
          fail-below: B   # fail the job if score drops below B

Similarly, the MCP Server integration lets you invoke a scan directly from your AI coding assistant (e.g., Claude or Cursor) while you are editing an Adonisjs controller, giving immediate feedback if a newly added endpoint inadvertently returns a secret.

Adonisjs-Specific Remediation

Remediation focuses on ensuring that API keys never leave the trusted boundary of the server and that logging or error handling does not inadvertently expose them. Below are concrete Adonisjs‑native fixes.

1. Load secrets through Config and never return them.

Adonisjs encourages storing secrets in .env and accessing them via the Config service. Ensure that any controller that needs to call an external service retrieves the key from config and uses it only for outbound requests.

// start/app.js
const Env = use('Env')
module.exports = {
  // ...
  providers: [
    // ...
    '@adonisjs/core/providers/EnvProvider'
  ]
}

// config/api.js
module.exports = {
  externalService: {
    apiKey: Env.get('EXTERNAL_API_KEY', '')
  }
}

// app/Controllers/Http/PaymentController.js
const Config = use('Config')
const Http = use('Http')

class PaymentController {
  async charge ({ request, response }) {
    const key = Config.get('api.externalService.apiKey')
    if (!key) {
      return response.status(500).send({ error: 'Missing API key' })
    }
    // Use the key only in an outbound request, never echo it back
    const externalResp = await Http.post('https://external.api/pay', {
      amount: request.input('amount')
    }, {
      headers: { Authorization: `Bearer ${key}` }
    })
    return response.send(externalResp.body)
  }
}
module.exports = PaymentController

2. Prevent logging of the Authorization header.

Create a custom logger middleware that redacts sensitive headers before passing the request to the default logger.

// app/Middleware/RedactAuthHeader.js
const Logger = use('Logger')

class RedactAuthHeader {
  async handle ({ request, response }, next) {
    // Clone headers and remove Authorization
    const safeHeaders = request.headers()
    delete safeHeaders.authorization
    Logger.info('Incoming request', {
      method: request.method(),
      url: request.url(),
      headers: safeHeaders
    })
    await next()
  }
}
module.exports = RedactAuthHeader

// start/kernel.js
const Middleware = use('Middleware')
Middleware.global = [
  // ...
  'App/Middleware/RedactAuthHeader'
]

3. Disable detailed error output in production.

Set debug: false in config/app.js and customize the exception handler to return a generic message.

// config/app.js
module.exports = {
  debug: Env.get('NODE_ENV', 'development') !== 'production',
  // ...
}

// app/Exceptions/Handler.js
const { HttpContextException } = use('@adonisjs/generic-exceptions')

class Handler {
  async error ({ error, response }) {
    if (error.code === 'E_ROUTE_NOT_FOUND') {
      return response.notFound().send({ error: 'Not found' })
    }
    // Never send stack trace or internal details to the client
    return response.status(error.status || 500).send({ error: 'Internal server error' })
  }
}
module.exports = Handler

4. Add .env to .gitignore and provide an .env.example file.

This prevents accidental commits of real keys while still documenting the required variables.

# .gitignore
.env

# .env.example
EXTERNAL_API_KEY=your_key_here
OTHER_SECRET=example

By applying these Adonisjs‑specific controls, you eliminate the most common pathways through which a phishing‑obtained API key could be abused or leaked. After fixing the code, run middleBrick again to confirm that the finding disappears and the security score improves.

Frequently Asked Questions

Can middleBrick fix the API key leak in my Adonisjs app automatically?
No. middleBrick only detects and reports security issues. It provides detailed findings and remediation guidance, but you must apply the fixes in your codebase (e.g., adjusting logging, error handling, or configuration usage) yourself.
Does scanning with middleBrick require me to share my Adonisjs source code or environment variables?
No. middleBrick performs unauthenticated, black‑box testing against the publicly reachable API endpoint. You only need to provide the URL; no source code, agents, or credentials are required.