Security Audit (extern) — Live-Website buergerinitiative-ejun.de (16.09.2026) #18

Open
opened 2026-09-16 06:24:46 +02:00 by Simon · 1 comment
Owner

Security Audit — externe Sicht, Live-Website

Datum: 16.09.2026, ~04:00–04:25 MESZ
Methodik: Blackbox von außen (hermes-lxc, öffentliche IP 88.133.36.255), ausschließlich curl/openssl/dig — kein Port-Scanner, keine aktiven Exploits, kein Login. Alle Werte live gemessen.
Ziel: https://www.buergerinitiative-ejun.de (DynDNS simowncloud.dnshome.de → OPNsense 10.10.10.1 → HAProxy → nginx 10.20.10.10) + Apex-Domain + DNS.


P1 — Hoch (beheben, bevor Mitglieder die Seite nutzen)

1. User-Enumeration über /odata/verify

Öffentlicher Endpunkt unterscheidet existierende von nicht-existierenden E-Mails:

  • unbekannt: {"Valid":false,"Role":null,"Status":"not-found"} (HTTP 200)
  • bekannt (simon@berleb.net, falsches PW): {"Valid":false,"Role":null,"Status":"bad-password"} (HTTP 200)

Jeder kann die Mitgliederliste (inkl. Admin-Adresse) extern enumerieren. Rate-Limit (~2/s) bremst nur, verhindert nichts.
Fix: Einheitliche Antwort für beide Fälle (z. B. immer invalid-credentials, HTTP 401, gleiche Antwortzeit) — im OData-Backend (ejun-oapi) oder per Nginx-Abstraktion.

2. Apex-Domain zeigt noch auf die alte Zoho-Seite

buergerinitiative-ejun.de (naked) löst auf Cloudflare (104.21.63.34 / 172.67.169.111) → 301 → buergerinitiative-ejun.zohosites.eu (HTTP 200, alte Seite). Wer die Adresse eingibt, sieht nicht unsere Website. Zoho setzt dabei Cookies unter unserer Domain (zalb_…, csrfc mit SameSite=None;Secure) — drittanbieter-Cookies auf unserer Domain, DSGVO-relevant.
Fix: DNS (Andreas): naked Domain ebenfalls auf simowncloud.dnshome.de zeigen lassen + LE-Zertifikat mit SAN für naked + www ausstellen (aktuelles Zert hat nur www.buergerinitiative-ejun.de) + HAProxy-ACL deckt naked bereits ab (hdr_end(host) -i buergerinitiative-ejun.de).

3. Kein DMARC — Phishing-Schutz für @buergerinitiative-ejun.de fehlt

_dmarc.buergerinitiative-ejun.de liefert keine TXT. SPF existiert (v=spf1 include:zohomail.eu ip4:159.69.123.124 -all), MX → Zoho. Ohne DMARC kann jeder E-Mails im Namen unserer Domain fälschen (Phishing an Mitglieder/Bürger).
Fix: v=DMARC1; p=quarantine; rua=mailto:... als TXT auf _dmarc. (nach DNS-Umstellung ggf. p=reject).


P2 — Mittel

4. Google Fonts werden extern geladen (DSGVO)

index.html lädt fonts.googleapis.com/css2 + fonts.gstatic.com (Barlow, Space Grotesk) direkt vom Browser. Jeder Besucher-Request geht mit IP an Google (US) — ohne Consent-Grundlage problematisch, für eine Bürgerinitiative ein Vertrauens-Thema.
Fix: Fonts self-hosten (Dateien ins Repo, @font-face lokal, wie app.js/styles.css bereits lokal ausgeliefert).

index.html verlinkt auf https://www.buergerinitiative-ejun.de/Dokumente/…:

  • 2024_07_09 Windvorranggebiete Bürgermeisterschreiben.pdf → 404
  • 2025_03_12 Stümpfig- Gutachten Umfassung 2021.pdf → 404
  • 2025_06_06 Public Petition … Franken-Neuhofen.pdf → 404

(root und /dev/ getestet, beide 404; /Dokumente/ und /docs/ existieren nicht). Auch https://www.buergerinitiative-ejun.de/docs/ → 404.
Fix: PDFs nach Dokumente/ im Deploy legen (oder Pfade korrigieren) und alle Links in index.html live-prüfen.

