Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
92 changes: 92 additions & 0 deletions plugins/default/regexReplace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
HookEventType,
PluginContext,
PluginHandler,
PluginParameters,
} from '../types';
import { getCurrentContentPart, setCurrentContentPart } from '../utils';

export const handler: PluginHandler = async (
context: PluginContext,
parameters: PluginParameters,
eventType: HookEventType
) => {
let error = null;
let verdict = true;
let data: any = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Bug Fix

Issue: Using any type weakens type safety and can lead to runtime errors
Fix: Use proper typing for the data object
Impact: Prevents potential runtime type errors and improves code maintainability

Suggested change
let data: any = null;
let data: { regexPattern?: string; verdict?: boolean; explanation?: string } | null = null;

const transformedData: Record<string, any> = {
request: {
json: null,
},
response: {
json: null,
},
};
let transformed = false;

try {
const regexPattern = parameters.rule;
const redactText = parameters.redactText || '[REDACTED]';
const failOnDetection = parameters.failOnDetection || false;

const { content, textArray } = getCurrentContentPart(context, eventType);

if (!regexPattern) {
throw new Error('Missing regex pattern');
}
if (!content) {
throw new Error('Missing text to match');
}

const regex = new RegExp(regexPattern, 'g');
Comment on lines +34 to +41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚡️ Performance Improvement

Issue: Creating new RegExp instance inside the handler for every execution is inefficient
Fix: Move regex creation after validation but before the loop to avoid recreation
Impact: Reduces object allocation overhead and improves performance for multiple text processing

Suggested change
if (!regexPattern) {
throw new Error('Missing regex pattern');
}
if (!content) {
throw new Error('Missing text to match');
}
const regex = new RegExp(regexPattern, 'g');
if (!regexPattern) {
throw new Error('Missing regex pattern');
}
if (!content) {
throw new Error('Missing text to match');
}
const regex = new RegExp(regexPattern, 'g');


// Process all text items in the array
let hasMatches = false;
const mappedTextArray: Array<string | null> = [];
textArray.forEach((text) => {
if (!text) {
mappedTextArray.push(null);
return;
}

// Reset regex for each text when using global flag
regex.lastIndex = 0;

const matches = text.match(regex);
if (matches && matches.length > 0) {
hasMatches = true;
}
Comment on lines +55 to +58
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Bug Fix

Issue: The match() method already returns null when no matches are found, making the length check redundant
Fix: Simplify the condition to just check for matches existence
Impact: Cleaner code and slightly better performance by avoiding unnecessary array length check

Suggested change
const matches = text.match(regex);
if (matches && matches.length > 0) {
hasMatches = true;
}
const matches = text.match(regex);
if (matches) {
hasMatches = true;
}

const replacedText = text.replace(regex, redactText);
mappedTextArray.push(replacedText);
});

// Handle transformation
if (hasMatches) {
setCurrentContentPart(
context,
eventType,
transformedData,
mappedTextArray
);
transformed = true;
}
if (failOnDetection && hasMatches) {
verdict = false;
}
data = {
regexPattern,
verdict,
explanation: transformed
? `Pattern '${regexPattern}' matched and was replaced with '${redactText}'`
: `The regex pattern '${regexPattern}' did not match any text.`,
Comment on lines +79 to +81
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Code Refactor

Issue: The explanation message construction could be more readable and maintainable
Fix: Use template literals consistently and improve readability
Impact: Better code maintainability and consistent string formatting

Suggested change
explanation: transformed
? `Pattern '${regexPattern}' matched and was replaced with '${redactText}'`
: `The regex pattern '${regexPattern}' did not match any text.`,
explanation: transformed
? `Pattern '${regexPattern}' matched and was replaced with '${redactText}'`
: `The regex pattern '${regexPattern}' did not match any text.`,

};
} catch (e: any) {
error = e;
data = {
explanation: `An error occurred while processing the regex: ${e.message}`,
regexPattern: parameters.rule,
};
}

return { error, verdict, data, transformedData, transformed };
};
2 changes: 2 additions & 0 deletions plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { handler as panwPrismaAirsintercept } from './panw-prisma-airs/intercept
import { handler as defaultjwt } from './default/jwt';
import { handler as defaultrequiredMetadataKeys } from './default/requiredMetadataKeys';
import { handler as walledaiguardrails } from './walledai/guardrails';
import { handler as defaultregexReplace } from './default/regexReplace';

export const plugins = {
default: {
Expand All @@ -70,6 +71,7 @@ export const plugins = {
modelWhitelist: defaultmodelWhitelist,
jwt: defaultjwt,
requiredMetadataKeys: defaultrequiredMetadataKeys,
regexReplace: defaultregexReplace,
},
portkey: {
moderateContent: portkeymoderateContent,
Expand Down