karajan-code 1.25.1 → 1.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/mcp/server-handlers.js +33 -0
package/package.json
CHANGED
|
@@ -823,10 +823,43 @@ function handleRoles(a) {
|
|
|
823
823
|
return runKjCommand({ command: "roles", commandArgs, options: a });
|
|
824
824
|
}
|
|
825
825
|
|
|
826
|
+
const RESUME_MAX_ANSWER_LENGTH = 500;
|
|
827
|
+
const RESUME_INJECTION_PATTERNS = [
|
|
828
|
+
/ignore\s+(previous|all|above)\s+(instructions|rules|prompts)/i,
|
|
829
|
+
/you\s+are\s+now/i,
|
|
830
|
+
/new\s+instructions?:/i,
|
|
831
|
+
/override\s+(all|security|guardrails|rules)/i,
|
|
832
|
+
/skip\s+(all\s+)?(review|test|sonar|security|solomon|guard)s?\b/i,
|
|
833
|
+
/disable\s+(tdd|review|test|sonar|security)\b/i,
|
|
834
|
+
/set\s+(status|approved|verdict)\s*(=|to|:)/i,
|
|
835
|
+
/force\s+(approve|merge|push|commit)\b/i,
|
|
836
|
+
];
|
|
837
|
+
|
|
838
|
+
export function validateResumeAnswer(answer) {
|
|
839
|
+
if (answer == null || answer === "") return { valid: true, sanitized: answer ?? null };
|
|
840
|
+
if (typeof answer !== "string") return { valid: true, sanitized: String(answer) };
|
|
841
|
+
if (answer.length > RESUME_MAX_ANSWER_LENGTH) {
|
|
842
|
+
return { valid: false, reason: `Answer too long (${answer.length} chars, max ${RESUME_MAX_ANSWER_LENGTH})` };
|
|
843
|
+
}
|
|
844
|
+
for (const pattern of RESUME_INJECTION_PATTERNS) {
|
|
845
|
+
if (pattern.test(answer)) {
|
|
846
|
+
return { valid: false, reason: "Answer rejected: matches guardrail bypass pattern" };
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
return { valid: true, sanitized: answer.trim() };
|
|
850
|
+
}
|
|
851
|
+
|
|
826
852
|
async function handleResume(a, server, extra) {
|
|
827
853
|
if (!a.sessionId) {
|
|
828
854
|
return failPayload("Missing required field: sessionId");
|
|
829
855
|
}
|
|
856
|
+
if (a.answer) {
|
|
857
|
+
const validation = validateResumeAnswer(a.answer);
|
|
858
|
+
if (!validation.valid) {
|
|
859
|
+
return failPayload(`Resume answer rejected: ${validation.reason}`);
|
|
860
|
+
}
|
|
861
|
+
a.answer = validation.sanitized;
|
|
862
|
+
}
|
|
830
863
|
applySessionOverrides(a, ["coder", "reviewer", "tester", "security", "solomon", "enableTester", "enableSecurity", "enableImpeccable"]);
|
|
831
864
|
return handleResumeDirect(a, server, extra);
|
|
832
865
|
}
|