(file, content)
| 426 | } |
| 427 | |
| 428 | function checkPromptUnicode(file, content) { |
| 429 | let line = 1; |
| 430 | let column = 1; |
| 431 | |
| 432 | for (const char of content) { |
| 433 | const codePoint = char.codePointAt(0); |
| 434 | const classification = classifyPromptCodePoint(codePoint); |
| 435 | |
| 436 | if (classification) { |
| 437 | addFailure({ |
| 438 | ruleId: "prompt/no-hidden-or-control-unicode", |
| 439 | title: "Prompt files must not contain hidden Unicode controls", |
| 440 | file, |
| 441 | problem: `${file} contains disallowed ${classification} ${formatCodePoint(codePoint)} at ${line}:${column}. AI prompt files must not contain invisible Unicode, bidirectional overrides, or terminal control characters.`, |
| 442 | why: "Hidden Unicode and terminal controls can conceal prompt-injection text or make review output misleading.", |
| 443 | fix: "Remove the disallowed character and keep prompt text visible ASCII or ordinary visible Unicode only.", |
| 444 | }); |
| 445 | } |
| 446 | |
| 447 | if (char === "\n") { |
| 448 | line += 1; |
| 449 | column = 1; |
| 450 | } else if (char === "\r") { |
| 451 | column = 1; |
| 452 | } else { |
| 453 | column += 1; |
| 454 | } |
| 455 | } |
| 456 | } |
| 457 | |
| 458 | function classifyPromptCodePoint(codePoint) { |
| 459 | if (isBidirectionalTextControl(codePoint)) { |
no test coverage detected