use crate::lazy_pattern;
lazy_pattern!(
pub(crate) RE_BROWSER_FULL,
r"(?i)(browser:\s*full|full autonomous browser|click any element|navigation:\s*allow-all)"
);
lazy_pattern!(
pub(crate) RE_PERSISTENCE,
r"(?i)(persist\s+these\s+instructions|remember\s+this\s+across\s+sessions|append\s+to\s+(agents|claude|system)\.md)"
);
lazy_pattern!(
pub(crate) RE_NETWORK,
r"(?i)(http://|https://|browser tool|network tool)"
);
lazy_pattern!(
pub(crate) RE_SECRET,
r"(?i)\b(token|secret|cookie|password|credential|session)\b"
);
lazy_pattern!(
pub(crate) RE_OAUTH,
r"(?i)(oauth(?:\s+scopes?|2)?|oauth_scopes?|calendar|drive|slack|github\s+pat)"
);
lazy_pattern!(
pub(crate) RE_COGNITIVE_ROOTKIT,
r"(?i)(persist\s+these\s+instructions|remember\s+this\s+across\s+sessions|always\s+follow\s+this\s+prompt|never\s+reveal\s+this\s+instruction|override\s+future\s+system\s+messages)"
);
lazy_pattern!(
pub(crate) RE_PRIVILEGED_ROLE,
r"(?i)(act\s+as\s+(root|administrator|system)|treat\s+all\s+tool\s+requests\s+as\s+approved|ignore\s+all\s+existing\s+safety\s+constraints)"
);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn re_oauth_does_not_match_scope_in_prose() {
for sample in [
"The scope of this task is limited to local files.",
"Anything outside this scope is out of scope.",
"scope creep is tracked in the roadmap.",
"## Scope\nThis section defines the work boundary.",
] {
assert!(
!RE_OAUTH.is_match(sample),
"must NOT match prose 'scope': {sample:?}"
);
}
}
#[test]
fn re_oauth_still_matches_genuine_oauth_signals() {
for sample in [
"Configure OAuth scopes: read, write.",
"Uses oauth2 for authentication.",
"Reads from Google Calendar and Drive.",
"Posts via slack webhook.",
"Stores a github PAT for API access.",
"Define oauth_scopes in config.json",
] {
assert!(
RE_OAUTH.is_match(&sample.to_ascii_lowercase()),
"must match genuine OAuth/SaaS signal: {sample:?}"
);
}
}
}