diff --git a/devdocs/modernization/NET10-PORT.md b/devdocs/modernization/NET10-PORT.md index 1d213791..8dcca74c 100644 --- a/devdocs/modernization/NET10-PORT.md +++ b/devdocs/modernization/NET10-PORT.md @@ -193,7 +193,7 @@ John's "next release" cases for AyaNova (exported 2026-10-24). Each is its own s | 4724 | SMTP: certificate checked, password never returned | F30, F31. **Done** (certificate checked, opt-out config setting `AYANOVA_SMTP_ACCEPT_ANY_CERTIFICATE` with manual page; password masked as `********` and kept on save; test `SmtpPasswordHidden`; self-signed listener proof; changelog lines for both) | | 4725 | Sessions: password change ends sessions, exact-path token exemption, default SuperUser refused when licensed | F7, F8, F9. **Done** (sessions end on reset, administrator password change and login disabled; exact route exemption, inactive users refused; default-password SuperUser limited to changing it on a purchased licence, option A; test `Sessions`; John's click-through with a temporary licence override; manual and changelog) | | 4726 | Login throttling/lockout (raven and sockeye) | F6. **Done** (10 failures per login or 50 per address in 15 minutes, then 429 for the rest of the window; same in Sockeye, whose login is public; test `LoginLockout`; per-address limit proved with a forwarded documentation address) | -| 4727 | Low severity hardening | F10, F11, F12, F22, F23, F25, F29, F35, F36, F38; the AyaNova half of F39 (DB ID not shown anonymously). In steps: 1 logo (F23) **done**; 2 API root page (F11, F39); 3 `server-info` (F29); 4 job owner and template export (F22); 5 `OverrideUserId` and export download (F25); 6 safe headers (F35); 7 remove `dist/docker` (F38) | +| 4727 | Low severity hardening | F10, F11, F12, F22, F23, F25, F29, F35, F36, F38; the AyaNova half of F39 (DB ID not shown anonymously). In steps: 1 logo (F23) **done**; 2 API root page (F11, F39) **done**; 3 `server-info` (F29); 4 job owner and template export (F22); 5 `OverrideUserId` and export download (F25); 6 safe headers (F35); 7 remove `dist/docker` (F38) | | 4681 | Sockeye: licence/trial request hardening (tagged sockeye, rockfish) | F40. **Done** (sockeye `cd3ebed`: rate limits, email check, cryptographic codes; rvf unchanged) | **From the port and earlier triage** diff --git a/devdocs/modernization/SECURITY-REVIEW.md b/devdocs/modernization/SECURITY-REVIEW.md index 96c668e6..bc1c633f 100644 --- a/devdocs/modernization/SECURITY-REVIEW.md +++ b/devdocs/modernization/SECURITY-REVIEW.md @@ -223,7 +223,7 @@ take the next free number; a fixed or accepted finding keeps its ID and changes | F8 | Low | **fixed in case 4725** | Latest-token check skipped for any URL ending in `/auth` or `notify/hello` | | F4 | Low | **fixed in cases 4712 and 4723** | Any logged-in user can send an in-app notification to any user | | F10 | Low | confirmed | Anyone can record acceptance of the licence agreement (`license/lc`) | -| F11 | Low | confirmed | API root page shows licensee, version, licence terms (and DB ID when unlicensed) to anyone | +| F11 | Low | **fixed in case 4727** | API root page shows licensee, version, licence terms (and DB ID when unlicensed) to anyone | | F12 | Low | confirmed | Password hashing: PBKDF2-SHA512 with 10,000 iterations | | F25 | Low | confirmed (code) | Attachment and export gaps: upload stored before the rights check, "attached by" can be set to anyone, exports not tied to their user | | F29 | Low | confirmed (code) | `server-info` gives every login, customer contacts included, the server DB ID and full licence details | @@ -354,6 +354,7 @@ does not prove who accepted. Fix: require SuperUser. `GET /api/v8/` returns an HTML page with the exact version, "Registered to", licence type, expiry dates and licensed features; unlicensed, the server DB ID. Helps an attacker pick targets by version. Fix: show it only to logged-in users, or show the version only. +**Fixed in case 4727, step 2 (2026-10-24):** the page shows the version and the links only; the licence block is gone and the support link no longer carries the DB ID and licensee (it did, unlicensed or not). The DB ID stays available to logged-in users (licence form, About form support link). Test `ApiRoute.ServerApiRootPageHasNoDbIdOrLicence`. The manual's screenshot of this page (`api-console.md`) still shows the old licence block. ### F12 Password hashing strength (pass 2) diff --git a/docs/8.0/ayanova/docs/changelog.md b/docs/8.0/ayanova/docs/changelog.md index e55a23e1..09524f5f 100644 --- a/docs/8.0/ayanova/docs/changelog.md +++ b/docs/8.0/ayanova/docs/changelog.md @@ -28,6 +28,7 @@ IN PROGRESS - Server: removed an unused internal performance profiling component. - Server: AyaNova now checks the email (SMTP) server's security certificate when sending email. If your mail server uses a self-signed or internal certificate and email notifications stop after upgrading, see [SMTP certificate check](ops-config-smtp-accept-any-certificate.md). - Server: after repeated failed login attempts, further attempts for that login, or from that address, are refused for a few minutes. +- Server: the server information page at `/api/v8/` no longer shows license details. - Server: business logo uploads must be PNG, JPEG, GIF, WebP or SVG images, and need full rights to global settings. See [business logos](adm-global-logo.md). - Server: when a user's password is reset or set by an administrator, or their login is disabled, they are signed out and must sign in again. - Server: on a server with a purchased license, the SuperUser account can only be used to change its password while it still has the default password, and the login form no longer offers the default SuperUser login. See [SuperUser login](ay-start-login.md). diff --git a/server/AyaNova/Controllers/ApiRootController.cs b/server/AyaNova/Controllers/ApiRootController.cs index ebf33ae6..2dd79495 100644 --- a/server/AyaNova/Controllers/ApiRootController.cs +++ b/server/AyaNova/Controllers/ApiRootController.cs @@ -47,9 +47,9 @@ namespace AyaNova.Api.Controllers */ - var dbId = Uri.EscapeDataString(AyaNova.Core.License.ServerDbId); - var company = Uri.EscapeDataString(AyaNova.Core.License.ActiveKey.RegisteredTo); - return $"https://contact.ayanova.com/contact?dbid={dbId}&company={company}"; + //case 4727 (F11, F39): this page is anonymous, so the link no longer carries the DB ID and licensee; + //the About form's support link (logged in) still fills them in + return "https://contact.ayanova.com/contact"; } @@ -98,7 +98,6 @@ namespace AyaNova.Api.Controllers
{AyaNova.Core.License.LicenseInfo}