HIGH api key exposurestrapi

Api Key Exposure in Strapi

How Api Key Exposure Manifests in Strapi

API key exposure in Strapi applications typically occurs through misconfigured authentication plugins, hard-coded secrets in configuration files, and improper handling of API tokens. Strapi's plugin-based architecture creates several attack surfaces where API keys can be inadvertently exposed.

The most common scenario involves Strapi's JWT authentication plugin. When configured incorrectly, JWT secrets are stored in plain text within config/plugins.js or environment files that might be committed to version control. Attackers who gain access to these files can generate valid tokens and impersonate any user.

// Vulnerable configuration - DO NOT use this pattern
module.exports = ({ env }) => ({
  jwt: {
    secret: 'my-super-secret-jwt-key', // Hard-coded secret
    expiresIn: '1d'
  }
});

Another frequent issue occurs with Strapi's API token system. Strapi allows creating API tokens with different scopes and permissions. When these tokens are generated with overly broad permissions or stored insecurely, they become high-value targets. The tokens are often embedded directly in client-side JavaScript or stored in local storage, making them vulnerable to XSS attacks.

Strapi's content-type permissions system can also lead to API key exposure. When developers enable public access to content types without proper authentication, API endpoints become accessible without any protection. This is particularly problematic for endpoints that return sensitive metadata or configuration information.

// Overly permissive content type permissions
module.exports = ({}) => ({
  'api::product.product': {
    permissions: {
      public: {
        find: true,
        findOne: true,
        create: true, // Dangerous - allows unauthenticated creation
        update: true,
        delete: true
      }
    }
  }
});

Third-party plugin vulnerabilities also contribute to API key exposure. Strapi's marketplace includes numerous authentication and payment processing plugins that may store API keys in configuration files or expose them through poorly secured endpoints. The Strapi ecosystem's rapid growth means some plugins receive limited security review.

Environment variable misconfiguration is another common problem. Developers sometimes reference undefined environment variables, causing Strapi to fall back to default or empty values. This can result in endpoints accepting any authentication token or using default secrets that are widely known.

// Vulnerable - undefined environment variable
module.exports = ({ env }) => ({
  jwt: {
    secret: env('JWT_SECRET') || 'fallback-secret', // Default secret if env var missing
    expiresIn: '1d'
  }
});

Strapi-Specific Detection

Detecting API key exposure in Strapi requires a combination of static code analysis and dynamic runtime scanning. middleBrick's API security scanner is particularly effective at identifying these vulnerabilities because it understands Strapi's specific architecture and common misconfiguration patterns.

Static analysis should focus on configuration files and source code. Look for hard-coded secrets in config/ directories, environment variable usage patterns, and authentication plugin configurations. middleBrick automatically scans these locations and identifies potential exposure points.

# middleBrick CLI scan for Strapi API
middlebrick scan https://your-strapi-app.com/api --target=strapi

Dynamic scanning involves testing the running Strapi application. middleBrick's black-box scanning approach sends requests to Strapi endpoints without requiring authentication, mimicking how an attacker would probe the system. It tests for common exposure patterns like:

  • Publicly accessible endpoints that should require authentication
  • API endpoints that return sensitive configuration data
  • Missing rate limiting on authentication endpoints
  • Improper CORS configuration exposing internal APIs

middleBrick's Strapi-specific checks include validation of JWT implementation, API token permissions, and content-type access controls. The scanner attempts to authenticate with default or weak credentials and analyzes the application's response to identify potential vulnerabilities.

Manual verification should include checking Strapi's admin panel configuration. Navigate to Settings > Users & Permissions > Roles to verify that public permissions are appropriately restricted. Also examine the API tokens section to ensure tokens have minimal necessary permissions.

Network traffic analysis can reveal API key exposure in client-side applications. Use browser developer tools to inspect API calls from single-page applications using Strapi as a backend. Look for API keys or tokens being sent in URLs, headers, or local storage that could be intercepted.

middleBrick's LLM/AI security scanning is particularly relevant for Strapi applications using AI features. The scanner checks for system prompt leakage and prompt injection vulnerabilities that could expose API keys through AI model interactions.