http://www.buergerinitiative-ejun.de/ → Timeout (Exit 28). Bekannter Punkt (ACME läuft über TLS-ALPN-01 auf 443), aber: jeder http://-Link (z. B. in E-Mails/Druck) bricht ab. HSTS schützt nur Browser mit bereits bekannter HSTS-Angabe.
Fix (eine von beiden): Port 80 öffnen mit Redirect 301 → https (dann auch HTTP-01-ACME simpler) — oder dokumentieren, dass nur https://-Links verwendet werden dürfen.

7. Fehlende Security-Header

Vorhanden: Strict-Transport-Security: max-age=15768000; includeSubDomains (auch auf 404 — gut).
Fehlt: Content-Security-Policy, X-Frame-Options/frame-ancestors (Clickjacking-Schutz), Referrer-Policy, X-Content-Type-Options: nosniff.
Fix: zentral in nginx (add_header auf server-Block), CSP default-src 'self'; font-src 'self' (nach Self-Hosting der Fonts) + img-src 'self' data:.

8. server: nginx/1.24.0 (Ubuntu) — Versions-Disclosure

Server-Header und alle nginx-Fehlerseiten (404/401) verraten exakte Version + Distro.
Fix: server_tokens off; + eigene Fehlerseiten (error_page 404 /404.html im EjUn-Design).


P3 — Niedrig / Hygiene

9. adminapi sendet doppelte WWW-Authenticate-Header

GET /adminapi/ und /admin/einwaende.html liefern zwei Header gleichzeitig: Basic realm="EjUn Dev Preview" + Basic realm="EjUn Admin". nginx-Config-Doppelung; Clients verhalten sich unbestimmt, Browser-Realm-Cache durcheinander.
Fix: Exakten auth_basic/@admin401-Block prüfen — pro Location genau ein Realm.

10. /api/health öffentlich + /api/ → HTTP 500

GET /api/health → 200 {"status":"ok","api":true} (Backend-Existenz-Leak, ohne Auth). GET /api/ → 500 mit leerem Body (HEAD liefert 405 + allow: DELETE, GET, PUT — inkonsistent). POST/PUT /api/health → 400, DELETE → 405.
Fix: /api/health intern-only oder mit Auth; /api/-Root sauber auf 404/405 statt 500.

11. /dev/ ohne Passwort + robots.txt dokumentiert falschen Schutz

/dev/ liefert exakt denselben Content wie / (21225 B, gleicher ETAG — Dev-Preview = Produktions-Stand, kein sensibler Inhalt). X-Robots-Tag: noindex, nofollow + Cache-Control: no-store sind gesetzt. Aber: die robots.txt behauptet, „Der eigentliche Schutz ist die nginx-Schicht (Basic Auth + X-Robots-Tag …)“ — Basic Auth existiert auf /dev/ aktuell nicht.
Fix: Entweder Basic Auth auf /dev/ wieder aktivieren oder robots.txt-Kommentar korrigieren (Doku = Realität).

12. Kein PTR-Record für die WAN-IP

dig -x 88.133.36.255 → leer. Für ausgehende E-Mails (falls die Domain später selbst mailt) und für Mail-Server-Spam-Scores relevant. DynDNS-Provider — ggf. anfragbar.


