Api Key Exposure in Strapi with Mysql
Api Key Exposure in Strapi with Mysql — how this specific combination creates or exposes the vulnerability
Strapi stores environment-specific configuration such as database credentials and third-party service tokens in files like .env or database.js. When the project uses MySQL as the database, these configuration files often contain API keys or connection strings that, if inadvertently exposed through an insecure endpoint, lead to API key exposure. Because Strapi’s admin panel and REST/GraphQL endpoints can reflect configuration or error messages, an attacker performing unauthenticated black-box scanning can sometimes retrieve sensitive values through verbose error responses or misconfigured routes.
In a MySQL-backed Strapi deployment, API key exposure commonly occurs when sensitive values are stored in environment variables (e.g., DATABASE_PASSWORD, JWT_SECRET, or custom service keys) and later referenced in Strapi’s configuration files. If the application serves debug endpoints or if the database connection fails in a way that exposes stack traces, those errors might leak the keys or patterns that help an attacker infer them. Additionally, if Strapi generates OpenAPI specs dynamically and those specs are publicly accessible, hardcoded examples or default values might reveal placeholder API keys that resemble real secrets.
During an unauthenticated scan, middleBrick runs 12 security checks in parallel, including Data Exposure and Authentication, to identify endpoints that may disclose sensitive information. For a Strapi + MySQL setup, this means testing error handling, introspection routes, and any publicly reachable GraphQL or REST endpoints that might echo configuration details. The LLM/AI Security checks also probe for system prompt leakage and output scanning, ensuring that if an API response includes API-like strings or secrets, they are flagged. Findings will reference relevant attack patterns such as insecure error handling and misconfigured CORS, which can amplify exposure when combined with MySQL connection strings stored in accessible config files.
Remediation guidance centers on configuration hygiene and access control. Use environment variables injected at runtime rather than storing keys in version-controlled files, restrict network access to the MySQL instance, and ensure Strapi’s admin routes are not publicly exposed. middleBrick’s reports will map findings to frameworks like OWASP API Top 10 and provide prioritized remediation steps without claiming to fix or block anything directly.
Mysql-Specific Remediation in Strapi — concrete code fixes
To reduce API key exposure when Strapi uses MySQL, apply configuration changes that prevent sensitive values from appearing in code or logs. Always use environment variables and avoid hardcoding credentials in config/database.js. Below are concrete, syntactically correct examples tailored for Strapi with MySQL.
1. Securing database configuration
Replace static configuration with environment-aware logic. This ensures credentials are supplied at runtime and not persisted in files that might be exposed.
// config/database.js
module.exports = ({ env }) => ({
defaultConnection: 'default',
connections: {
default: {
connector: 'bookshelf',
settings: {
client: 'mysql',
host: env('DATABASE_HOST', '127.0.0.1'),
port: env.int('DATABASE_PORT', 3306),
database: env('DATABASE_NAME', 'strapi'),
username: env('DATABASE_USERNAME', 'strapi'),
password: env('DATABASE_PASSWORD', ''),
ssl: env.bool('DATABASE_SSL', false) ? { rejectUnauthorized: false } : false,
},
options: {
timezone: 'UTC',
debug: false,
},
},
},
});
2. Securing JWT and admin routes
Ensure JWT secrets and admin paths are not predictable or exposed in error messages.
// config/server.js
module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
admin: {
path: env('ADMIN_PATH', '/admin'),
cookieSecret: env('ADMIN_COOKIE_SECRET', 'a-secure-random-value-change-this'),
},
jwt: {
secret: env('JWT_SECRET', 'another-secure-random-value-change-this'),
},
});
3. Safeguarding error responses
Disable verbose errors in production to prevent stack traces that might reference keys or internal paths.
// config/env/production.js
module.exports = ({ env }) => ({
strapi: {
admin: {
autoOpen: false,
},
graphql: {
playground: false,
endpoint: '/graphql',
},
},
errors: {
stack: false,
},
});
4. Securing environment variables
Use a runtime injection mechanism so secrets are never stored in the repository. Example for a deployment platform that injects env vars:
# .env (do not commit this file)
DATABASE_HOST=db.example.com
DATABASE_PORT=3306
DATABASE_NAME=strapi_production
DATABASE_USERNAME=app_user
DATABASE_PASSWORD=SuperSecretPassword123
JWT_SECRET=complex-jwt-signing-key-2024
ADMIN_PATH=/secure-admin
DATABASE_SSL=true
5. Validate MySQL user permissions
Create a dedicated MySQL user with least-privilege access to limit impact if credentials are ever exposed.
-- MySQL example: create a restricted user for Strapi
CREATE USER 'strapi_user'@'app-host.example.com' IDENTIFIED BY 'StrongPassword!234';
GRANT SELECT, INSERT, UPDATE, DELETE ON strapi.* TO 'strapi_user'@'app-host.example.com';
FLUSH PRIVILEGES;