HIGH broken access controlstrapiapi keys

Broken Access Control in Strapi with Api Keys

Broken Access Control in Strapi with Api Keys — how this specific combination creates or exposes the vulnerability

Broken Access Control in Strapi when using API keys typically arises when policies or role-based permissions are not enforced consistently for key-authenticated requests. Strapi’s permission system relies on roles and policies to determine what actions a subject can perform on a content type. When API keys are used for authentication, the system must still validate scopes and assign the correct role to the key; if this mapping is missing or misconfigured, requests executed with the key may bypass intended restrictions.

Consider a Strapi collection type Article with custom endpoints and policies. An API key issued for a limited scope (e.g., read-only on public content) might be accepted by Strapi’s core authentication handler, but if the role assigned to that key lacks a policy that restricts find to published records only, an attacker can request unpublished or restricted records. This is a BOLA/IDOR pattern where object-level authorization is missing: the key proves identity, but not authorization for the specific resource instance.

Another scenario involves property-level authorization. Suppose a Strapi API key has permissions to read articles, but the API response inadvertently exposes sensitive fields such as author.email or internal flags like isReviewed because the GraphQL or REST response configuration does not enforce field-level permissions. Input validation failures can also interact with key-based access; if query parameters such as populate or filters are passed directly without strict allowlists, an attacker might traverse relationships to access data outside the key’s intended scope.

SSRF and unsafe consumption amplify these problems. If Strapi is deployed behind middleware that forwards requests based on API key headers without validating target URLs, an attacker may leverage the key to trigger internal network calls. Additionally, if the API key is logged or exposed in error messages or responses, data exposure occurs. The LLM/AI Security checks in middleBrick specifically detect system prompt leakage and output PII; while this does not directly test Strapi, such findings highlight how improperly surfaced information can complement broken access control by revealing roles, endpoints, or data structures that aid further exploitation.

To map this to real-world patterns, consider OWASP API Top 10 2023: Broken Object Level Authorization (BOLA). A Strapi endpoint like GET /api/articles/:id that only checks whether a record exists, without confirming that the API key’s role has rights to that specific :id, is vulnerable. PCI-DSS and SOC2 controls also require strict access governance; without scoped API keys and policy enforcement, compliance assessments may flag excessive access as a finding.

Api Keys-Specific Remediation in Strapi — concrete code fixes

Remediation centers on ensuring API keys are bound to roles with precise policies and that every endpoint enforces object-level checks. Begin by defining a dedicated role for API key usage in Strapi’s Settings → Roles & Permissions. Assign only the necessary permissions: for read-only public content, grant find and read on the specific collection type; avoid granting delete, create, or update unless strictly required.

Use environment variables to store the API key and reference it securely in your requests. Do not embed keys in client-side code. In Strapi, you can customize policies to validate key scopes. For example, create a policy that checks a custom header x-api-scope against allowed values before proceeding:

// src/policies/scope-validation.js
module.exports = async (ctx, next) => {
  const allowedScopes = ['public:read', 'admin:write'];
  const scope = ctx.request.header['x-api-scope'];
  if (!scope || !allowedScopes.includes(scope)) {
    ctx.throw(403, 'Invalid scope');
  }
  // Optionally attach scope to state for downstream policies
  ctx.state.scope = scope;
  await next();
};

Then apply this policy to the relevant route in src/config/routes.json:

{
  "routes": [
    {
      "method": "GET",
      "path": "/articles",
      "handler": "article.find",
      "policies": ["scope-validation", "rbac"]
    }
  ]
}

For object-level checks, ensure your controller or policy verifies ownership or visibility. If articles have a status field, enforce that unpublished records are only accessible to elevated roles:

// src/api/article/controllers/article.js
async find(ctx) {
  const userRole = ctx.state.user?.role || 'anonymous';
  const isAdmin = userRole === 'admin';
  const filters = { published: true };
  if (!isAdmin) {
    filters.status = 'published';
  }
  const entities = await strapi.entityService.findMany('api::article.article', {
    filters,
    pagination: ctx.pagination,
    populate: ctx.populate,
  });
  return entities;
}

When using API keys for third-party integrations, rotate keys regularly and scope them by IP or referer where possible. In the Strapi Admin, review assigned roles for each API key entry and remove unused permissions. middleBrick’s CLI can be used to scan these configurations from the terminal:

$ middlebrick scan https://your-strapi.example.com --output json

The GitHub Action can enforce a maximum risk score before merging, while the MCP Server enables scanning API endpoints directly from AI coding assistants during development. Continuous monitoring in the Pro plan helps detect regressions when roles or policies are updated.

Frequently Asked Questions

How can I verify that my Strapi API keys are scoped correctly?
Review roles under Settings → Roles & Permissions in Strapi Admin and confirm each API key’s role has only the permissions needed. Use the Strapi API to list keys programmatically and audit their assigned roles; combine this with middleBrick scans to detect overly permissive policies.
Does enabling field-level responses in Strapi fix broken access control?
No. Controlling what fields are returned is part of response configuration, but authorization must be enforced at the controller or policy level. Always validate that the requesting key’s role is allowed to access the specific resource instance and sensitive fields; response masking alone does not prevent unauthorized read or write actions.