perf(security): bound regex input in filters and redaction

This commit is contained in:
Peter Steinberger
2026-03-02 16:37:23 +00:00
parent 31c7637e0f
commit b1592457fa
6 changed files with 103 additions and 5 deletions

View File

@@ -318,6 +318,17 @@ describe("DiscordExecApprovalHandler.shouldHandle", () => {
expect(handler.shouldHandle(createRequest({ sessionKey: `${"a".repeat(28)}!` }))).toBe(false);
});
it("matches long session keys with tail-bounded regex checks", () => {
const handler = createHandler({
enabled: true,
approvers: ["123"],
sessionFilter: ["discord:tail$"],
});
expect(
handler.shouldHandle(createRequest({ sessionKey: `${"x".repeat(5000)}discord:tail` })),
).toBe(true);
});
it("filters by discord account when session store includes account", () => {
writeStore({
"agent:test-agent:discord:channel:999888777": {

View File

@@ -34,6 +34,7 @@ import { createDiscordClient, stripUndefinedFields } from "../send.shared.js";
import { DiscordUiContainer } from "../ui.js";
const EXEC_APPROVAL_KEY = "execapproval";
const SESSION_FILTER_REGEX_MAX_INPUT = 2048;
export type { ExecApprovalRequest, ExecApprovalResolved };
@@ -367,12 +368,28 @@ export class DiscordExecApprovalHandler {
if (!session) {
return false;
}
const head = session.slice(0, SESSION_FILTER_REGEX_MAX_INPUT);
const tail =
session.length > SESSION_FILTER_REGEX_MAX_INPUT
? session.slice(-SESSION_FILTER_REGEX_MAX_INPUT)
: "";
const matches = config.sessionFilter.some((p) => {
if (session.includes(p)) {
return true;
}
const regex = compileSafeRegex(p);
return regex ? regex.test(session) : false;
if (!regex) {
return false;
}
regex.lastIndex = 0;
if (regex.test(head)) {
return true;
}
if (tail) {
regex.lastIndex = 0;
return regex.test(tail);
}
return false;
});
if (!matches) {
return false;