SanitizePromptText strips invisible Unicode characters that could hide prompt-injection content from human reviewers, normalizes line endings, collapses excessive blank lines, and trims surrounding whitespace. The stripped codepoints are truly invisible and have no legitimate use in prompt text. An
(s string)
| 20 | // system prompts are not emoji art, and ZWJ is actively exploited in |
| 21 | // zero-width steganography schemes as a delimiter character. |
| 22 | func SanitizePromptText(s string) string { |
| 23 | // 1. Normalize line endings: \r\n → \n, lone \r → \n. |
| 24 | s = strings.ReplaceAll(s, "\r\n", "\n") |
| 25 | s = strings.ReplaceAll(s, "\r", "\n") |
| 26 | |
| 27 | // 2. Strip invisible characters rune-by-rune. |
| 28 | var b strings.Builder |
| 29 | b.Grow(len(s)) |
| 30 | for _, r := range s { |
| 31 | if !isVisible(r) { |
| 32 | continue |
| 33 | } |
| 34 | _, _ = b.WriteRune(r) |
| 35 | } |
| 36 | s = b.String() |
| 37 | |
| 38 | // 3. Collapse 3+ consecutive newlines down to 2 (one blank |
| 39 | // line between paragraphs). This runs after invisible-char |
| 40 | // stripping so that lines containing only stripped chars |
| 41 | // become empty and get collapsed. |
| 42 | s = collapseNewlines(s) |
| 43 | |
| 44 | // 4. Final trim. |
| 45 | return strings.TrimSpace(s) |
| 46 | } |
| 47 | |
| 48 | // isVisible reports whether r is a visible Unicode character that |
| 49 | // should be preserved in prompt text. Each invisible range is |