Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,23 @@ jobs:
env:
JEKYLL_ENV: production

# Strip unused CSS from the built output so html-proofer and the deployed
# site see the same slimmed-down production CSS.
- name: Purge unused CSS
run: npm run purge-css

- name: Check internal links (html-proofer)
run: npm run test-links

# Accessibility audit (WCAG 2.1 AA, BITV-relevant) against the built site.
# Non-blocking for now: the existing Webflow-exported pages have known
# a11y errors, so this reports the debt on every PR without blocking
# merges. Remove continue-on-error once the baseline is clean to make it
# a hard gate.
- name: Check accessibility (pa11y-ci)
run: npm run test-a11y
continue-on-error: true

- name: Lint Ruby (RuboCop)
run: npm run rubocop

Expand Down
22 changes: 22 additions & 0 deletions .pa11yci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"defaults": {
"standard": "WCAG2AA",
"timeout": 30000,
"wait": 500,
"runners": ["axe", "htmlcs"],
"ignore": ["notice", "warning"],
"chromeLaunchConfig": {
"args": ["--no-sandbox", "--disable-dev-shm-usage"]
}
},
"urls": [
"http://localhost:8080/",
"http://localhost:8080/projekte/",
"http://localhost:8080/veroeffentlichungen/",
"http://localhost:8080/kontakt/",
"http://localhost:8080/impressum/",
"http://localhost:8080/datenschutz/",
"http://localhost:8080/offenerbrief-epa-2025/",
"http://localhost:8080/404/"
]
}
5 changes: 5 additions & 0 deletions .well-known/security.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Canonical location: https://www.inoeg.de/.well-known/security.txt
# This file follows RFC 9116 (https://www.rfc-editor.org/rfc/rfc9116).
Contact: mailto:kontakt@inoeg.de
Expires: 2027-01-01T00:00:00.000Z
Preferred-Languages: de, en
1 change: 1 addition & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ exclude:
include:
- _pages # static content
- _posts # for blog / news posts
- .well-known # security.txt (RFC 9116); dot-dirs are excluded by default
34 changes: 34 additions & 0 deletions _includes/head.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,38 @@
<meta charset="utf-8">

<!--
Security headers policy

GitHub Pages serves static files only and cannot set custom HTTP response
headers, so the Content-Security-Policy and Referrer-Policy below are
enforced via <meta> tags instead of real headers. This is a weaker
enforcement point than an HTTP header (a meta CSP cannot cover the response
itself, e.g. it does not apply to the page's own top-level navigation and is
ignored for some directives — see below) but it is the only mechanism
available on this host.

This policy relies on the site having zero JavaScript, no third-party
embeds, and only same-origin CSS/images (verified at time of writing: no
<script> tags, no external iframes, all assets under /assets/...).

style-src includes 'unsafe-inline' because several Webflow-exported pages
in _pages/ use inline style="..." attributes (e.g. _pages/projekte.html,
_pages/offenerbrief-epa-2025.html for background-color/text-align). A
stricter style-src without 'unsafe-inline' would break their layout, and a
CSP that breaks styling is worse than no CSP.

X-Content-Type-Options and X-Frame-Options are deliberately NOT emitted as
meta tags: both directives are only honored by browsers when sent as real
HTTP response headers and have no effect via <meta http-equiv>. Enforcing
them requires either GitHub Pages gaining header support or fronting the
site with something that can inject headers (e.g. Cloudflare Transform
Rules / a Worker).
-->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'">
<meta name="referrer" content="strict-origin-when-cross-origin">

<!-- title -->
<title>
{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}
Expand Down
Loading
Loading