|
@@ -11,7 +11,7 @@
|
|
|
>
|
|
>
|
|
|
> Each finding is referenced as **F<N>** for later citation.
|
|
> Each finding is referenced as **F<N>** for later citation.
|
|
|
>
|
|
>
|
|
|
-> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (21 fixed, 6 open), 42 sev-1.
|
|
|
|
|
|
|
+> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (27 fixed, 0 open), 42 sev-1 (1 fixed, 41 open).
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
@@ -1159,6 +1159,20 @@
|
|
|
later confuse two users since the OIDC primary key is `subject` but
|
|
later confuse two users since the OIDC primary key is `subject` but
|
|
|
some IdPs don't release `email`.
|
|
some IdPs don't release `email`.
|
|
|
- **Severity: 1**
|
|
- **Severity: 1**
|
|
|
|
|
+- **Status:** Fixed. `UserRepository::upsertOidc` now types `email` as
|
|
|
|
|
+ `?string` and the DBAL upsert persists `users.email = NULL` when the
|
|
|
|
|
+ IdP doesn't release the claim. `AuthController::upsertOidc` switches
|
|
|
|
|
+ to a `nullableStr()` extractor for `email` (missing / JSON-null /
|
|
|
|
|
+ empty string all collapse to `null`); `subject` and `display_name`
|
|
|
|
|
+ remain mandatory. The `user.created` / `user.role_changed` audit
|
|
|
|
|
+ rows fall back to `display_name` for `target_label` when `email`
|
|
|
|
|
+ is null, so SOC tooling still gets a human-readable identifier.
|
|
|
|
|
+ Regression tests in
|
|
|
|
|
+ `api/tests/Integration/Auth/AuthEndpointsTest.php`
|
|
|
|
|
+ (`testUpsertOidcAcceptsMissingEmail`,
|
|
|
|
|
+ `testUpsertOidcAcceptsExplicitNullEmail`,
|
|
|
|
|
+ `testUpsertOidcStillRejectsMissingSubject`,
|
|
|
|
|
+ `testUpsertOidcStillRejectsMissingDisplayName`).
|
|
|
|
|
|
|
|
### F34 — Sensitive identifiers logged at INFO/WARN/ERROR
|
|
### F34 — Sensitive identifiers logged at INFO/WARN/ERROR
|
|
|
- **Files:** `ui/src/Auth/LoginThrottle.php:79-90`,
|
|
- **Files:** `ui/src/Auth/LoginThrottle.php:79-90`,
|