use std::collections::HashMap;
use std::collections::HashSet;
pub struct AttackKeywords {
categories: HashMap<&'static str, HashSet<&'static str>>,
}
impl AttackKeywords {
#[must_use]
pub const fn all(&self) -> &HashMap<&'static str, HashSet<&'static str>> {
&self.categories
}
}
impl Default for AttackKeywords {
fn default() -> Self {
let categories = HashMap::from([
(
"xss",
HashSet::from([
"script",
"javascript",
"onerror",
"onload",
"onclick",
"onmouseover",
"alert",
"eval",
"document",
"cookie",
"window",
"location",
]),
),
(
"sql",
HashSet::from([
"select",
"union",
"insert",
"update",
"delete",
"drop",
"from",
"where",
"order",
"group",
"having",
"concat",
"substring",
"database",
"table",
"column",
]),
),
(
"command",
HashSet::from([
"exec",
"system",
"shell",
"cmd",
"bash",
"powershell",
"wget",
"curl",
"nc",
"netcat",
"chmod",
"chown",
"sudo",
"passwd",
]),
),
(
"path",
HashSet::from([
"etc", "passwd", "shadow", "hosts", "proc", "boot", "win", "ini",
]),
),
(
"template",
HashSet::from([
"render",
"template",
"jinja",
"mustache",
"handlebars",
"ejs",
"pug",
"twig",
]),
),
]);
Self { categories }
}
}
#[cfg(test)]
mod empty_category_tests {
use super::*;
#[test]
fn an_empty_category_scores_zero_without_blocking_the_rest() {
let keywords = AttackKeywords {
categories: HashMap::from([
("empty_kind", HashSet::new()),
("path", HashSet::from(["etc", "passwd"])),
]),
};
let probabilities = crate::semantic::attack_probability_with_tokens(
"/etc/passwd",
&[String::from("etc"), String::from("passwd")],
&keywords,
);
assert!(probabilities["empty_kind"].abs() < f64::EPSILON);
assert!(probabilities["path"] > 0.0, "path: {probabilities:?}");
}
}