# Continuous monitoring with middleBrick GitHub Action
name: API Security Scan
on: [push, pull_request]
jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run middleBrick Scan
        run: |
          npx middlebrick scan https://staging.yourstrapi.com/api --format=json --output=middlebrick-report.json
      - name: Fail on low score
        run: |
          SCORE=$(jq '.score' middlebrick-report.json)
          if [ $SCORE -lt 80 ]; then exit 1; fi

Strapi-Specific Remediation

Remediating API key exposure in Strapi requires a defense-in-depth approach that addresses configuration, code, and deployment practices. Start with proper secret management using Strapi's environment variable system.

// Secure configuration pattern
module.exports = ({ env }) => ({
  jwt: {
    secret: env('JWT_SECRET'), // Always use environment variables
    expiresIn: '1d'
  },
  api: {
    token: {
      accessTokenLifetime: '15m',
      refreshTokenLifetime: '7d',
      secret: env('API_TOKEN_SECRET') // Separate secret for API tokens
    }
  }
});

Implement proper content-type permissions by default. Strapi's permission system should follow the principle of least privilege. Only grant public access to endpoints that genuinely need it, and never allow destructive operations (create, update, delete) without authentication.

// Secure content type permissions
module.exports = ({}) => ({
  'api::product.product': {
    permissions: {
      authenticated: {
        find: true,
        findOne: true,
        create: true,
        update: true,
        delete: true
      },
      public: {
        find: true,
        findOne: true
      }
    }
  }
});

API token management should follow strict guidelines. Generate tokens with minimal required scopes, use short expiration times, and implement proper revocation mechanisms. Strapi's admin panel provides token management, but programmatic control is often necessary.

// Programmatic token management
import { ApiToken } from '@strapi/admin'

// Create scoped token with minimal permissions
const createScopedToken = async (userId, scopes) => {
  try {
    const token = await ApiToken.create({
      name: 'Scoped API Token',
      userId,
      type: 'custom',
      permissions: scopes.map(scope => ({
        action: scope.action,
        subject: scope.subject
      }))
    })
    return token
  } catch (error) {
    console.error('Token creation failed:', error)
    throw error
  }
}

Implement rate limiting on authentication endpoints to prevent brute-force attacks and API key enumeration. Strapi's built-in rate limiting can be configured per endpoint.

// Rate limiting configuration
module.exports = ({ env }) => ({
  rateLimit: {
    defaultLimit: '100/hour',
    defaultHeaders: true,
    onLimitReached: () => {
      console.log('Rate limit exceeded')
    },
    onLimitMessage: 'Too many requests, please try again later.'
  }
});

Add API key validation middleware to catch malformed or suspicious requests early. This can prevent unnecessary database queries and provide early blocking of potential attacks.

// API key validation middleware
export default async (ctx, next) => {
  const authHeader = ctx.request.headers.authorization
  
  if (authHeader && authHeader.startsWith('Bearer ')) {
    const token = authHeader.substring(7)
    
    try {
      // Validate token format and signature
      const decoded = await strapi.plugins['users-permissions'].services.jwt.verify(token)
      ctx.state.user = decoded
    } catch (error) {
      ctx.status = 401
      ctx.body = { message: 'Invalid authentication token' }
      return
    }
  }
  
  await next()
}

Continuous monitoring with middleBrick Pro provides ongoing protection by scanning your Strapi APIs on a configurable schedule. Set up alerts for score drops and integrate with your CI/CD pipeline to prevent vulnerable deployments.

# middleBrick Pro continuous monitoring
middlebrick monitor https://api.yourstrapi.com \
  --schedule=daily \
  --alert=slack://webhook-url \
  --threshold=80

Frequently Asked Questions

How can I tell if my Strapi API keys are exposed?
Check your configuration files for hard-coded secrets, verify that environment variables are properly set, and use middleBrick's scanner to test your API endpoints. Look for public access to sensitive endpoints and review your content-type permissions in the admin panel.
What's the difference between JWT secrets and API tokens in Strapi?
JWT secrets are used to sign JSON Web Tokens for user authentication, while API tokens are long-lived credentials for programmatic access to Strapi's API. JWT secrets should be rotated regularly and kept highly confidential, while API tokens should have minimal permissions and short lifespans.