fix(security): harden spoofed system marker handling

This commit is contained in:
Peter Steinberger
2026-03-02 06:18:52 +00:00
parent 7c9d2c1d48
commit 5b8f492a48
11 changed files with 158 additions and 34 deletions

View File

@@ -44,7 +44,7 @@ import { resolveOriginMessageProvider } from "./origin-routing.js";
import { resolveQueueSettings } from "./queue.js";
import { routeReply } from "./route-reply.js";
import { BARE_SESSION_RESET_PROMPT } from "./session-reset-prompt.js";
import { ensureSkillSnapshot, prependSystemEvents } from "./session-updates.js";
import { buildQueuedSystemPrompt, ensureSkillSnapshot } from "./session-updates.js";
import { resolveTypingMode } from "./typing-mode.js";
import { resolveRunTypingPolicy } from "./typing-policy.js";
import type { TypingController } from "./typing.js";
@@ -267,9 +267,12 @@ export async function runPreparedReply(
const inboundMetaPrompt = buildInboundMetaSystemPrompt(
isNewSession ? sessionCtx : { ...sessionCtx, ThreadStarterBody: undefined },
);
const extraSystemPrompt = [inboundMetaPrompt, groupChatContext, groupIntro, groupSystemPrompt]
.filter(Boolean)
.join("\n\n");
const extraSystemPromptParts = [
inboundMetaPrompt,
groupChatContext,
groupIntro,
groupSystemPrompt,
].filter(Boolean);
const baseBody = sessionCtx.BodyStripped ?? sessionCtx.Body ?? "";
// Use CommandBody/RawBody for bare reset detection (clean message without structural context).
const rawBodyTrimmed = (ctx.CommandBody ?? ctx.RawBody ?? ctx.Body ?? "").trim();
@@ -329,13 +332,15 @@ export async function runPreparedReply(
});
const isGroupSession = sessionEntry?.chatType === "group" || sessionEntry?.chatType === "channel";
const isMainSession = !isGroupSession && sessionKey === normalizeMainKey(sessionCfg?.mainKey);
prefixedBodyBase = await prependSystemEvents({
const queuedSystemPrompt = await buildQueuedSystemPrompt({
cfg,
sessionKey,
isMainSession,
isNewSession,
prefixedBodyBase,
});
if (queuedSystemPrompt) {
extraSystemPromptParts.push(queuedSystemPrompt);
}
prefixedBodyBase = appendUntrustedContext(prefixedBodyBase, sessionCtx.UntrustedContext);
const threadStarterBody = ctx.ThreadStarterBody?.trim();
const threadHistoryBody = ctx.ThreadHistoryBody?.trim();
@@ -504,7 +509,7 @@ export async function runPreparedReply(
timeoutMs,
blockReplyBreak: resolvedBlockStreamingBreak,
ownerNumbers: command.ownerList.length > 0 ? command.ownerList : undefined,
extraSystemPrompt: extraSystemPrompt || undefined,
extraSystemPrompt: extraSystemPromptParts.join("\n\n") || undefined,
...(isReasoningTagProvider(provider) ? { enforceFinalTag: true } : {}),
},
};