HIGH api key exposuresails

Api Key Exposure in Sails

How Api Key Exposure Manifests in Sails

Api key exposure in Sails applications typically occurs through several distinct attack vectors that leverage the framework's conventions and common implementation patterns. One of the most prevalent issues arises from configuration file management. Sails applications often store API keys in config files like config/local.js or config/production.js, which may inadvertently be committed to version control or deployed to production environments where they become accessible to unauthorized users.

Another common manifestation occurs through error responses that leak sensitive information. Sails's default error handling can expose API keys in stack traces or error messages when exceptions occur during API calls. For instance, if an application makes an external API call using an exposed key and that call fails, the error response might include the full request including the API key in the response body or headers.

Middleware misconfiguration presents another significant risk. Sails applications frequently use middleware for authentication, logging, or request processing. If API keys are passed through request headers or query parameters and the middleware logs requests without proper sanitization, these keys can end up in log files that are accessible to developers or stored in centralized logging systems.

Client-side exposure represents a particularly insidious variant. Sails applications that expose API keys to client-side JavaScript for making direct API calls create a fundamental security vulnerability. Even if the keys are obfuscated or stored in environment variables, they become accessible to anyone who can inspect the browser's network traffic or view the source code.

Environment variable leakage through Sails's configuration system can also expose API keys. While Sails encourages using environment variables for sensitive data, improper configuration can cause these variables to be exposed through the application's configuration endpoints or debug interfaces.

Sails-Specific Detection

Detecting API key exposure in Sails applications requires a multi-faceted approach that combines static analysis with runtime testing. Start by examining your configuration files for hardcoded credentials. Use this command to search for common API key patterns across your Sails project:

grep -r -E "(sk-[a-zA-Z0-9]{20}|pk-[a-zA-Z0-9]{20}|AIza[0-9A-Za-z_-]{35}|Bearer\s+[a-zA-Z0-9\-\._~\+\/]+=*)" config/

This regex pattern catches common API key formats from services like Stripe, Google Cloud, and generic Bearer tokens. For a more comprehensive scan, use middleBrick's API scanning capabilities which can detect exposed API keys in runtime environments without requiring access to source code.

middleBrick's scanning engine specifically looks for API key exposure patterns in Sails applications by testing unauthenticated endpoints and analyzing response headers, body content, and error messages. The scanner identifies keys using a database of 500+ known API key patterns and can detect keys even when they're obfuscated or encoded.

Runtime detection should include monitoring your application's error responses. Set up a test endpoint that intentionally triggers errors and examine the response for any exposed credentials. Additionally, review your Sails application's logging configuration to ensure API keys are not being logged in plain text.

For production deployments, implement request logging analysis to detect any API keys appearing in client-accessible responses. Tools like middleBrick can continuously monitor your API endpoints and alert you when new instances of API key exposure are detected.

Sails-Specific Remediation

Remediating API key exposure in Sails applications requires both code changes and process improvements. Start by implementing proper configuration management using Sails's built-in configuration system. Move all API keys to environment variables and access them through sails.config:

// config/apiKeys.js
module.exports.apiKeys = {
  stripe: process.env.STRIPE_SECRET_KEY,
  twilio: process.env.TWILIO_ACCOUNT_SID,
  mapbox: process.env.MAPBOX_API_KEY
};

// policies/apiKeyPolicy.js
module.exports = async function (req, res, next) {
  const requiredKeys = ['stripe', 'twilio'];
  const missingKeys = requiredKeys.filter(key => !sails.config.apiKeys[key]);
  
  if (missingKeys.length > 0) {
    return res.status(500).json({
      error: 'Missing API configuration',
      missing: missingKeys
    });
  }
  
  next();
};

Implement comprehensive error handling that never exposes API keys in error responses. Create a custom error handler that sanitizes all error messages before sending them to clients:

// api/hooks/customErrorHandler.js
module.exports = function (sails) {
  return {
    initialize: function (cb) {
      sails.on('router:request', (req, res) => {
        const originalSend = res.send;
        res.send = function (body) {
          if (typeof body === 'object' && body.error) {
            // Remove any sensitive information from error objects
            delete body.error.apiKey;
            delete body.error.token;
          }
          return originalSend.call(this, body);
        };
      });
      cb();
    }
  };
};

Configure Sails's logging system to redact API keys from all log entries. Create a custom logger that automatically masks sensitive information:

// config/log.js
module.exports.log = {
  custom: function (msg, data) {
    const redacted = JSON.stringify(data, (key, value) => {
      if (key.match(/key|token|secret|password/i)) {
        return 'REDACTED';
      }
      return value;
    });
    
    sails.log.verbose(msg, JSON.parse(redacted));
  }
};

For client-side API calls, implement a proxy service that keeps API keys server-side. Create a Sails controller that makes external API calls on behalf of the client:

// api/controllers/apiProxyController.js
module.exports = {
  proxyRequest: async function (req, res) {
    const { service, endpoint, data } = req.body;
    
    // Validate the requested service
    const allowedServices = ['stripe', 'twilio', 'mapbox'];
    if (!allowedServices.includes(service)) {
      return res.status(400).json({ error: 'Invalid service' });
    }
    
    try {
      const response = await sails.helpers.makeExternalApiCall(service, endpoint, data);
      return res.json(response);
    } catch (error) {
      return res.status(500).json({ error: 'Proxy request failed' });
    }
  }
};

Finally, implement automated security testing in your CI/CD pipeline using middleBrick's GitHub Action to scan your APIs before deployment:

name: API Security Scan
on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Run middleBrick Security Scan
        uses: middlebrick/middlebrick-action@v1
        with:
          api-url: ${{ secrets.API_URL }}
          fail-on-severity: high
        env:
          MIDDLEBRICK_API_KEY: ${{ secrets.MIDDLEBRICK_API_KEY }}

Frequently Asked Questions

How can I test my Sails application for API key exposure without exposing production credentials?
Create a dedicated test environment with mock API keys that follow the same format as your production keys. Use middleBrick's scanning capabilities to test your staging environment, which should mirror your production configuration but use non-functional test credentials. This allows you to identify exposure patterns without risking actual API key compromise.
Does middleBrick detect API key exposure in Sails applications that use environment variables?
Yes, middleBrick can detect API key exposure regardless of how keys are stored. The scanner tests runtime endpoints and analyzes responses for exposed credentials, whether they're hardcoded, in environment variables, or stored in configuration files. It also checks for keys appearing in error responses, logs, and client-side code.