use erroracle::{
body_has_waf_block_phrases, body_has_waf_markers, classify_response, HttpResponse,
ResponseDisposition,
};
pub const CAPTCHAFORGE_BLOCK_EXTRAS: &[&str] = &[
"sorry, you have been blocked",
"pardon our interruption",
"your request has been blocked",
"this request has been blocked",
"the owner of this website",
"request unsuccessful",
"you don't have permission",
"automated access",
"bot detected",
"suspicious activity",
"you have been rate limited",
"rate limit exceeded",
"permission denied",
"security policy",
"forbidden",
];
#[must_use]
pub fn http_response_indicates_block(status: u16, body: Option<&str>) -> bool {
if !(200..300).contains(&status) {
return true;
}
let Some(body) = body else {
return false;
};
let lower = body.to_lowercase();
if extras_indicate_block(&lower) {
return true;
}
if body_has_waf_block_phrases(&lower) {
return true;
}
if body_has_waf_markers(&lower) {
return matches!(
classify_response(&HttpResponse::new(403, body)).disposition,
ResponseDisposition::WafBlock | ResponseDisposition::RateLimited
);
}
false
}
#[must_use]
pub fn page_text_indicates_hard_block(title: &str, body_excerpt: &str) -> bool {
let lower = format!("{}\n{}", title.to_lowercase(), body_excerpt.to_lowercase());
extras_indicate_block(&lower) || body_has_waf_block_phrases(&lower)
}
fn extras_indicate_block(lower: &str) -> bool {
CAPTCHAFORGE_BLOCK_EXTRAS.iter().any(|p| lower.contains(p))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn http_block_delegates_to_erroracle_phrases() {
assert!(http_response_indicates_block(
200,
Some("Sorry, REQUEST BLOCKED by policy")
));
}
#[test]
fn http_block_uses_extras() {
assert!(http_response_indicates_block(
200,
Some("Pardon Our Interruption while we verify")
));
}
#[test]
fn http_block_clean_200_accepted() {
assert!(!http_response_indicates_block(200, Some("{\"ok\": true}")));
}
#[test]
fn page_text_uses_shared_phrases() {
assert!(page_text_indicates_hard_block(
"Access Denied",
"your request was rejected"
));
}
#[test]
fn benign_cloudflare_mention_not_hard_block_without_phrase() {
assert!(!page_text_indicates_hard_block(
"How Cloudflare works",
"Cloudflare is a CDN"
));
}
}