Add security headers, external CSS, HTML escaping
- Middleware sets CSP (default-src 'none'; style-src 'self'), HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy on every response - Inline <style> moved to /styles.css so CSP needs no unsafe-inline - /favicon.ico returns a 1x1 GIF (kills 404 noise) - Escape LLM jokes, article title, and URL before HTML rendering (XSS fix)
This commit is contained in:
+34
-32
@@ -1,40 +1,42 @@
|
||||
CSS = """
|
||||
:root { color-scheme: light dark; }
|
||||
body {
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
max-width: 720px; margin: 0 auto; padding: 2rem 1rem;
|
||||
background: #fdfcf8; color: #222;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #1a1a1e; color: #e8e6e1; }
|
||||
a { color: #8ab4f8; }
|
||||
.joke { background: #26262c; color: #eceae4; border-color: #3a3a42; }
|
||||
header h1 { color: #f0ede6; }
|
||||
}
|
||||
header h1 { font-size: 2rem; margin-bottom: .25rem; }
|
||||
.date { color: #777; margin-top: 0; }
|
||||
.stale {
|
||||
background: #fff3cd; color: #665100; padding: .5rem .75rem;
|
||||
border-radius: 6px; font-size: .9rem;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.stale { background: #4a3c0a; color: #ffd970; }
|
||||
}
|
||||
ul.jokes { list-style: none; padding: 0; }
|
||||
li.joke {
|
||||
background: #fff; color: #222; border: 1px solid #e2ddd2; border-radius: 10px;
|
||||
padding: 1rem 1.25rem; margin: .9rem 0; font-size: 1.15rem;
|
||||
line-height: 1.5; box-shadow: 0 1px 3px rgba(0,0,0,.06);
|
||||
}
|
||||
li.joke::before { content: "\\1F604 "; }
|
||||
footer { margin-top: 2rem; font-size: .9rem; color: #888; }
|
||||
"""
|
||||
|
||||
PAGE_TEMPLATE = """<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Wiki Jokes — {day}</title>
|
||||
<style>
|
||||
:root {{ color-scheme: light dark; }}
|
||||
body {{
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
max-width: 720px; margin: 0 auto; padding: 2rem 1rem;
|
||||
background: #fdfcf8; color: #222;
|
||||
}}
|
||||
@media (prefers-color-scheme: dark) {{
|
||||
body {{ background: #1a1a1e; color: #e8e6e1; }}
|
||||
a {{ color: #8ab4f8; }}
|
||||
.joke {{ background: #26262c; color: #eceae4; border-color: #3a3a42; }}
|
||||
header h1 {{ color: #f0ede6; }}
|
||||
}}
|
||||
header h1 {{ font-size: 2rem; margin-bottom: .25rem; }}
|
||||
.date {{ color: #777; margin-top: 0; }}
|
||||
.stale {{
|
||||
background: #fff3cd; color: #665100; padding: .5rem .75rem;
|
||||
border-radius: 6px; font-size: .9rem;
|
||||
}}
|
||||
@media (prefers-color-scheme: dark) {{
|
||||
.stale {{ background: #4a3c0a; color: #ffd970; }}
|
||||
}}
|
||||
ul.jokes {{ list-style: none; padding: 0; }}
|
||||
li.joke {{
|
||||
background: #fff; color: #222; border: 1px solid #e2ddd2; border-radius: 10px;
|
||||
padding: 1rem 1.25rem; margin: .9rem 0; font-size: 1.15rem;
|
||||
line-height: 1.5; box-shadow: 0 1px 3px rgba(0,0,0,.06);
|
||||
}}
|
||||
li.joke::before {{ content: "😄 "; }}
|
||||
footer {{ margin-top: 2rem; font-size: .9rem; color: #888; }}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
@@ -47,7 +49,7 @@ PAGE_TEMPLATE = """<!DOCTYPE html>
|
||||
</ul>
|
||||
<footer>
|
||||
Inspired by today's Wikipedia featured article:
|
||||
<a href="{article_url}" rel="noopener">{article_title}</a>
|
||||
<a href="{article_url}" rel="noopener noreferrer">{article_title}</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user