@aj-archipelago/cortex
Version:
Cortex is a GraphQL API for AI. It provides a simple, extensible interface for using AI services from OpenAI, Azure and others.
74 lines (63 loc) • 2.36 kB
JavaScript
/**
* Security utilities for logging - redacts sensitive information from logs
*/
/**
* Redacts contextId for security in logs - shows first 4 and last 4 characters
* @param {string|null|undefined} contextId - The contextId to redact
* @returns {string} - Redacted contextId (e.g., "abcd...xyz1") or empty string if null/undefined
*/
export function redactContextId(contextId) {
if (!contextId || typeof contextId !== 'string') return '';
// If contextId is 8 characters or less, just show first 2 and last 2
if (contextId.length <= 8) {
if (contextId.length <= 4) {
return '****'; // Too short to show anything meaningful
}
return `${contextId.substring(0, 2)}...${contextId.substring(contextId.length - 2)}`;
}
// Show first 4 and last 4 characters for longer IDs
return `${contextId.substring(0, 4)}...${contextId.substring(contextId.length - 4)}`;
}
/**
* Redacts SAS tokens from Azure Blob Storage URLs for security in logs
* @param {string} url - The URL that may contain a SAS token
* @returns {string} - URL with SAS token redacted (everything after ? is replaced with ?[REDACTED])
*/
export function redactSasToken(url) {
if (typeof url !== 'string') return url;
// Check if it's an Azure blob URL
if (url.includes('blob.core.windows.net') || url.includes('devstoreaccount1')) {
const questionMarkIndex = url.indexOf('?');
if (questionMarkIndex !== -1) {
return url.substring(0, questionMarkIndex) + '?[REDACTED]';
}
}
return url;
}
/**
* Recursively sanitizes an object by redacting SAS tokens from URLs and contextIds
* @param {any} obj - The object to sanitize
* @returns {any} - Sanitized copy of the object
*/
export function sanitizeForLogging(obj) {
if (obj === null || obj === undefined) return obj;
if (typeof obj === 'string') {
return redactSasToken(obj);
}
if (Array.isArray(obj)) {
return obj.map(item => sanitizeForLogging(item));
}
if (typeof obj === 'object') {
const sanitized = {};
for (const [key, value] of Object.entries(obj)) {
// Redact contextId fields specifically
if (key === 'contextId' && typeof value === 'string') {
sanitized[key] = redactContextId(value);
} else {
sanitized[key] = sanitizeForLogging(value);
}
}
return sanitized;
}
return obj;
}