test(tess): cover streamed private key redaction
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful

This commit is contained in:
Jarvis
2026-07-12 19:43:53 -05:00
parent fdd58a353b
commit 726f7ab772
3 changed files with 37 additions and 1 deletions

View File

@@ -94,6 +94,31 @@ describe('ChatGateway redaction boundary', (): void => {
expect(JSON.stringify(client.emit.mock.calls)).not.toContain('canaryvalue123');
});
it('holds a streamed private key until it can be redacted', (): void => {
const { gateway } = buildGateway();
const client = {
connected: true,
id: 'client-1',
data: { user: { id: 'user-1' } },
emit: vi.fn(),
};
gateway.relayEvent(client, CONVERSATION_ID, {
type: 'message_update',
assistantMessageEvent: { type: 'text_delta', delta: '-----BEGIN PRIVATE KEY-----\ncanary' },
});
gateway.relayEvent(client, CONVERSATION_ID, {
type: 'message_update',
assistantMessageEvent: { type: 'text_delta', delta: '\n-----END PRIVATE KEY-----' },
});
expect(client.emit).toHaveBeenCalledWith('agent:text', {
conversationId: CONVERSATION_ID,
text: '[REDACTED_SECRET]',
});
expect(JSON.stringify(client.emit.mock.calls)).not.toContain('canary');
});
it('drops an oversized unterminated stream fragment rather than retaining it', (): void => {
const { gateway } = buildGateway();
const client = {

View File

@@ -858,6 +858,17 @@ export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewa
);
}
const privateKeyStart = content.lastIndexOf('-----BEGIN');
if (privateKeyStart >= 0) {
const privateKey = content.slice(privateKeyStart);
if (/-----END(?: [A-Z]+)* KEY-----/.test(privateKey)) {
// Release the complete block in one pass so the full-block classifier can redact it.
retainedFrom = content.length;
} else {
retainedFrom = Math.min(retainedFrom, privateKeyStart);
}
}
return retainedFrom;
}

View File

@@ -11,7 +11,7 @@ const SECRET_PATTERNS: RegExp[] = [
/\b(?:authorization\s*:\s*)?bearer\s+[A-Za-z0-9._~+/-]+=*/gi,
/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g,
/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,
/-----BEGIN(?: [A-Z]+)* PRIVATE KEY-----[\s\S]*?-----END(?: [A-Z]+)* PRIVATE KEY-----/g,
/-----BEGIN(?: [A-Z]+)* KEY-----[\s\S]*?-----END(?: [A-Z]+)* KEY-----/g,
/https?:\/\/[^\s?#]+[^\s]*[?&](?:token|key|secret|signature|sig)=[^\s&#]+/gi,
];
const PII_PATTERNS: RegExp[] = [