Positiv — geprüft und OK

  • TLS: Nur TLS 1.2/1.3 (1.0/1.1 → alert protocol version), keine schwachen Cipher (RC4/3DES/EXPORT/SHA1-CBC alle rejected), AEAD-only (AES-GCM), LE-Zert gültig bis 14.12.2026.
  • HSTS: max-age=15768000; includeSubDomains auf allen Antworten inkl. 404.
  • Zensiermodus intakt: Anonyme Report-Seite (/dev/uvp-hayforst-report.html, 6388 B) enthält nur 171 Wörter + CSS-only Skeleton-Balken + Veil-Box „Nur für registrierte Personen“. Kein versteckter Volltext (kein data-full, keine hidden-Blöcke, keine langen aria-labels).
  • Rate-Limits greifen extern: /odata/register 4×200 dann 503 (~5/min), /odata/verify 6×200 dann 503 (~2/s), /odata/submitEinwendung 4×400 dann 503.
  • Kein OData-Metadata-Leak: /odata/$metadata → 404; /odata/Members → 404; nur register/verify/submitEinwendung öffentlich erreichbar.
  • Keine Datei-Exposition: /.git/config, /members.db, /.env, /server-status, /backup/ → alle 404/403.
  • Kein Passwort-Leak bei Registrierung: POST /odata/register (frische E-Mail) → 200 {"Ok":true,"Status":"created","Email":…} — das generierte Passwort erscheint nicht in der öffentlichen Antwort.
  • Kein X-Auth-Email-Leak in Headers der Report-Seiten.
  • CORS: Keine Access-Control-Allow-Origin-Header (auch nicht auf Origin: https://evil.example) — keine CORS-Fehlkonfiguration.
  • Robustheit: 10 KB User-Agent → sauberes 400; Transfer-Encoding-Anomalie → 500 (kein Smuggling, nginx lehnt ab); SNI-Fingerprinting: fremde Hosts bekommen Fallback-Zert ai.berleb.net (keine EjUn-Infos).
  • CORS/Origin, HTTP/2 + HTTP/1.1: beide sauber.
  • Nur ein offener Port an der WAN-IP: 443 (geprüft: 20,21,22,25,53,80,110,143,443,465,587,993,995,2083,3000,3001,3389,4443,5000,5432,6379,8000,8080,8081,8082,8085,8443,8888,9000,9443,10443,20000,32768 → nur 443 offen).

⚠️ Audit-Nebenwirkungen (Cleanup nötig!)

Während des Rate-Limit-Tests wurden 5 Test-Accounts im Live-Backend angelegt (alle Unverifiziert/Active, keine echten Daten):

  • sec-audit-20260916@example.org (Register-Test, created)
  • rl-test-1@example.org … rl-test-4@example.org (Rate-Limit-Test; Existenz via verify → bad-password bestätigt)

Action: Über das Admin-Panel (/admin/members.html) per Soft-Delete (Status: Deleted) entfernen. Die @example.org-Adressen sind eindeutig als Test erkennbar.


Empfohlene Reihenfolge

  1. #1 User-Enumeration (Backend-Änderung ejun-oapi)
  2. #2 Apex-Domain auf DynDNS + LE-Zert mit naked+www (abhängig von Andreas, DNS)
  3. #3 DMARC-Record
  4. #4 Fonts self-hosten
  5. #5 PDF-Links reparieren
  6. #6–8 Port 80 / Security-Header / server_tokens
  7. #9–12 Hygiene + Test-Account-Cleanup

Alle Befunde extern verifiziert (curl/openssl/dig, 16.09.2026). Kein interner Zugriff auf VM/Firewall für dieses Audit verwendet — interne Konfig-Details (HAProxy-ACLs, Zert-SANs) stammen aus früheren Live-Messungen (15.09.2026).

# Security Audit — externe Sicht, Live-Website **Datum:** 16.09.2026, ~04:00–04:25 MESZ **Methodik:** Blackbox von außen (hermes-lxc, öffentliche IP `88.133.36.255`), ausschließlich `curl`/`openssl`/`dig` — kein Port-Scanner, keine aktiven Exploits, kein Login. Alle Werte live gemessen. **Ziel:** `https://www.buergerinitiative-ejun.de` (DynDNS `simowncloud.dnshome.de` → OPNsense 10.10.10.1 → HAProxy → nginx 10.20.10.10) + Apex-Domain + DNS. --- ## P1 — Hoch (beheben, bevor Mitglieder die Seite nutzen) ### 1. User-Enumeration über `/odata/verify` Öffentlicher Endpunkt unterscheidet existierende von nicht-existierenden E-Mails: - unbekannt: `{"Valid":false,"Role":null,"Status":"not-found"}` (HTTP 200) - bekannt (simon@berleb.net, falsches PW): `{"Valid":false,"Role":null,"Status":"bad-password"}` (HTTP 200) Jeder kann die Mitgliederliste (inkl. Admin-Adresse) extern enumerieren. Rate-Limit (~2/s) bremst nur, verhindert nichts. **Fix:** Einheitliche Antwort für beide Fälle (z. B. immer `invalid-credentials`, HTTP 401, gleiche Antwortzeit) — im OData-Backend (`ejun-oapi`) oder per Nginx-Abstraktion. ### 2. Apex-Domain zeigt noch auf die alte Zoho-Seite `buergerinitiative-ejun.de` (naked) löst auf Cloudflare (104.21.63.34 / 172.67.169.111) → 301 → `buergerinitiative-ejun.zohosites.eu` (HTTP 200, alte Seite). Wer die Adresse eingibt, sieht nicht unsere Website. Zoho setzt dabei Cookies unter unserer Domain (`zalb_…`, `csrfc` mit `SameSite=None;Secure`) — drittanbieter-Cookies auf unserer Domain, DSGVO-relevant. **Fix:** DNS (Andreas): naked Domain ebenfalls auf `simowncloud.dnshome.de` zeigen lassen + LE-Zertifikat mit SAN für **naked + www** ausstellen (aktuelles Zert hat nur `www.buergerinitiative-ejun.de`) + HAProxy-ACL deckt naked bereits ab (`hdr_end(host) -i buergerinitiative-ejun.de`). ### 3. Kein DMARC — Phishing-Schutz für @buergerinitiative-ejun.de fehlt `_dmarc.buergerinitiative-ejun.de` liefert **keine** TXT. SPF existiert (`v=spf1 include:zohomail.eu ip4:159.69.123.124 -all`), MX → Zoho. Ohne DMARC kann jeder E-Mails im Namen unserer Domain fälschen (Phishing an Mitglieder/Bürger). **Fix:** `v=DMARC1; p=quarantine; rua=mailto:...` als TXT auf `_dmarc.` (nach DNS-Umstellung ggf. `p=reject`). --- ## P2 — Mittel ### 4. Google Fonts werden extern geladen (DSGVO) `index.html` lädt `fonts.googleapis.com/css2` + `fonts.gstatic.com` (Barlow, Space Grotesk) direkt vom Browser. Jeder Besucher-Request geht mit IP an Google (US) — ohne Consent-Grundlage problematisch, für eine Bürgerinitiative ein Vertrauens-Thema. **Fix:** Fonts self-hosten (Dateien ins Repo, `@font-face` lokal, wie `app.js`/`styles.css` bereits lokal ausgeliefert). ### 5. Drei tote PDF-Links auf der öffentlichen Startseite `index.html` verlinkt auf `https://www.buergerinitiative-ejun.de/Dokumente/…`: - `2024_07_09 Windvorranggebiete Bürgermeisterschreiben.pdf` → **404** - `2025_03_12 Stümpfig- Gutachten Umfassung 2021.pdf` → **404** - `2025_06_06 Public Petition … Franken-Neuhofen.pdf` → **404** (root und `/dev/` getestet, beide 404; `/Dokumente/` und `/docs/` existieren nicht). Auch `https://www.buergerinitiative-ejun.de/docs/` → 404. **Fix:** PDFs nach `Dokumente/` im Deploy legen (oder Pfade korrigieren) und alle Links in `index.html` live-prüfen. ### 6. Port 80 am WAN geschlossen — reine `http://`-Links hängen `http://www.buergerinitiative-ejun.de/` → Timeout (Exit 28). Bekannter Punkt (ACME läuft über TLS-ALPN-01 auf 443), aber: jeder `http://`-Link (z. B. in E-Mails/Druck) bricht ab. HSTS schützt nur Browser mit bereits bekannter HSTS-Angabe. **Fix (eine von beiden):** Port 80 öffnen mit Redirect `301 → https` (dann auch HTTP-01-ACME simpler) — oder dokumentieren, dass nur `https://`-Links verwendet werden dürfen. ### 7. Fehlende Security-Header Vorhanden: `Strict-Transport-Security: max-age=15768000; includeSubDomains` (auch auf 404 — gut). **Fehlt:** `Content-Security-Policy`, `X-Frame-Options`/`frame-ancestors` (Clickjacking-Schutz), `Referrer-Policy`, `X-Content-Type-Options: nosniff`. **Fix:** zentral in nginx (`add_header` auf server-Block), CSP `default-src 'self'; font-src 'self'` (nach Self-Hosting der Fonts) + `img-src 'self' data:`. ### 8. `server: nginx/1.24.0 (Ubuntu)` — Versions-Disclosure `Server`-Header und alle nginx-Fehlerseiten (404/401) verraten exakte Version + Distro. **Fix:** `server_tokens off;` + eigene Fehlerseiten (`error_page 404 /404.html` im EjUn-Design). --- ## P3 — Niedrig / Hygiene ### 9. `adminapi` sendet doppelte `WWW-Authenticate`-Header `GET /adminapi/` und `/admin/einwaende.html` liefern **zwei** Header gleichzeitig: `Basic realm="EjUn Dev Preview"` + `Basic realm="EjUn Admin"`. nginx-Config-Doppelung; Clients verhalten sich unbestimmt, Browser-Realm-Cache durcheinander. **Fix:** Exakten `auth_basic`/`@admin401`-Block prüfen — pro Location genau ein Realm. ### 10. `/api/health` öffentlich + `/api/` → HTTP 500 `GET /api/health` → `200 {"status":"ok","api":true}` (Backend-Existenz-Leak, ohne Auth). `GET /api/` → **500** mit leerem Body (HEAD liefert `405` + `allow: DELETE, GET, PUT` — inkonsistent). `POST/PUT /api/health` → 400, `DELETE` → 405. **Fix:** `/api/health` intern-only oder mit Auth; `/api/`-Root sauber auf 404/405 statt 500. ### 11. `/dev/` ohne Passwort + robots.txt dokumentiert falschen Schutz `/dev/` liefert exakt denselben Content wie `/` (21225 B, gleicher ETAG — Dev-Preview = Produktions-Stand, kein sensibler Inhalt). `X-Robots-Tag: noindex, nofollow` + `Cache-Control: no-store` sind gesetzt. **Aber:** die `robots.txt` behauptet, „Der eigentliche Schutz ist die nginx-Schicht (Basic Auth + X-Robots-Tag …)“ — Basic Auth existiert auf `/dev/` aktuell **nicht**. **Fix:** Entweder Basic Auth auf `/dev/` wieder aktivieren oder robots.txt-Kommentar korrigieren (Doku = Realität). ### 12. Kein PTR-Record für die WAN-IP `dig -x 88.133.36.255` → leer. Für ausgehende E-Mails (falls die Domain später selbst mailt) und für Mail-Server-Spam-Scores relevant. DynDNS-Provider — ggf. anfragbar. --- ## Positiv — geprüft und OK - **TLS:** Nur TLS 1.2/1.3 (1.0/1.1 → `alert protocol version`), keine schwachen Cipher (RC4/3DES/EXPORT/SHA1-CBC alle rejected), AEAD-only (AES-GCM), LE-Zert gültig bis 14.12.2026. - **HSTS:** `max-age=15768000; includeSubDomains` auf allen Antworten inkl. 404. - **Zensiermodus intakt:** Anonyme Report-Seite (`/dev/uvp-hayforst-report.html`, 6388 B) enthält nur 171 Wörter + CSS-only Skeleton-Balken + Veil-Box „Nur für registrierte Personen“. **Kein** versteckter Volltext (kein `data-full`, keine `hidden`-Blöcke, keine langen `aria-label`s). - **Rate-Limits greifen extern:** `/odata/register` 4×200 dann 503 (~5/min), `/odata/verify` 6×200 dann 503 (~2/s), `/odata/submitEinwendung` 4×400 dann 503. - **Kein OData-Metadata-Leak:** `/odata/$metadata` → 404; `/odata/Members` → 404; nur `register`/`verify`/`submitEinwendung` öffentlich erreichbar. - **Keine Datei-Exposition:** `/.git/config`, `/members.db`, `/.env`, `/server-status`, `/backup/` → alle 404/403. - **Kein Passwort-Leak bei Registrierung:** `POST /odata/register` (frische E-Mail) → `200 {"Ok":true,"Status":"created","Email":…}` — das generierte Passwort erscheint **nicht** in der öffentlichen Antwort. - **Kein X-Auth-Email-Leak** in Headers der Report-Seiten. - **CORS:** Keine `Access-Control-Allow-Origin`-Header (auch nicht auf `Origin: https://evil.example`) — keine CORS-Fehlkonfiguration. - **Robustheit:** 10 KB User-Agent → sauberes 400; `Transfer-Encoding`-Anomalie → 500 (kein Smuggling, nginx lehnt ab); SNI-Fingerprinting: fremde Hosts bekommen Fallback-Zert `ai.berleb.net` (keine EjUn-Infos). - **CORS/Origin, HTTP/2 + HTTP/1.1:** beide sauber. - **Nur ein offener Port** an der WAN-IP: 443 (geprüft: 20,21,22,25,53,80,110,143,443,465,587,993,995,2083,3000,3001,3389,4443,5000,5432,6379,8000,8080,8081,8082,8085,8443,8888,9000,9443,10443,20000,32768 → nur 443 offen). --- ## ⚠️ Audit-Nebenwirkungen (Cleanup nötig!) Während des Rate-Limit-Tests wurden **5 Test-Accounts** im Live-Backend angelegt (alle `Unverifiziert/Active`, keine echten Daten): - `sec-audit-20260916@example.org` (Register-Test, `created`) - `rl-test-1@example.org` … `rl-test-4@example.org` (Rate-Limit-Test; Existenz via `verify` → `bad-password` bestätigt) **Action:** Über das Admin-Panel (`/admin/members.html`) per Soft-Delete (`Status: Deleted`) entfernen. Die `@example.org`-Adressen sind eindeutig als Test erkennbar. --- ## Empfohlene Reihenfolge 1. **#1** User-Enumeration (Backend-Änderung `ejun-oapi`) 2. **#2** Apex-Domain auf DynDNS + LE-Zert mit naked+www (abhängig von Andreas, DNS) 3. **#3** DMARC-Record 4. **#4** Fonts self-hosten 5. **#5** PDF-Links reparieren 6. **#6–8** Port 80 / Security-Header / server_tokens 7. **#9–12** Hygiene + Test-Account-Cleanup *Alle Befunde extern verifiziert (curl/openssl/dig, 16.09.2026). Kein interner Zugriff auf VM/Firewall für dieses Audit verwendet — interne Konfig-Details (HAProxy-ACLs, Zert-SANs) stammen aus früheren Live-Messungen (15.09.2026).*
Author
Owner

Vollständiger Crawl aller öffentlichen Seiten (index.html + alle 9 verlinkten HTML-Seiten) und aller url:/sourceUrl:-Felder in news.js. 13 tote URLs (einzeln) gefunden, verteilt über 16 Zeilen/Plätze. Alle Dokumente existieren bereits im Repo unter sources/ejun/ (neue Namen) und sind live erreichbar — es müssen nur die Links getauscht werden. Alle 12 Ersatz-Ziele heute erneut live geprüft, alle 200.

Korrektur 09:50: drei Filennamen enthalten planungsverband, in der ersten Fassung stand oben fälschlich planverterband. Die Tabelle unten ist korrekt.

A) index.html — öffentlich klickbar (Sektion Quellen & Unterlagen)

  • A1: /docs/ (Gesamtes Dokumenten- und Neuigkeiten-Archiv) — 404
  • A2: /Dokumente/2024_07_09 Windvorranggebiete Bürgermeisterschreiben.pdf — 404
  • A3: /Dokumente/2025_03_12 Stümpfig-Gutachten Umfassung 2021.pdf — 404
  • A4: /Dokumente/2025_06_06 Public Petition Windkraft Umzingelung Franken-Neuhofen.pdf — 404

