Api Key Exposure in Restify with Firestore
Api Key Exposure in Restify with Firestore — how this specific combination creates or exposes the vulnerability
When a Restify service uses Firestore and handles API keys without strict access controls and data minimization, keys can be exposed through server-side code or misconfigured endpoints. In this combination, API keys are often stored in Firestore documents (for example, to authorize third-party integrations or to call downstream services). If a Restify endpoint retrieves or logs these keys without proper validation, rate limiting, or output filtering, the keys may be returned to clients or written to logs accessible to unintended parties.
Consider a scenario where a Restify route performs server-side operations with a Firestore document that contains an API key field. If the route does not explicitly exclude sensitive fields when constructing a response, an attacker who gains limited read access (for example, via an Insecure Direct Object Reference or insufficient property-level authorization) can receive the key in JSON output. This is a data exposure finding where sensitive material leaves the server environment.
Another exposure path arises from error messages and debugging output. If Firestore operations throw exceptions and the Restify error handler includes raw document contents or stack traces in responses, API keys stored in those documents can be reflected back to the caller. This often occurs when developers accidentally include entire Firestore snapshots in responses during rapid prototyping and forget to strip sensitive fields before sending data to the client.
LLM/AI Security checks highlight these risks when endpoints expose behavior that could lead to system prompt leakage or output that contains sensitive patterns such as API keys. For example, an endpoint that echoes Firestore document contents might inadvertently return an API key if the document contains one. The scanner tests for PII and secret patterns in outputs and flags findings where keys appear in responses without encryption or redaction.
Additionally, if the Restify service calls other internal or external APIs using keys stored in Firestore, insecure consumption practices may expose those keys through logs, monitoring tools, or SSRF-related pathways. Inventory management checks are relevant here: if Firestore documents are used to track external service credentials, the scanner will flag whether those documents are over-permissioned or whether retrieval endpoints lack proper authentication and authorization checks.
To summarize, the specific risk in this combination stems from storing sensitive material in Firestore, retrieving it through Restify routes, and failing to enforce strict output filtering, property-level authorization, and secure handling of secrets. This creates conditions where API keys can be read, logged, or returned to clients, violating data exposure best practices and increasing the likelihood of credential leakage.
Firestore-Specific Remediation in Restify — concrete code fixes
Remediation focuses on ensuring that API keys stored in Firestore are never returned to clients, are accessed with least privilege, and are handled securely within Restify routes. Below are concrete code examples that illustrate secure patterns.
First, structure your Firestore documents so that sensitive fields are excluded from client-facing responses. Use explicit projection to return only required, non-sensitive data:
// Recommended: retrieve only safe fields from Firestore
const safeFields = ['id', 'name', 'createdAt', 'integrationType'];
const doc = await firestore.doc(`integrations/${id}`).get();
if (!doc.exists) {
throw new Error('Integration not found');
}
const data = doc.data();
// Remove or omit sensitive fields before sending the response
const response = safeFields.reduce((obj, key) => {
if (data[key] !== undefined) obj[key] = data[key];
return obj;
}, {});
response.publicKey = data.publicKey; // only non-sensitive keys
res.send(response);
Second, enforce property-level authorization by validating the requesting context against document-level permissions before retrieving sensitive fields. Do not rely on client-supplied parameters to decide which fields to return:
// Secure: server decides which fields may be accessed
const requestedFields = req.query.fields ? req.query.fields.split(',') : [];
const allowedFields = new Set(['id', 'name', 'publicKey']);
const safeData = {};
for (const field of requestedFields) {
if (allowedFields.has(field)) {
safeData[field] = doc.data()[field];
}
}
res.send(safeData);
Third, avoid logging sensitive values. If you must log for debugging, explicitly redact keys:
// Redact sensitive values before logging
const logData = { ...doc.data() };
if (logData.apiKey) {
logData.apiKey = 'REDACTED';
}
logger.info('Firestore document accessed', { docId: id, ...logData });
Fourth, when your Restify service uses Firestore-stored keys to call external services, keep those keys in server-side memory only for the duration of the call and never echo them back. Use environment-based secret management where possible and ensure the Firestore document permissions limit who can read key fields:
// Use the key server-side without exposing it
const doc = await firestore.doc(`services/payment`).get();
const payload = { apiKey: doc.data().apiKey, transactionId: txId };
const result = await externalApi.call(payload);
// Do not include apiKey in any response sent to the client
res.send({ status: 'processed', transactionId: txId });
These patterns align with the scanner’s checks for Property Authorization, Data Exposure, and Unsafe Consumption. By controlling which fields are returned, how errors are handled, and how secrets are used server-side, you reduce the chances of API key exposure when using Restify with Firestore.