Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import type { GuardrailResult } from '../actions/types';
|
|
|
|
export function applyPreflightModifications(
|
|
data: string,
|
|
preflightResults: GuardrailResult[],
|
|
): string {
|
|
if (preflightResults.length === 0) {
|
|
return data;
|
|
}
|
|
|
|
// Get PII mappings from preflight results for individual text processing
|
|
const piiMappings: Record<string, string> = {};
|
|
for (const result of preflightResults) {
|
|
if (result.info?.maskEntities) {
|
|
const detected = result.info.maskEntities;
|
|
for (const [entityType, entities] of Object.entries(detected)) {
|
|
for (const entity of entities) {
|
|
// Map original PII to masked token
|
|
piiMappings[entity] = `<${entityType}>`;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Object.keys(piiMappings).length === 0) {
|
|
return data;
|
|
}
|
|
|
|
const maskText = (text: string): string => {
|
|
if (typeof text !== 'string') {
|
|
return text;
|
|
}
|
|
|
|
let maskedText = text;
|
|
|
|
// Sort PII entities by length (longest first) to avoid partial replacements
|
|
// This ensures longer matches are processed before shorter ones
|
|
const sortedPii = Object.entries(piiMappings).sort((a, b) => b[0].length - a[0].length);
|
|
|
|
for (const [originalPii, maskedToken] of sortedPii) {
|
|
if (maskedText.includes(originalPii)) {
|
|
// Use split/join instead of regex to avoid regex injection
|
|
// This treats all characters literally and is safe from special characters
|
|
maskedText = maskedText.split(originalPii).join(maskedToken);
|
|
}
|
|
}
|
|
|
|
return maskedText;
|
|
};
|
|
return maskText(data);
|
|
}
|