zhaohai666 opened a new pull request, #1673: URL: https://github.com/apache/rocketmq-dashboard/pull/1673
# PR: fix(security): harden SSRF guards, default login and edge exposure **Branch:** `feature/studio-security-hardening` **Commit:** `814bf241` — pushed to `origin/feature/studio-security-hardening` **Base:** `apache:rocketmq-studio` @ `990ba092` **PR create link:** https://github.com/zhaohai666/rocketmq-dashboard/pull/new/feature/studio-security-hardening ## Summary Security hardening for the P0 items from the 2026-08-11 audit: SSRF guards are now shared and applied on every path that makes a server-side request to a caller-supplied URL, login is required by default and the auth gate fails closed, and the deployment no longer exposes the backend port or the full actuator surface. ## Changes ### Shared SSRF guard (`server/.../common/util/UrlHostGuard.java`, new) Rejects loopback, link-local (including the cloud-metadata range `169.254.169.254`) and any-local hosts. Unlike the old per-service check, unresolvable hosts are rejected (fail-closed) instead of being handed to the connection layer. Private site-local ranges stay allowed for on-premise Prometheus / internal LLM gateways. Applied on every path: - **Data source save** — `SettingsService.createDataSource/updateDataSource` now validate the URL when saving. Previously only the test path was guarded, so a data source pointing at `127.0.0.1` could be stored and later queried. - **Data source query** — `AbstractPrometheusCompatibleMetricsSource.queryRangeUri` validates the stored base URL on every request (defense in depth against direct DB edits). - **Data source test** — `SettingsService.isAllowedDataSourceHost` now delegates to the guard. - **LLM config** — `LlmConfigService.validate()` (used by both save and test) rejects link-local/metadata hosts while allowing loopback, so a local `ollama` gateway keeps working. ### Authentication - Default `studio.auth.login-required=true` in `application.yml`, `deploy/docker-compose.yml` and `deploy/deploy.sh`. - `AuthInterceptor.isLoginRequired()` fails closed when the settings store cannot be read (previously it defaulted to *no* login requirement). ### Deployment - `deploy/docker-compose.yml`: MySQL root password externalized to the `MYSQL_ROOT_PASSWORD` env var (compose-default `studio123` kept for out-of-the-box use); the healthcheck reads the password from the environment instead of hard-coding it in the command line. - `web/nginx.conf` + `deploy/nginx.conf`: only `/actuator/health` is proxied at the edge; the rest of `/actuator/` returns 404. - `deploy/deploy.sh`: the backend `8888` port is no longer published to the host (nginx already proxies `/api/` inside the podman network). ## Verification - `mvn compile` — BUILD SUCCESS (checkstyle clean). - `SettingsServiceTest` 31/31 (incl. two new SSRF rejection tests: create rejects loopback, update rejects metadata address), `LlmConfigServiceTest` 21/21, `AuthInterceptorTest` 16/16. ## Notes - Behavior change for existing deployments: login is now required by default; set `STUDIO_AUTH_LOGIN_REQUIRED=false` only when the deployment is intentionally unauthenticated (e.g. local development). -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
