OXYGENHUB
# a549ddd5941f oxygenhub / crates / hub / tests / csp.rs
1.6 KiB · Rust · last changed No inline code in pages, so the CSP can be enforced (#227) 18 days ago source blame history raw
1
//! The pages carry no inline code (oxygenhub#227), so the
2
//! Content-Security-Policy's `script-src 'self'` can be enforced: no
3
//! `<script>` without `src` (JSON data blocks aside) and no `on…=` handler
4
//! attributes in any template. Scripts belong in assets/ (hub.js reads
5
//! `data-confirm`, `data-autosubmit`, `data-select`).
6
7
#[test]
8
fn templates_carry_no_inline_scripts_or_handlers() {
9
    let dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../templates");
10
    let handler = |s: &str| {
11
        s.match_indices(" on").any(|(i, _)| {
12
            let rest = &s[i + 3..];
13
            let name: String = rest.chars().take_while(|c| c.is_ascii_lowercase()).collect();
14
            !name.is_empty() && rest[name.len()..].starts_with("=\"")
15
        })
16
    };
17
    let mut found = Vec::new();
18
    for e in std::fs::read_dir(&dir).unwrap() {
19
        let path = e.unwrap().path();
20
        if path.extension().and_then(|x| x.to_str()) != Some("html") {
21
            continue;
22
        }
23
        let text = std::fs::read_to_string(&path).unwrap();
24
        for (n, line) in text.lines().enumerate() {
25
            let inline_script = line.match_indices("<script").any(|(i, _)| {
26
                let tag = &line[i..line[i..].find('>').map_or(line.len(), |e| i + e)];
27
                !tag.contains("src=") && !tag.contains("application/json")
28
            });
29
            if inline_script || handler(line) {
30
                found.push(format!("{}:{}: {}", path.file_name().unwrap().to_string_lossy(), n + 1, line.trim()));
31
            }
32
        }
33
    }
34
    assert!(found.is_empty(), "inline code the CSP would block:\n{}", found.join("\n"));
35
}