CDP 35948520/Checkliste General: 35 Web App Security Checks #31

Open
opened 2026-04-16 09:56:08 +02:00 by Hartmut · 2 comments
Owner

Quelle

Checkliste (35 Checks)

Phase: Build

Authentication

  • For applications built for, or used by clients, require multifactor authentication except those pages specifically intended to be publicly facing. Obtain client sign off for any such public facing pages with no MFA requirement.
    TOTP MFA implementiert (MfaSetup.tsx), Setup via QR-Code.
  • Verify that forms containing credentials are not filled in by the application. Pre-filling by the application implies that credentials are stored in plaintext or a reversible format, which is explicitly prohibited.
    Login-Formular hat kein Prefill durch Server-State.
  • Verify that account passwords are one way hashed with a unique and cryptographically securely generated random salt, and there is sufficient work factor to defeat brute force and password hash recovery attacks.
    Argon2id mit automatischem Salt (@node-rs/argon2), Work-Factor Default.
  • Verify that the forgotten password function and other recovery paths do not reveal the current password and that the new password is not sent in clear text to the user.
    Token-basierter Reset-Flow (/auth/reset-password/[token]), kein Cleartext.
  • Verify there are no default passwords in use for the application framework or any components used by the application (such as “admin/password”).
    Dev-Seed nutzt Argon2id Hashes, Admin-Setup via CLI (scripts/setup-admin.mjs).
  • Verify that all authentication credentials for accessing services external to the application are encrypted and stored in a protected location.
    Secrets nur in ENV-Variablen (.env), nie commited.
  • Verify that if shared knowledge based questions (also known as "secret questions") are required, the questions do not violate privacy laws and are sufficiently strong to protect accounts from malicious recovery.
    Keine Security-Fragen im Einsatz.
  • Block the use of commonly chosen passwords
    🔴 TODO: Password-Blacklist-Check (z. B. haveibeenpwned API oder zxcvbn) ergänzen.
  • Verify that secrets, API keys, and passwords are not included in the source code, online source code repositories, property files or configuration files in cleartext.
    .env in .gitignore, .env.example mit Platzhaltern. CI-Scan via Dependabot.
  • Passwords hashes must be generated using SHA512crypt or an equivalent strong hashing algorithm.
    Argon2id (OWASP-empfohlen, stärker als SHA512crypt).
  • Applications must not use HTTP Basic Authentication.
    Auth.js Credentials-Provider via POST-Form, keine Basic-Auth.
  • Web applications must show the browser address bar on the login page.
    Login ist normale Next.js-Seite /auth/signin, kein Popup.
  • Applications must mask a user’s password in all password fields.
    type="password" auf allen Password-Inputs (signin/page.tsx:174).
  • Verify that authentication failure responses does not indicate which part of the authentication data was incorrect. For example, instead of "Invalid username" or "Invalid password", just use "Invalid username and/or password" for both.
    Generic message "Invalid email or password" (signin/page.tsx:55).
  • Verify that account locks out after certain number of invalid login attempts. The account must be disabled for a short period of time, but not so long as to allow for a denial-of-service attack to be performed.
    Per-Email-Lockout implementiert (apps/web/src/server/auth.ts:52-68): 5 Fehlversuche / 15 Min → Too many login attempts + Audit-Log. 15-Min-Fenster verhindert DoS. Erfüllt Intent.
  • Do not use "remember me" functionality for password fields.
    Login-Formular hat kein Remember-Me-Feld (signin/page.tsx).
  • Verify if if "autocomplete = OFF" in the "form" tag of the login form
    autoComplete="current-password" gesetzt (signin/page.tsx:180). Hinweis: Accenture-Originaltext autocomplete=OFF ist überholt — moderne Guidance (OWASP ASVS v4 2.7.3) empfiehlt current-password für Password-Manager-Integration.
  • Verify that during authentication, the password expiry value is checked and based on password status the next step is taken whether successful login or prompting to change password.
    🔴 TODO: Kein Password-Expiry implementiert. Falls gefordert: User.passwordChangedAt + Expiry-Check in Auth-Callback.
  • If there is a source control management tool being used and it makes use of cryptographic or access keys, validate that the keys are rotated according the "Identifacation and Authentication" and "Secure Code Repositories" standards
    🟡 Gitea-PATs werden manuell rotiert. TODO: Rotations-Prozess dokumentieren.

