Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/cache/redisPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ client.on('connect', () => {
});

client.on('error', (err: any) => {
console.error('🚨 [Cache Critical] Redis memory pool encountered an error:', err);
console.error('🚨 [Cache Critical] Redis memory pool encountered an error:', err instanceof Error ? err.message : String(err));
});

client.on('end', () => {
Expand All @@ -34,7 +34,7 @@ if (process.env.NODE_ENV !== 'test') {
try {
await client.connect();
} catch (err) {
console.error('🚨 [Cache Fault] Immediate initialization failed. Running in degraded failover state.', err);
console.error('🚨 [Cache Fault] Immediate initialization failed. Running in degraded failover state.', err instanceof Error ? err.message : String(err));
}
})();
}
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/verifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export async function verifyCryptographicProof(rawProof: string, expectedHash?:
} catch (error) {
// Sentinel: Log only unexpected errors to prevent log flooding from malformed client input
if (!(error instanceof SyntaxError)) {
console.error("Critical: Security framework evaluation failure inside verifier engine:", error);
console.error("Critical: Security framework evaluation failure inside verifier engine:", error instanceof Error ? error.message : String(error));
}
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/gateway/sessionMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export async function cipherTubeGateway(req: Request, res: Response, next: NextF

} catch (err) {
// Enforce fallback state containment
console.error("Gateway Processing Error:", err);
console.error("Gateway Processing Error:", err instanceof Error ? err.message : String(err));
return res.status(500).json({
status: "error",
message: "Internal cryptographic channel fault."
Expand Down
16 changes: 3 additions & 13 deletions src/os/persistence/PersistenceLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,12 @@ export class PersistenceLayer {
*/
save(data: any, key: string): Buffer {
const payload = JSON.stringify(data);
const payloadBuf = Buffer.from(payload, 'utf8');

// Bolt Optimization: Allocate unsafe buffer for exact combined size to avoid Buffer.concat and intermediate payload allocations
const outBuf = Buffer.allocUnsafe(38 + payloadBuf.length);

// Copy pre-allocated header and payload
outBuf.set(HEADER_BUF, 0);
outBuf.set(payloadBuf, 38);
const payloadByteLength = Buffer.byteLength(payload, 'utf8');

// Compute and write HMAC signature directly
const hmac = crypto.createHmac('sha256',. key);
hmac.update(payloadBuf);
const hmac = crypto.createHmac('sha256', key);
hmac.update(payload, 'utf8');
const signature = hmac.digest();
outBuf.set(signature, 6);

const payloadByteLength = Buffer.byteLength(payload, 'utf8');
const out = Buffer.allocUnsafe(HEADER_LENGTH + SIGNATURE_LENGTH + payloadByteLength);

// Zero-copy set of pre-allocated header
Expand Down
74 changes: 74 additions & 0 deletions tests/sentinel_sanitized_logs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Request, Response } from 'express';
import { cipherTubeGateway } from '../src/gateway/sessionMiddleware';
import { verifyCryptographicProof } from '../src/crypto/verifier';

describe('Sanitized Error Logging Security Controls', () => {
let consoleErrorSpy: jest.SpyInstance;

beforeEach(() => {
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
});

afterEach(() => {
consoleErrorSpy.mockRestore();
});

it('should log sanitized error string in gateway middleware without leaking raw error object', async () => {
const req = {
headers: {
'x-cipher-proof': 'valid_proof',
'x-cipher-hash': 'valid_hash'
}
} as unknown as Request;

const res = {
status: jest.fn().mockReturnThis(),
json: jest.fn()
} as unknown as Response;

const next = jest.fn();

// Create a custom error object with extra sensitive property
const sensitiveError = new Error('Database connection failed');
(sensitiveError as any).sensitiveCredential = 'secret_password_123';

const { cache } = require('../src/cache/redisPool');
jest.spyOn(cache, 'get').mockRejectedValueOnce(sensitiveError);

await cipherTubeGateway(req, res, next);

expect(res.status).toHaveBeenCalledWith(500);
expect(consoleErrorSpy).toHaveBeenCalled();
const callArgs = consoleErrorSpy.mock.calls[0];
// Ensure the second argument passed to console.error is a string (message), not the raw Error object
expect(typeof callArgs[1]).toBe('string');
expect(callArgs[1]).toBe('Database connection failed');
expect(callArgs[1]).not.toContain('secret_password_123');
});

it('should log sanitized error string in verifyCryptographicProof on unexpected failure', async () => {
const sensitiveError = new Error('Crypto subsystem failure');
(sensitiveError as any).internalState = 'heap_dump_0x123';

const crypto = require('crypto');
const hmacSpy = jest.spyOn(crypto, 'createHmac').mockImplementationOnce(() => {
throw sensitiveError;
});

const proof = {
salt: Date.now(),
structuralHash: 'test',
challengeProof: 'abc'
};
const rawProof = Buffer.from(JSON.stringify(proof)).toString('base64');
const result = await verifyCryptographicProof(rawProof);

expect(result).toBe(false);
expect(consoleErrorSpy).toHaveBeenCalled();
const callArgs = consoleErrorSpy.mock.calls[0];
expect(typeof callArgs[1]).toBe('string');
expect(callArgs[1]).toBe('Crypto subsystem failure');

hmacSpy.mockRestore();
});
});