fix(security): disable config leak detection to prevent false positives

StripConfigLeak was blocking legitimate responses when predefined agents
mentioned SOUL.md/IDENTITY.md/AGENTS.md in architecture explanations.
Improved detection logic to exclude code blocks but disabled the gate
entirely for now until a more robust approach is designed.
This commit is contained in:
viettranx committed 2026-03-10 23:11:02 +07:00
1 parent b9e9e6e34a
commit ee31387aa1
3 files changed
+43 -6

No files matched your search

+3 -2
View File
@@ -887,8 +887,9 @@ func (l *Loop) runLoop(ctx context.Context, req RunRequest) (*RunResult, error)
// 4. Full sanitization pipeline (matching TS extractAssistantText + sanitizeUserFacingText)
finalContent = SanitizeAssistantContent(finalContent)
// 4b. Config leak detection (predefined agents only)
finalContent = StripConfigLeak(finalContent, l.agentType)
// 4b. Config leak detection — disabled: too many false positives
// (e.g. agent explaining public architecture mentioning SOUL.md etc.)
// finalContent = StripConfigLeak(finalContent, l.agentType)
// 5. Handle NO_REPLY: save to session for context but mark as silent.
// Matching TS: NO_REPLY is saved (via resolveSilentReplyFallbackText) but
+19 -4
View File
@@ -322,22 +322,37 @@ var configLeakFileNames = []string{
"internal_config", "system prompt",
}
// Patterns to strip markdown code from content before config leak detection.
// Mentions inside code blocks/inline code are typically architecture docs, not leaks.
var fencedCodeBlockPattern = regexp.MustCompile("(?s)```[^`]*```")
var inlineCodePattern = regexp.MustCompile("`[^`\n]+`")
// stripMarkdownCode removes fenced code blocks and inline code from text.
func stripMarkdownCode(s string) string {
s = fencedCodeBlockPattern.ReplaceAllString(s, "")
s = inlineCodePattern.ReplaceAllString(s, "")
return s
}
// StripConfigLeak detects when a predefined agent dumps its internal configuration
// (e.g. referencing SOUL.md, AGENTS.md, IDENTITY.md) and replaces the entire
// response with a friendly decline.
//
// Only active for predefined agents. Single-gate detection:
// 3+ distinct internal file names mentioned → replace entire response.
// A predefined agent legitimately referencing 3+ internal config files in one
// response is essentially impossible, so this has no false-positive risk.
// 3+ distinct internal file names mentioned in plain text → replace entire response.
// Mentions inside markdown code blocks and inline code are excluded from counting,
// as they typically appear in architecture explanations rather than actual leaks.
func StripConfigLeak(content, agentType string) string {
if agentType != "predefined" || content == "" {
return content
}
// Count hits only in plain text (outside code blocks/inline code)
plain := stripMarkdownCode(content)
hits := 0
for _, name := range configLeakFileNames {
if strings.Contains(content, name) {
if strings.Contains(plain, name) {
hits++
}
}
@@ -75,6 +75,27 @@ Có gì anh hỏi thêm nhé!`,
content: "",
agentType: "predefined",
},
{
name: "predefined - config names in fenced code block (architecture docs)",
content: "Đây là cấu trúc hệ thống:\n\n```\nagents/\n├── SOUL.md\n├── IDENTITY.md\n├── AGENTS.md\n├── BOOTSTRAP.md\n└── TOOLS.md\n```\n\nAnh cần gì thêm không?",
agentType: "predefined",
},
{
name: "predefined - config names in inline code",
content: "Mỗi agent có các file `SOUL.md`, `IDENTITY.md`, `AGENTS.md` để cấu hình.",
agentType: "predefined",
},
{
name: "predefined - mixed: code block + plain text below threshold",
content: "Hệ thống dùng:\n\n```\nSOUL.md\nIDENTITY.md\nAGENTS.md\nBOOTSTRAP.md\n```\n\nEm đã update SOUL.md rồi.",
agentType: "predefined",
},
{
name: "predefined - plain text leak still triggers",
content: "Em load SOUL.md, IDENTITY.md, AGENTS.md vào context.",
agentType: "predefined",
want: declineMsg,
},
}
for _, tt := range tests {