From b2a30ab49c996b4692f47567be9a27dd22a8ca52 Mon Sep 17 00:00:00 2001 From: Senih Bayankulu Date: Wed, 17 Jun 2026 19:07:34 +0300 Subject: [PATCH] feat(module10): add local security headers server --- experiments/module-10-security-demo/README.md | 19 +++++++ .../module-10-security-demo/index.html | 10 +--- experiments/module-10-security-demo/server.py | 49 +++++++++++++++++++ .../module-10-security-demo/styles.css | 41 ++++++++++++++++ 4 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 experiments/module-10-security-demo/server.py create mode 100644 experiments/module-10-security-demo/styles.css diff --git a/experiments/module-10-security-demo/README.md b/experiments/module-10-security-demo/README.md index 1035c20..9f9fcaf 100644 --- a/experiments/module-10-security-demo/README.md +++ b/experiments/module-10-security-demo/README.md @@ -16,6 +16,25 @@ Open: http://127.0.0.1:8090/ ``` +## Run With Security Headers + +For Module 10-E remediation validation, run the local security-header server: + +```powershell +python .\server.py --port 8090 +``` + +Expected response headers: + +```text +Content-Security-Policy +X-Frame-Options +X-Content-Type-Options +Referrer-Policy +Permissions-Policy +Strict-Transport-Security +``` + ## DevTools Panels Use Chrome DevTools: diff --git a/experiments/module-10-security-demo/index.html b/experiments/module-10-security-demo/index.html index 34c5ea2..9e667bf 100644 --- a/experiments/module-10-security-demo/index.html +++ b/experiments/module-10-security-demo/index.html @@ -5,15 +5,7 @@ Module 10 Security Inspection Demo - +
diff --git a/experiments/module-10-security-demo/server.py b/experiments/module-10-security-demo/server.py new file mode 100644 index 0000000..bcc88cf --- /dev/null +++ b/experiments/module-10-security-demo/server.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +import argparse +import os +from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer +from pathlib import Path + + +SECURITY_HEADERS = { + "Content-Security-Policy": ( + "default-src 'self'; " + "base-uri 'self'; " + "connect-src 'self'; " + "form-action 'self'; " + "frame-ancestors 'none'; " + "img-src 'self' data:; " + "object-src 'none'; " + "script-src 'self'; " + "style-src 'self'" + ), + "X-Frame-Options": "DENY", + "X-Content-Type-Options": "nosniff", + "Referrer-Policy": "no-referrer-when-downgrade", + "Permissions-Policy": "geolocation=(), microphone=(), camera=()", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains", +} + + +class SecurityHeadersHandler(SimpleHTTPRequestHandler): + def end_headers(self) -> None: + for header, value in SECURITY_HEADERS.items(): + self.send_header(header, value) + super().end_headers() + + +def main() -> None: + parser = argparse.ArgumentParser(description="Serve Module 10 demo locally.") + parser.add_argument("--host", default="127.0.0.1") + parser.add_argument("--port", type=int, default=8090) + args = parser.parse_args() + + os.chdir(Path(__file__).resolve().parent) + server = ThreadingHTTPServer((args.host, args.port), SecurityHeadersHandler) + print(f"Serving Module 10 demo at http://{args.host}:{args.port}/") + server.serve_forever() + + +if __name__ == "__main__": + main() diff --git a/experiments/module-10-security-demo/styles.css b/experiments/module-10-security-demo/styles.css new file mode 100644 index 0000000..3a8bbe4 --- /dev/null +++ b/experiments/module-10-security-demo/styles.css @@ -0,0 +1,41 @@ +body { + font-family: system-ui, sans-serif; + margin: 2rem; + line-height: 1.5; + max-width: 960px; +} + +header, +section { + margin-bottom: 1.5rem; +} + +.card { + border: 1px solid #ccc; + border-radius: 12px; + padding: 1rem; + margin: 0.75rem 0; +} + +code { + background: #f4f4f4; + padding: 0.1rem 0.3rem; + border-radius: 4px; +} + +button { + padding: 0.6rem 1rem; + border-radius: 8px; + border: 1px solid #555; + background: white; + cursor: pointer; +} + +button:focus-visible { + outline: 3px solid #000; + outline-offset: 3px; +} + +.status { + font-weight: 700; +}