Crlf Injection in Strapi with Cockroachdb
Crlf Injection in Strapi with Cockroachdb — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when an attacker can inject CRLF sequences (\r\n) into data that is later reflected into headers or logs. In Strapi, this commonly arises in parameters that influence dynamic header construction, redirects, or logging before data reaches Cockroachdb. When Strapi writes user-controlled input into HTTP response headers or constructs queries that store newline-containing values in Cockroachdb, the injected CRLF can split headers, enabling HTTP response splitting, header injection, or log injection.
With Cockroachdb, the risk is not in the database engine itself but in how Strapi handles and reflects data that ultimately persists in Cockroachdb. For example, if Strapi accepts an X-Redirect-URL parameter, concatenates it into a Location header, and stores that value in Cockroachdb, an attacker can supply example.com\r\nSet-Cookie: malicious=1. The CRLF terminates the Location header early and adds a new header. Even if Cockroachdb stores the raw payload, the damage occurs at the HTTP layer when the stored value is later read and used in a redirect or header response. This makes the combination dangerous: user input enters via Strapi, persists in Cockroachdb, and is re-used in contexts where CRLF is interpreted as control characters.
Another scenario involves logging or audit trails. Strapi may log request details including parameters before inserting them into Cockroachdb. If those logs are viewed later (e.g., via an admin tool or SIEM), injected CRLF can cause log injection, leading to forged entries or disruption of log parsing. Because Cockroachdb stores the exact bytes provided by Strapi, the injected sequences remain intact and can be replayed when data is exported or displayed in vulnerable admin interfaces.
OpenAPI specs can inadvertently encourage this risk if path or query parameters are not explicitly constrained to disallow control characters. Without strict validation in Strapi’s input pipeline, an OpenAPI description that accepts free-form strings becomes a vector. During unauthenticated scans, middleBrick checks for missing input validation on string parameters and flags CRLF injection as a finding when newline characters are accepted without sanitization or strict schema enforcement.
Cockroachdb-Specific Remediation in Strapi — concrete code fixes
Remediation focuses on preventing CRLF characters from being accepted, stored, or reflected. In Strapi, validate and sanitize all user input before it reaches services that interact with Cockroachdb. Use Strapi’s built-in validation rules and custom sanitizers to strip or reject \r and \n characters where inappropriate. For fields stored in Cockroachdb that may later be used in headers, URLs, or logs, enforce a strict schema that disallows control characters.
Example: If you have a content type redirect with a url field, define a validation rule that rejects CRLF. In your schema JSON, set validation for the string field to disallow newline characters.
// path: ./src/api/redirect/content-types/redirect/schema.json
{
"kind": "collectionType",
"collectionName": "redirects",
"info": { "singularName": "redirect", "pluralName": "redirects" },
"options": { "draftAndPublish": false },
"attributes": {
"url": {
"type": "string",
"required": true,
"pattern": "^(?!.*[\\r\\n])(https?://).+$"
}
}
}
This pattern ensures that any string containing \r or \n is rejected at the model level before Strapi attempts to insert into Cockroachdb. For fields that must accept free text, sanitize on input by removing \r and \n:
// path: ./src/api/redirect/content-types/redirect/controllers/redirect.js
module.exports = {
async create(ctx) {
const { url } = ctx.request.body;
const sanitizedUrl = url.replace(/[\r\n]/g, '');
const entry = await strapi.entityService.create('api::redirect.redirect', {
data: { url: sanitizedUrl }
});
return entry;
}
};
When using dynamic headers or redirects, avoid directly concatenating stored Cockroachdb values into header strings. Instead, use a whitelist approach for known-safe domains or use Strapi’s built-in URL utilities to construct safe Location headers. For example, if you store a redirect target in Cockroachdb, validate it against an allowlist or ensure it’s a relative path when possible:
// path: ./src/api/redirect/content-types/redirect/controllers/redirect.js
const isSafeRedirect = (href) => {
try {
const url = new URL(href);
return url.hostname.endsWith('.example.com');
} catch {
return false;
}
};
module.exports = {
async find(ctx) {
const entries = await strapi.entityService.findMany('api::redirect.redirect');
return entries.map(e => {
if (isSafeRedirect(e.url)) {
return {
...e,
safeUrl: e.url
};
}
return {
...e,
safeUrl: '/fallback';
};
});
}
};
For logging, configure Winston or Pino transports used by Strapi to sanitize newlines before writing to files or external stores. This prevents log injection when logs contain data fetched from Cockroachdb that may have been originally rejected but exist in historic records.
middleBrick can help identify missing input validation around string fields that could permit CRLF injection. When scanning an endpoint that writes to Cockroachdb, it checks whether user-controlled fields allow \r or \n and reports findings with severity and remediation guidance. In the Pro plan, continuous monitoring can alert you if new endpoints or models introduce patterns that permit control characters, helping maintain secure handling across schema changes.