B) news.js — Feld sourceUrl (Metadaten, werden von app.js NICHT gerendert, nur url: ist klickbar. Trotzdem tote URLs im ausgelieferten JS)

  • B1: 2025_10_06 Stellungnahme EjUn gegen Planungsverband Donau-Wald.pdf (Zeile 103)
  • B2: 2025_12_11 Petition-Antwort Ergebnis der Regierung.pdf (Zeile 89)
  • B3: /Dokumente/2024_12 Antwort Laumer- Regionaler Planungsverband.pdf (Zeile 164)
  • B4: /Dokumente/2025_03 Unwirtschaftlichkeit und umzingelnde Wirkung von WKA aus 2013.pdf.pdf (Zeile 157)
  • B5: /Dokumente/2025_03_07 Allgemeine Laber Zeitung- Windkraft Eldorado wider Willen.pdf (Zeile 150)
  • B6: /Dokumente/2025_05 Entlastung Franken-Neuhofen durch optimierte Planung Windvorrangflächen.pdf (Zeile 136)
  • B7: /Dokumente/2025_05_26 Stellungnahme Planungsverband Donau-Wald und Landrat Laumer.pdf (Zeile 129)
  • B8: /Dokumente/2025_06_06 Public Petition Franken-Neuhofen.pdf, dupliziert A4 (Zeile 122)
  • B9: /Dokumente/2025_03_12 Stümpfig-Gutachten Umfassung 2021.pdf, dupliziert A3 (Zeile 143)
  • B10: /Dokumente/2024_07_09 Windvorranggebiete Bürgermeisterschreiben.pdf, dupliziert A2 (Zeile 171)
  • B11: /docs/post/treffen-vom-23.06.2024 (Zeile 178)
  • B12: /docs/post/unterlagen-neuigkeiten-vom-01.02.2026 (Zeilen 82 und 96)

