@juspay/neurolink
Version:
Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio
122 lines • 4.88 kB
JavaScript
/**
* WordObfuscator — inserts zero-width characters into sensitive words so
* that naive string-matching by upstream APIs cannot detect them.
*
* For example, "proxy" becomes "p\u200Broxy" (ZWS after the first character),
* making the text visually identical to humans but different at the byte level.
*/
/** Unicode zero-width space (U+200B). */
const ZWS = "\u200B";
/**
* Insert a zero-width space after the first character.
* This defeats simple substring matching while preserving readability.
*/
function obfuscateWord(word) {
if (word.length <= 1) {
return word;
}
return word.charAt(0) + ZWS + word.slice(1);
}
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
/**
* Replace all case-insensitive occurrences of each sensitive word in `text`
* with the obfuscated version, preserving original casing.
*
* Words are sorted longest-first so that longer matches take priority over
* shorter substrings (e.g., "load balancer" matches before "load").
*/
function obfuscateText(text, sortedWords) {
let result = text;
for (const word of sortedWords) {
const pattern = new RegExp(escapeRegExp(word), "gi");
result = result.replace(pattern, (match) => obfuscateWord(match));
}
return result;
}
/** Default sensitive words that might reveal proxy usage. */
const DEFAULT_SENSITIVE_WORDS = [
"proxy",
"neurolink",
"load balancer",
"round-robin",
"failover",
"multi-account",
];
export function createWordObfuscator(customWords) {
const words = customWords ?? [...DEFAULT_SENSITIVE_WORDS];
// Sort longest-first so longer matches take priority
const sorted = [...words].sort((a, b) => b.length - a.length);
return {
name: "word-obfuscator",
order: 40,
enabled: true,
async transformRequest(ctx) {
const messages = ctx.request.body.messages.map((msg) => {
if (typeof msg.content === "string") {
return { ...msg, content: obfuscateText(msg.content, sorted) };
}
if (Array.isArray(msg.content)) {
const obfuscatedContent = msg.content.map((block) => {
if (block.type === "text" && typeof block.text === "string") {
return {
...block,
text: obfuscateText(block.text, sorted),
};
}
// Obfuscate tool_result content (string or nested blocks)
if (block.type === "tool_result") {
if (typeof block.content === "string") {
return {
...block,
content: obfuscateText(block.content, sorted),
};
}
if (Array.isArray(block.content)) {
const obfuscatedBlocks = block.content.map((inner) => {
if (inner.type === "text" && typeof inner.text === "string") {
return {
...inner,
text: obfuscateText(inner.text, sorted),
};
}
return inner;
});
return { ...block, content: obfuscatedBlocks };
}
}
return block;
});
return { ...msg, content: obfuscatedContent };
}
return msg;
});
// Also obfuscate system prompt if present
let system = ctx.request.body.system;
if (typeof system === "string") {
system = obfuscateText(system, sorted);
}
else if (Array.isArray(system)) {
system = system.map((block) => {
if (block.type === "text" && typeof block.text === "string") {
return { ...block, text: obfuscateText(block.text, sorted) };
}
return block;
});
}
return {
...ctx,
request: {
...ctx.request,
body: {
...ctx.request.body,
messages,
...(system !== undefined ? { system } : {}),
},
},
};
},
};
}
//# sourceMappingURL=wordObfuscator.js.map