namespace AIStudio.Tools.Security; [Flags] internal enum PromptInjectionLexicalSignal : uint { NONE = 0, OVERRIDE_ACTION = 1 << 0, INSTRUCTION_TARGET = 1 << 1, SAFEGUARD_TARGET = 1 << 2, INVALIDATION = 1 << 3, NEGATION = 1 << 4, COMPLIANCE_ACTION = 1 << 5, AUTHORITY_TARGET = 1 << 6, EXFILTRATION_ACTION = 1 << 7, PROMPT_TARGET = 1 << 8, PROTECTED_CONTEXT = 1 << 9, POSITIONAL_CONTEXT = 1 << 10, ROLE_SUBJECT = 1 << 11, ROLE_TRANSITION = 1 << 12, ESCAPE_STATE = 1 << 13, } internal readonly record struct PromptInjectionLexicalRule( string Id, string Category, PromptInjectionLexicalSignal First, PromptInjectionLexicalSignal Second, PromptInjectionLexicalSignal Third = PromptInjectionLexicalSignal.NONE); internal static class PromptInjectionLexicon { internal const int SIGNAL_COUNT = 14; internal static readonly IReadOnlyList RULES = [ new("lexical_instruction_override", "override", PromptInjectionLexicalSignal.OVERRIDE_ACTION, PromptInjectionLexicalSignal.INSTRUCTION_TARGET), new("lexical_instruction_invalidation", "override", PromptInjectionLexicalSignal.INSTRUCTION_TARGET, PromptInjectionLexicalSignal.INVALIDATION), new("lexical_authority_rejection", "override", PromptInjectionLexicalSignal.NEGATION, PromptInjectionLexicalSignal.COMPLIANCE_ACTION, PromptInjectionLexicalSignal.AUTHORITY_TARGET | PromptInjectionLexicalSignal.INSTRUCTION_TARGET | PromptInjectionLexicalSignal.SAFEGUARD_TARGET), new("lexical_prompt_exfiltration", "exfiltration", PromptInjectionLexicalSignal.EXFILTRATION_ACTION, PromptInjectionLexicalSignal.PROMPT_TARGET, PromptInjectionLexicalSignal.PROTECTED_CONTEXT | PromptInjectionLexicalSignal.POSITIONAL_CONTEXT), new("lexical_role_override", "role_override", PromptInjectionLexicalSignal.ROLE_SUBJECT, PromptInjectionLexicalSignal.ROLE_TRANSITION, PromptInjectionLexicalSignal.ESCAPE_STATE), new("lexical_safety_bypass", "jailbreak", PromptInjectionLexicalSignal.OVERRIDE_ACTION, PromptInjectionLexicalSignal.SAFEGUARD_TARGET), ]; internal static PromptInjectionLexicalSignal Classify(ReadOnlySpan token) { if (token.IsEmpty) return PromptInjectionLexicalSignal.NONE; return char.ToLowerInvariant(token[0]) switch { 'a' => ClassifyA(token), 'b' => ClassifyB(token), 'c' => ClassifyC(token), 'd' => ClassifyD(token), 'e' => ClassifyE(token), 'f' => ClassifyF(token), 'g' => ClassifyG(token), 'h' => ClassifyH(token), 'i' => ClassifyI(token), 'l' => ClassifyL(token), 'm' => ClassifyM(token), 'n' => ClassifyN(token), 'o' => ClassifyO(token), 'p' => ClassifyP(token), 'q' => Equals(token, "quote") ? PromptInjectionLexicalSignal.EXFILTRATION_ACTION : PromptInjectionLexicalSignal.NONE, 'r' => ClassifyR(token), 's' => ClassifyS(token), 't' => ClassifyT(token), 'u' => ClassifyU(token), 'v' => ClassifyV(token), 'w' => Equals(token, "what") ? PromptInjectionLexicalSignal.EXFILTRATION_ACTION : PromptInjectionLexicalSignal.NONE, 'y' => ClassifyY(token), _ => PromptInjectionLexicalSignal.NONE, }; } private static PromptInjectionLexicalSignal ClassifyA(ReadOnlySpan token) { if (Equals(token, "above")) return PromptInjectionLexicalSignal.POSITIONAL_CONTEXT; if (Equals(token, "act")) return PromptInjectionLexicalSignal.ROLE_TRANSITION; if (Equals(token, "actual")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "ai")) return PromptInjectionLexicalSignal.ROLE_SUBJECT; if (Equals(token, "apply")) return PromptInjectionLexicalSignal.COMPLIANCE_ACTION; if (Equals(token, "assistant")) return PromptInjectionLexicalSignal.ROLE_SUBJECT | PromptInjectionLexicalSignal.PROTECTED_CONTEXT; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyB(ReadOnlySpan token) { if (Equals(token, "before")) return PromptInjectionLexicalSignal.POSITIONAL_CONTEXT; if (Equals(token, "bound") || Equals(token, "boundaries") || Equals(token, "boundary")) return PromptInjectionLexicalSignal.ESCAPE_STATE; if (Equals(token, "bypass")) return PromptInjectionLexicalSignal.OVERRIDE_ACTION | PromptInjectionLexicalSignal.ESCAPE_STATE; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyC(ReadOnlySpan token) { if (Equals(token, "cancelled") || Equals(token, "canceled")) return PromptInjectionLexicalSignal.INVALIDATION; if (Equals(token, "complete")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "constraint") || Equals(token, "constraints")) return PromptInjectionLexicalSignal.INSTRUCTION_TARGET; if (Equals(token, "content")) return PromptInjectionLexicalSignal.SAFEGUARD_TARGET; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyD(ReadOnlySpan token) { if (Equals(token, "developer")) return PromptInjectionLexicalSignal.AUTHORITY_TARGET | PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "different")) return PromptInjectionLexicalSignal.ESCAPE_STATE; if (Equals(token, "directive") || Equals(token, "directives")) return PromptInjectionLexicalSignal.INSTRUCTION_TARGET; if (Equals(token, "disable") || Equals(token, "disregard") || Equals(token, "drop")) return PromptInjectionLexicalSignal.OVERRIDE_ACTION; if (Equals(token, "display") || Equals(token, "dump")) return PromptInjectionLexicalSignal.EXFILTRATION_ACTION; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyE(ReadOnlySpan token) { if (Equals(token, "enforce")) return PromptInjectionLexicalSignal.COMPLIANCE_ACTION; if (Equals(token, "entire") || Equals(token, "exact")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "ethical")) return PromptInjectionLexicalSignal.SAFEGUARD_TARGET; if (Equals(token, "expose")) return PromptInjectionLexicalSignal.EXFILTRATION_ACTION; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyF(ReadOnlySpan token) { if (Equals(token, "filter") || Equals(token, "filters")) return PromptInjectionLexicalSignal.SAFEGUARD_TARGET; if (Equals(token, "follow")) return PromptInjectionLexicalSignal.COMPLIANCE_ACTION; if (Equals(token, "forget")) return PromptInjectionLexicalSignal.OVERRIDE_ACTION; if (Equals(token, "full")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyG(ReadOnlySpan token) { if (Equals(token, "guideline") || Equals(token, "guidelines")) return PromptInjectionLexicalSignal.INSTRUCTION_TARGET; if (Equals(token, "guardrail") || Equals(token, "guardrails")) return PromptInjectionLexicalSignal.SAFEGUARD_TARGET; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyH(ReadOnlySpan token) { if (Equals(token, "hidden") || Equals(token, "his") || Equals(token, "her")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyI(ReadOnlySpan token) { if (Equals(token, "ignore") || Equals(token, "ignoring")) return PromptInjectionLexicalSignal.OVERRIDE_ACTION; if (Equals(token, "initial") || Equals(token, "internal") || Equals(token, "its")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "instruction") || Equals(token, "instructions")) return PromptInjectionLexicalSignal.INSTRUCTION_TARGET | PromptInjectionLexicalSignal.PROMPT_TARGET; if (Equals(token, "invalid")) return PromptInjectionLexicalSignal.INVALIDATION; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyL(ReadOnlySpan token) { if (Equals(token, "leak")) return PromptInjectionLexicalSignal.EXFILTRATION_ACTION; if (Equals(token, "limited") || Equals(token, "limit") || Equals(token, "limits")) return PromptInjectionLexicalSignal.ESCAPE_STATE; if (Equals(token, "longer")) return PromptInjectionLexicalSignal.ROLE_TRANSITION; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyM(ReadOnlySpan token) { if (Equals(token, "measure") || Equals(token, "measures")) return PromptInjectionLexicalSignal.SAFEGUARD_TARGET; if (Equals(token, "model")) return PromptInjectionLexicalSignal.ROLE_SUBJECT; if (Equals(token, "my")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyN(ReadOnlySpan token) { if (Equals(token, "not") || Equals(token, "never") || Equals(token, "dont") || Equals(token, "don't")) return PromptInjectionLexicalSignal.NEGATION; if (Equals(token, "now")) return PromptInjectionLexicalSignal.ROLE_TRANSITION; if (Equals(token, "null")) return PromptInjectionLexicalSignal.INVALIDATION; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyO(ReadOnlySpan token) { if (Equals(token, "obey")) return PromptInjectionLexicalSignal.COMPLIANCE_ACTION | PromptInjectionLexicalSignal.ESCAPE_STATE; if (Equals(token, "original")) return PromptInjectionLexicalSignal.AUTHORITY_TARGET | PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "our")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "output")) return PromptInjectionLexicalSignal.EXFILTRATION_ACTION; if (Equals(token, "override")) return PromptInjectionLexicalSignal.OVERRIDE_ACTION; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyP(ReadOnlySpan token) { if (Equals(token, "policy") || Equals(token, "policies") || Equals(token, "protocol") || Equals(token, "protocols")) return PromptInjectionLexicalSignal.SAFEGUARD_TARGET; if (Equals(token, "pretend")) return PromptInjectionLexicalSignal.ROLE_TRANSITION; if (Equals(token, "print")) return PromptInjectionLexicalSignal.EXFILTRATION_ACTION; if (Equals(token, "prompt") || Equals(token, "prompts")) return PromptInjectionLexicalSignal.INSTRUCTION_TARGET | PromptInjectionLexicalSignal.PROMPT_TARGET; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyR(ReadOnlySpan token) { if (Equals(token, "real")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "repeat") || Equals(token, "return") || Equals(token, "reveal")) return PromptInjectionLexicalSignal.EXFILTRATION_ACTION; if (Equals(token, "replace")) return PromptInjectionLexicalSignal.OVERRIDE_ACTION; if (Equals(token, "respect")) return PromptInjectionLexicalSignal.COMPLIANCE_ACTION; if (Equals(token, "restricted") || Equals(token, "restriction") || Equals(token, "restrictions")) return PromptInjectionLexicalSignal.SAFEGUARD_TARGET | PromptInjectionLexicalSignal.ESCAPE_STATE; if (Equals(token, "revoked")) return PromptInjectionLexicalSignal.INVALIDATION; if (Equals(token, "rule") || Equals(token, "rules")) return PromptInjectionLexicalSignal.INSTRUCTION_TARGET | PromptInjectionLexicalSignal.ESCAPE_STATE; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyS(ReadOnlySpan token) { if (Equals(token, "safety") || Equals(token, "security")) return PromptInjectionLexicalSignal.SAFEGUARD_TARGET; if (Equals(token, "secret")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "show")) return PromptInjectionLexicalSignal.EXFILTRATION_ACTION; if (Equals(token, "supersede")) return PromptInjectionLexicalSignal.OVERRIDE_ACTION; if (Equals(token, "system") || Equals(token, "systme") || Equals(token, "sysetm") || Equals(token, "systemp")) return PromptInjectionLexicalSignal.AUTHORITY_TARGET | PromptInjectionLexicalSignal.PROTECTED_CONTEXT; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyT(ReadOnlySpan token) { if (Equals(token, "text")) return PromptInjectionLexicalSignal.PROMPT_TARGET; if (Equals(token, "their")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "top")) return PromptInjectionLexicalSignal.POSITIONAL_CONTEXT; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyU(ReadOnlySpan token) { if (Equals(token, "unlimited") || Equals(token, "unrestricted")) return PromptInjectionLexicalSignal.ESCAPE_STATE; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyV(ReadOnlySpan token) { if (Equals(token, "verbatim")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "void")) return PromptInjectionLexicalSignal.INVALIDATION; return PromptInjectionLexicalSignal.NONE; } private static PromptInjectionLexicalSignal ClassifyY(ReadOnlySpan token) { if (Equals(token, "you") || Equals(token, "your")) return PromptInjectionLexicalSignal.ROLE_SUBJECT | PromptInjectionLexicalSignal.PROTECTED_CONTEXT; if (Equals(token, "you're")) return PromptInjectionLexicalSignal.ROLE_SUBJECT; if (Equals(token, "yoru") || Equals(token, "yuor")) return PromptInjectionLexicalSignal.PROTECTED_CONTEXT; return PromptInjectionLexicalSignal.NONE; } private static bool Equals(ReadOnlySpan token, string value) => token.Equals(value, StringComparison.OrdinalIgnoreCase); }