Austausch-Mapping (alle Ziele live geprüft 16.09., alle 200, exakte Repo-Dateinamen unter sources/ejun/)

  • A2 und B10 (Windvorranggebiete) → 2024-07-09_windvorranggebiete-buergermeisterschreiben.pdf (5.2 MB)
  • A3 und B9 (Stümpfig) → 2025-03-12_stuempfig-gutachten-umfassung-2021.pdf (3.3 MB)
  • A4 und B8 (Public Petition) → 2025-06-06_public-petition-windkraft-umzingelung-franken-neuhofen.pdf (1.5 MB)
  • B1 (Stellungnahme EjUn 10.10.) → 2025-10-06_stellungnahme-ejun-gegen-planungsverband-donau-wald.pdf
  • B2 (Petition-Antwort) → 2025-12-11_petition-antwort-ergebnis-der-regierung.pdf
  • B3 (Antwort Laumer 12.2024) → 2024-12-16_antwort-laumer-regionaler-planungsverband.pdf
  • B4 (Unwirtschaftlichkeit 2013) → 2025-03_unwirtschaftlichkeit-und-umzingelnde-wirkung-von-wka-aus-2013.pdf
  • B5 (Laber Zeitung 07.03.) → 2025-03-07_allgemeine-laber-zeitung-windkraft-eldorado-wider-willen.pdf
  • B6 (Entlastung FN 05.2025) → 2025-05-11_entlastung-franken-neuhofen-durch-optimierte-planung-windvorrangflaechen.pdf
  • B7 (Stellungnahme 26.05.) → 2025-05-26_stellungnahme-planungsverband-donau-wald-und-landrat-laumer.pdf
  • B11 (Treffen 23.06.2024) → 2024-06-23_treffen-vom-23-06-2024.html
  • B12 (Unterlagen 01.02.2026) → 2026-02-01_unterlagen-neuigkeiten.html
  • A1 (/docs/ Archiv) → kein 1:1-Ersatz vorhanden, die neue Site hat keine öffentliche Archiv-Seite. Entscheidung: eigene Dokumenten-Index-Seite anlegen, Link auf die News-Sektion zeigen lassen, oder Link entfernen.