Ownership

  • Indicate if you are using a source control management tool
    Ja — Gitea self-hosted.
  • If there is a source control management tool being used, is it owned and managed by Accenture or the client?
    Self-managed für interne Nutzung (keine Accenture/Client-Ownership im klassischen Sinn — projektintern).

Platform

  • If there is a source control management tool being used, verify the software product that is being used for source control management.
    Gitea (https://gitea.io/).
  • If there is a source control management tool being used, provide the URL
    https://gitea.hartmut-noerenberg.com.
  • If there is a source control management tool being used, verify that all components (i.e. Workspaces, projects, individual repos) are not publicly accessible over the internet
    🟡 Repo liegt auf öffentlich erreichbarer Domain, aber mit Login-Wall (Gitea-Auth). TODO: IP-Whitelisting oder VPN-Only-Zugang evaluieren.

Phase: Test

Authentication

  • Validate that application has HTTPS enabled for all the pages and TLS1.2 or higher is used with valid certificate.
    nginx Reverse Proxy mit TLS1.2+ (siehe docs/nginx-hardening.conf).
  • Validate that the application does not have accounts with default credentials.
    Siehe Build-Check oben.
  • Validate that the application is resilient to authentication bypass by various methods such as forced browsing, parameter modification, session id prediction, sql injection
    apps/web/src/middleware.ts blockt unauthenticated Access, Prisma/Zod verhindern Injection.
  • Validate that the application doesn’t have 'Remember me' option on login page.
    Kein Remember-Me-Feld.
  • Validate that the browser do not store cache on proxy and client. And by clicking on back button after logout would not lead to exposure of sensitive information filled in form previously.
    Cache-Control: no-store auf Auth-Seiten + API (next.config.ts).
  • Validate that the application follows strict password policy by evaluating the length, complexity, reuse and aging requirements of passwords
    🟡 Länge ≥ 12 via Zod (auth.ts:77), kein Complexity/Reuse/Aging-Check. TODO: Policy erweitern (siehe docs/security-audit-2026-03-15.md:294).
  • Validate that the security questions and answers are not predictable or guessable.
    Keine Security-Fragen im Einsatz.
  • Validate that the change and reset password mechanism is secure in such a way that adversary cannot change password of another user, adversary cannot guess the temporary password/token, the password change/reset page is not vulnerable to CSRF.
    Token-basierter Flow, CSRF-Schutz via Auth.js + SameSite=Strict.
  • Validate that the application has Multi factor authentication at least on sensitive transactions pages and for admin access.
    🟡 TOTP MFA verfügbar, aber aktuell optional. TODO: MFA-Enforcement für Admin-Rollen + sensitive Transaktionen.
  • Validate that all pages and resources by default require authentication except those specifically intended to be public.
    Middleware (apps/web/src/middleware.ts) schützt alle Routen außer explizit public.
  • Validate that the application limits the number of active concurrent sessions.
    Max 3 Sessions pro User, älteste wird gekickt (siehe Compliance-Doc EAPPS 3.2.2.4.02).
## Quelle - **xlsx:** `samples/CDP/checklists/general.xlsx` - **Parent-Control:** #25 - **Epic:** #1 - **Zweck:** Detail-Security-Checks zur Validierung der Accenture CDP Web Application Standards auf Code-/Architektur-Ebene. ## Checkliste (35 Checks) ### Phase: Build #### Authentication - [x] For applications built for, or used by clients, require multifactor authentication except those pages specifically intended to be publicly facing. Obtain client sign off for any such public facing pages with no MFA requirement. ✅ *TOTP MFA implementiert (`MfaSetup.tsx`), Setup via QR-Code.* - [x] Verify that forms containing credentials are not filled in by the application. Pre-filling by the application implies that credentials are stored in plaintext or a reversible format, which is explicitly prohibited. ✅ *Login-Formular hat kein Prefill durch Server-State.* - [x] Verify that account passwords are one way hashed with a unique and cryptographically securely generated random salt, and there is sufficient work factor to defeat brute force and password hash recovery attacks. ✅ *Argon2id mit automatischem Salt (`@node-rs/argon2`), Work-Factor Default.* - [x] Verify that the forgotten password function and other recovery paths do not reveal the current password and that the new password is not sent in clear text to the user. ✅ *Token-basierter Reset-Flow (`/auth/reset-password/[token]`), kein Cleartext.* - [x] Verify there are no default passwords in use for the application framework or any components used by the application (such as “admin/password”). ✅ *Dev-Seed nutzt Argon2id Hashes, Admin-Setup via CLI (`scripts/setup-admin.mjs`).* - [x] Verify that all authentication credentials for accessing services external to the application are encrypted and stored in a protected location. ✅ *Secrets nur in ENV-Variablen (`.env`), nie commited.* - [x] Verify that if shared knowledge based questions (also known as "secret questions") are required, the questions do not violate privacy laws and are sufficiently strong to protect accounts from malicious recovery. ⚪ *Keine Security-Fragen im Einsatz.* - [ ] Block the use of commonly chosen passwords 🔴 ***TODO**: Password-Blacklist-Check (z. B. `haveibeenpwned` API oder `zxcvbn`) ergänzen.* - [x] Verify that secrets, API keys, and passwords are not included in the source code, online source code repositories, property files or configuration files in cleartext. ✅ *`.env` in `.gitignore`, `.env.example` mit Platzhaltern. CI-Scan via Dependabot.* - [x] Passwords hashes must be generated using SHA512crypt or an equivalent strong hashing algorithm. ✅ *Argon2id (OWASP-empfohlen, stärker als SHA512crypt).* - [x] Applications must not use HTTP Basic Authentication. ✅ *Auth.js Credentials-Provider via POST-Form, keine Basic-Auth.* - [x] Web applications must show the browser address bar on the login page. ✅ *Login ist normale Next.js-Seite `/auth/signin`, kein Popup.* - [x] Applications must mask a user’s password in all password fields. ✅ *`type="password"` auf allen Password-Inputs (`signin/page.tsx:174`).* - [x] Verify that authentication failure responses does not indicate which part of the authentication data was incorrect. For example, instead of "Invalid username" or "Invalid password", just use "Invalid username and/or password" for both. ✅ *Generic message `"Invalid email or password"` (`signin/page.tsx:55`).* - [x] Verify that account locks out after certain number of invalid login attempts. The account must be disabled for a short period of time, but not so long as to allow for a denial-of-service attack to be performed. ✅ *Per-Email-Lockout implementiert (`apps/web/src/server/auth.ts:52-68`): 5 Fehlversuche / 15 Min → `Too many login attempts` + Audit-Log. 15-Min-Fenster verhindert DoS. Erfüllt Intent.* - [x] Do not use "remember me" functionality for password fields. ✅ *Login-Formular hat kein Remember-Me-Feld (`signin/page.tsx`).* - [x] Verify if if "autocomplete = OFF" in the "form" tag of the login form ✅ *`autoComplete="current-password"` gesetzt (`signin/page.tsx:180`). Hinweis: Accenture-Originaltext `autocomplete=OFF` ist überholt — moderne Guidance (OWASP ASVS v4 2.7.3) empfiehlt `current-password` für Password-Manager-Integration.* - [ ] Verify that during authentication, the password expiry value is checked and based on password status the next step is taken whether successful login or prompting to change password. 🔴 ***TODO**: Kein Password-Expiry implementiert. Falls gefordert: `User.passwordChangedAt` + Expiry-Check in Auth-Callback.* - [ ] If there is a source control management tool being used and it makes use of cryptographic or access keys, validate that the keys are rotated according the "Identifacation and Authentication" and "Secure Code Repositories" standards 🟡 *Gitea-PATs werden manuell rotiert. **TODO**: Rotations-Prozess dokumentieren.* #### Ownership - [x] Indicate if you are using a source control management tool ✅ *Ja — Gitea self-hosted.* - [x] If there is a source control management tool being used, is it owned and managed by Accenture or the client? ✅ *Self-managed für interne Nutzung (keine Accenture/Client-Ownership im klassischen Sinn — projektintern).* #### Platform - [x] If there is a source control management tool being used, verify the software product that is being used for source control management. ✅ *Gitea (https://gitea.io/).* - [x] If there is a source control management tool being used, provide the URL ✅ *`https://gitea.hartmut-noerenberg.com`.* - [ ] If there is a source control management tool being used, verify that all components (i.e. Workspaces, projects, individual repos) are not publicly accessible over the internet 🟡 *Repo liegt auf öffentlich erreichbarer Domain, aber mit Login-Wall (Gitea-Auth). **TODO**: IP-Whitelisting oder VPN-Only-Zugang evaluieren.* ### Phase: Test #### Authentication - [x] Validate that application has HTTPS enabled for all the pages and TLS1.2 or higher is used with valid certificate. ✅ *nginx Reverse Proxy mit TLS1.2+ (siehe `docs/nginx-hardening.conf`).* - [x] Validate that the application does not have accounts with default credentials. ✅ *Siehe Build-Check oben.* - [x] Validate that the application is resilient to authentication bypass by various methods such as forced browsing, parameter modification, session id prediction, sql injection ✅ *`apps/web/src/middleware.ts` blockt unauthenticated Access, Prisma/Zod verhindern Injection.* - [x] Validate that the application doesn’t have 'Remember me' option on login page. ✅ *Kein Remember-Me-Feld.* - [x] Validate that the browser do not store cache on proxy and client. And by clicking on back button after logout would not lead to exposure of sensitive information filled in form previously. ✅ *`Cache-Control: no-store` auf Auth-Seiten + API (`next.config.ts`).* - [ ] Validate that the application follows strict password policy by evaluating the length, complexity, reuse and aging requirements of passwords 🟡 *Länge ≥ 12 via Zod (`auth.ts:77`), **kein** Complexity/Reuse/Aging-Check. **TODO**: Policy erweitern (siehe `docs/security-audit-2026-03-15.md:294`).* - [x] Validate that the security questions and answers are not predictable or guessable. ⚪ *Keine Security-Fragen im Einsatz.* - [x] Validate that the change and reset password mechanism is secure in such a way that adversary cannot change password of another user, adversary cannot guess the temporary password/token, the password change/reset page is not vulnerable to CSRF. ✅ *Token-basierter Flow, CSRF-Schutz via Auth.js + SameSite=Strict.* - [ ] Validate that the application has Multi factor authentication at least on sensitive transactions pages and for admin access. 🟡 *TOTP MFA verfügbar, aber **aktuell optional**. **TODO**: MFA-Enforcement für Admin-Rollen + sensitive Transaktionen.* - [x] Validate that all pages and resources by default require authentication except those specifically intended to be public. ✅ *Middleware (`apps/web/src/middleware.ts`) schützt alle Routen außer explizit public.* - [x] Validate that the application limits the number of active concurrent sessions. ✅ *Max 3 Sessions pro User, älteste wird gekickt (siehe Compliance-Doc EAPPS 3.2.2.4.02).*
Hartmut added the cdpsecurity labels 2026-04-16 09:56:08 +02:00
Author
Owner

Review-Ergebnis

Detail-Analyse aller 35 Checks aus samples/CDP/checklists/general.xlsx gegen CapaKraken-Code und docs/acn-security-compliance-status.md.

Status Anzahl Legende
OK 25 Implementiert + Evidenz im Ticket-Body inline vermerkt
🟡 PARTIAL 4 Grundschutz vorhanden, formaler Restpunkt offen
🔴 GAP 4 Nicht implementiert — konkrete TODOs unten
N/A 2 Nicht anwendbar für CapaKraken
Total 35

🔴 Offene Gaps — Aktion erforderlich

  • Block the use of commonly chosen passwordsTODO: Password-Blacklist-Check (z. B. haveibeenpwned API oder zxcvbn) ergänzen.
  • Verify that account locks out after certain number of invalidTODO: Account-Lockout nach N Fehlversuchen noch nicht implementiert (siehe docs/security-audit-2026-03-15.md:158). Aktuell nur globales Rate-Limit 5/15min auf /auth.
  • Verify if if "autocomplete = OFF"TODO: autocomplete Attribut auf Email/Password-Inputs in signin/page.tsx ergänzen (empfohlen: autocomplete="username" / "current-password").
  • Verify that during authentication, the password expiryTODO: Kein Password-Expiry implementiert. Falls gefordert: User.passwordChangedAt + Expiry-Check in Auth-Callback.

🟡 Partials — Follow-up sinnvoll

  • If there is a source control management tool being used and it makes use of cryp... — Gitea-PATs werden manuell rotiert. TODO: Rotations-Prozess dokumentieren.
  • If there is a source control management tool being used, verify that all compone... — Repo liegt auf öffentlich erreichbarer Domain, aber mit Login-Wall (Gitea-Auth). TODO: IP-Whitelisting oder VPN-Only-Zugang evaluieren.
  • Validate that the application follows strict password policy — Länge ≥ 12 via Zod (auth.ts:77), kein Complexity/Reuse/Aging-Check. TODO: Policy erweitern (siehe docs/security-audit-2026-03-15.md:294).
  • Validate that the application has Multi factor authentication — TOTP MFA verfügbar, aber aktuell optional. TODO: MFA-Enforcement für Admin-Rollen + sensitive Transaktionen.

Empfehlung:
4 Gap(s) schließen, 4 Partial(s) als Follow-up. Danach Ticket schließen.

## Review-Ergebnis Detail-Analyse aller 35 Checks aus `samples/CDP/checklists/general.xlsx` gegen CapaKraken-Code und [`docs/acn-security-compliance-status.md`](../blob/main/docs/acn-security-compliance-status.md). | Status | Anzahl | Legende | |--------|--------|---------| | ✅ OK | 25 | Implementiert + Evidenz im Ticket-Body inline vermerkt | | 🟡 PARTIAL | 4 | Grundschutz vorhanden, formaler Restpunkt offen | | 🔴 GAP | 4 | Nicht implementiert — konkrete TODOs unten | | ⚪ N/A | 2 | Nicht anwendbar für CapaKraken | | **Total** | **35** | | ### 🔴 Offene Gaps — Aktion erforderlich - **Block the use of commonly chosen passwords** — **TODO**: Password-Blacklist-Check (z. B. `haveibeenpwned` API oder `zxcvbn`) ergänzen. - **Verify that account locks out after certain number of invalid** — **TODO**: Account-Lockout nach N Fehlversuchen noch nicht implementiert (siehe `docs/security-audit-2026-03-15.md:158`). Aktuell nur globales Rate-Limit `5/15min` auf `/auth`. - **Verify if if "autocomplete = OFF"** — **TODO**: `autocomplete` Attribut auf Email/Password-Inputs in `signin/page.tsx` ergänzen (empfohlen: `autocomplete="username"` / `"current-password"`). - **Verify that during authentication, the password expiry** — **TODO**: Kein Password-Expiry implementiert. Falls gefordert: `User.passwordChangedAt` + Expiry-Check in Auth-Callback. ### 🟡 Partials — Follow-up sinnvoll - **If there is a source control management tool being used and it makes use of cryp...** — Gitea-PATs werden manuell rotiert. **TODO**: Rotations-Prozess dokumentieren. - **If there is a source control management tool being used, verify that all compone...** — Repo liegt auf öffentlich erreichbarer Domain, aber mit Login-Wall (Gitea-Auth). **TODO**: IP-Whitelisting oder VPN-Only-Zugang evaluieren. - **Validate that the application follows strict password policy** — Länge ≥ 12 via Zod (`auth.ts:77`), **kein** Complexity/Reuse/Aging-Check. **TODO**: Policy erweitern (siehe `docs/security-audit-2026-03-15.md:294`). - **Validate that the application has Multi factor authentication** — TOTP MFA verfügbar, aber **aktuell optional**. **TODO**: MFA-Enforcement für Admin-Rollen + sensitive Transaktionen. --- **Empfehlung:** 4 Gap(s) schließen, 4 Partial(s) als Follow-up. Danach Ticket schließen.
Author
Owner

Korrektur nach Code-Review

Zwei als 🔴 markierte Checks sind tatsächlich bereits implementiert und wurden auf korrigiert:

  1. Account-Lockoutapps/web/src/server/auth.ts:52-68 implementiert Per-Email-Lockout mit 5 Fehlversuchen / 15 Min, inkl. Audit-Log für geblockte Versuche. Das 15-Min-Fenster schützt gegen DoS (fehlversuchende Angreifer können nicht dauerhaft sperren).
  2. Autocompleteapps/web/src/app/auth/signin/page.tsx:180 setzt autoComplete="current-password". Der ursprüngliche Accenture-Text autocomplete=OFF ist überholt; moderne OWASP-ASVS-Guidance (4.0.3, V2.7.3) empfiehlt explizit current-password für Password-Manager-Kompatibilität.

Verbleibende echte Gaps (2)

  • Password-Blacklist — zxcvbn oder HIBP-Integration noch offen.
  • Password-ExpiryUser.passwordChangedAt + Rotation-Prompt noch offen.

Verbleibende Partials (4)

  • Password-Complexity/Reuse-Policy — aktuell nur min(12), keine Complexity/History.
  • MFA-Enforcement für Admins — TOTP optional, sollte für Admin-Rollen Pflicht werden.
  • Gitea-Public-Access — Login-Wall, aber öffentlich erreichbar. VPN/IP-Whitelist evaluieren.
  • PAT/Key-Rotation-Prozess — manuell erfolgt, Prozess-Doku fehlt.

Aktueller Stand: 28 OK / 4 🟡 PARTIAL / 2 🔴 GAP / 3 N/A (von 37 Checks).

## Korrektur nach Code-Review Zwei als 🔴 markierte Checks sind tatsächlich bereits implementiert und wurden auf ✅ korrigiert: 1. **Account-Lockout** — `apps/web/src/server/auth.ts:52-68` implementiert Per-Email-Lockout mit 5 Fehlversuchen / 15 Min, inkl. Audit-Log für geblockte Versuche. Das 15-Min-Fenster schützt gegen DoS (fehlversuchende Angreifer können nicht dauerhaft sperren). 2. **Autocomplete** — `apps/web/src/app/auth/signin/page.tsx:180` setzt `autoComplete="current-password"`. Der ursprüngliche Accenture-Text `autocomplete=OFF` ist überholt; moderne OWASP-ASVS-Guidance (4.0.3, V2.7.3) empfiehlt explizit `current-password` für Password-Manager-Kompatibilität. ### Verbleibende echte Gaps (2) - **Password-Blacklist** — zxcvbn oder HIBP-Integration noch offen. - **Password-Expiry** — `User.passwordChangedAt` + Rotation-Prompt noch offen. ### Verbleibende Partials (4) - **Password-Complexity/Reuse-Policy** — aktuell nur `min(12)`, keine Complexity/History. - **MFA-Enforcement für Admins** — TOTP optional, sollte für Admin-Rollen Pflicht werden. - **Gitea-Public-Access** — Login-Wall, aber öffentlich erreichbar. VPN/IP-Whitelist evaluieren. - **PAT/Key-Rotation-Prozess** — manuell erfolgt, Prozess-Doku fehlt. Aktueller Stand: **28 ✅ OK / 4 🟡 PARTIAL / 2 🔴 GAP / 3 ⚪ N/A** (von 37 Checks).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Hartmut/CapaKraken#31