Randnotizen

  • Externer Link uvp-verbund.de/trefferanzeige?docuuid=… (news.js, klickbar) liefert 429 — vermutlich WAF/Rate-Limit gegen Nicht-Browser-Clients; im echten Browser vor Entfernen prüfen.
  • sources/2026-08-10_stellungnahme-ii-reduzierungsvorschlaege-ii.pdf → 302 → Login (bewusst geschützt, kein toter Link).
  • Alle übrigen lokalen Assets (25 abholzungen-Thumbs, 17 Visuals, 3 Windpark-PNGs, 3 Source-PDFs, 2026er sources) → 200.
  • /sources/ejun/ als Verzeichnis → 403 (kein Listing — korrekt so).

Umsetzung

index.html (4 Pfade in Sektion Quellen & Unterlagen) + news.js 12× sourceUrl (Zeilen 82, 89, 96, 103, 122, 129, 136, 143, 150, 157, 164, 171, 178) auf sources/ejun/… umsetzen; /docs/-Archiv-Link (A1) nach Entscheidung ersetzen. Danach: Dev-Deploy + Live-Prüfung aller getauschten Links.

## Tote Links — Vollliste + Austausch-Mapping (live verifiziert 16.09.2026, 09:50 korrigiert) Vollständiger Crawl aller öffentlichen Seiten (index.html + alle 9 verlinkten HTML-Seiten) und aller url:/sourceUrl:-Felder in news.js. 13 tote URLs (einzeln) gefunden, verteilt über 16 Zeilen/Plätze. Alle Dokumente existieren bereits im Repo unter sources/ejun/ (neue Namen) und sind live erreichbar — es müssen nur die Links getauscht werden. Alle 12 Ersatz-Ziele heute erneut live geprüft, alle 200. Korrektur 09:50: drei Filennamen enthalten planungsverband, in der ersten Fassung stand oben fälschlich planverterband. Die Tabelle unten ist korrekt. ### A) index.html — öffentlich klickbar (Sektion Quellen & Unterlagen) - A1: /docs/ (Gesamtes Dokumenten- und Neuigkeiten-Archiv) — 404 - A2: /Dokumente/2024_07_09 Windvorranggebiete Bürgermeisterschreiben.pdf — 404 - A3: /Dokumente/2025_03_12 Stümpfig-Gutachten Umfassung 2021.pdf — 404 - A4: /Dokumente/2025_06_06 Public Petition Windkraft Umzingelung Franken-Neuhofen.pdf — 404 ### B) news.js — Feld sourceUrl (Metadaten, werden von app.js NICHT gerendert, nur url: ist klickbar. Trotzdem tote URLs im ausgelieferten JS) - B1: 2025_10_06 Stellungnahme EjUn gegen Planungsverband Donau-Wald.pdf (Zeile 103) - B2: 2025_12_11 Petition-Antwort Ergebnis der Regierung.pdf (Zeile 89) - B3: /Dokumente/2024_12 Antwort Laumer- Regionaler Planungsverband.pdf (Zeile 164) - B4: /Dokumente/2025_03 Unwirtschaftlichkeit und umzingelnde Wirkung von WKA aus 2013.pdf.pdf (Zeile 157) - B5: /Dokumente/2025_03_07 Allgemeine Laber Zeitung- Windkraft Eldorado wider Willen.pdf (Zeile 150) - B6: /Dokumente/2025_05 Entlastung Franken-Neuhofen durch optimierte Planung Windvorrangflächen.pdf (Zeile 136) - B7: /Dokumente/2025_05_26 Stellungnahme Planungsverband Donau-Wald und Landrat Laumer.pdf (Zeile 129) - B8: /Dokumente/2025_06_06 Public Petition Franken-Neuhofen.pdf, dupliziert A4 (Zeile 122) - B9: /Dokumente/2025_03_12 Stümpfig-Gutachten Umfassung 2021.pdf, dupliziert A3 (Zeile 143) - B10: /Dokumente/2024_07_09 Windvorranggebiete Bürgermeisterschreiben.pdf, dupliziert A2 (Zeile 171) - B11: /docs/post/treffen-vom-23.06.2024 (Zeile 178) - B12: /docs/post/unterlagen-neuigkeiten-vom-01.02.2026 (Zeilen 82 und 96) ### Austausch-Mapping (alle Ziele live geprüft 16.09., alle 200, exakte Repo-Dateinamen unter sources/ejun/) - A2 und B10 (Windvorranggebiete) → 2024-07-09_windvorranggebiete-buergermeisterschreiben.pdf (5.2 MB) - A3 und B9 (Stümpfig) → 2025-03-12_stuempfig-gutachten-umfassung-2021.pdf (3.3 MB) - A4 und B8 (Public Petition) → 2025-06-06_public-petition-windkraft-umzingelung-franken-neuhofen.pdf (1.5 MB) - B1 (Stellungnahme EjUn 10.10.) → 2025-10-06_stellungnahme-ejun-gegen-planungsverband-donau-wald.pdf - B2 (Petition-Antwort) → 2025-12-11_petition-antwort-ergebnis-der-regierung.pdf - B3 (Antwort Laumer 12.2024) → 2024-12-16_antwort-laumer-regionaler-planungsverband.pdf - B4 (Unwirtschaftlichkeit 2013) → 2025-03_unwirtschaftlichkeit-und-umzingelnde-wirkung-von-wka-aus-2013.pdf - B5 (Laber Zeitung 07.03.) → 2025-03-07_allgemeine-laber-zeitung-windkraft-eldorado-wider-willen.pdf - B6 (Entlastung FN 05.2025) → 2025-05-11_entlastung-franken-neuhofen-durch-optimierte-planung-windvorrangflaechen.pdf - B7 (Stellungnahme 26.05.) → 2025-05-26_stellungnahme-planungsverband-donau-wald-und-landrat-laumer.pdf - B11 (Treffen 23.06.2024) → 2024-06-23_treffen-vom-23-06-2024.html - B12 (Unterlagen 01.02.2026) → 2026-02-01_unterlagen-neuigkeiten.html - A1 (/docs/ Archiv) → kein 1:1-Ersatz vorhanden, die neue Site hat keine öffentliche Archiv-Seite. Entscheidung: eigene Dokumenten-Index-Seite anlegen, Link auf die News-Sektion zeigen lassen, oder Link entfernen. ### Randnotizen - Externer Link uvp-verbund.de/trefferanzeige?docuuid=… (news.js, klickbar) liefert 429 — vermutlich WAF/Rate-Limit gegen Nicht-Browser-Clients; im echten Browser vor Entfernen prüfen. - sources/2026-08-10_stellungnahme-ii-reduzierungsvorschlaege-ii.pdf → 302 → Login (bewusst geschützt, kein toter Link). - Alle übrigen lokalen Assets (25 abholzungen-Thumbs, 17 Visuals, 3 Windpark-PNGs, 3 Source-PDFs, 2026er sources) → 200. - /sources/ejun/ als Verzeichnis → 403 (kein Listing — korrekt so). ### Umsetzung index.html (4 Pfade in Sektion Quellen & Unterlagen) + news.js 12× sourceUrl (Zeilen 82, 89, 96, 103, 122, 129, 136, 143, 150, 157, 164, 171, 178) auf sources/ejun/… umsetzen; /docs/-Archiv-Link (A1) nach Entscheidung ersetzen. Danach: Dev-Deploy + Live-Prüfung aller getauschten Links.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Simon/ejun-page#18
No description provided.