5.9 KiB
Limited administration exposure audit - 0.7.1
Scope and evidence
Reviewed the supplied 0.7.0 source and this patch's admin router/middleware, authentication endpoints, sessions, API assets, dashboard login/logout, Swagger integration, proxy header rule precedence and deployment readiness consumer. This is a manual source review plus static/browser-script regression tests. It is not a penetration test of the user's installed binary or a complete audit of proxy/TLS/QUIC/ACME/operating-system/dependency security. No Rust compiler was available; runtime enforcement and complete vendor rendering remain unverified.
The reported unauthenticated operational JSON disclosure was not reproduced on
an installed server. In the input source, /api/config, status, logs, metrics,
backend/cache and certificate endpoints already passed through a session guard.
The concrete findings were public version/mode metadata, unnecessarily public
operational HTML/JS/full language assets, broad path-only method exceptions and
incomplete browser-state minimization. Do not infer that a user's older build,
reverse-proxy front or a different exposed endpoint had the same behavior.
Findings and source changes
| Observation | 0.7.1 change | Verification limit |
|---|---|---|
/healthz disclosed version; auth discovery disclosed version/mode/password policy |
Health reduced to one status field; auth discovery to setup-required boolean | Source/contract tests; actual router tests supplied, not run |
| Full operational HTML/modules/language bundle could be fetched anonymously | Root selects minimal login or authenticated document; full modules/bundle are private | Login fetch/DOM checks use mocked fetch, not real HTTP |
| Public route exemptions were not a strict method/path matrix | Explicit allowlist; private and unknown requests denied before JSON/query parsing | Six additional async Rust test functions supplied, unexecuted |
| Anonymous JSON rejection could include extractor input detail | Login/setup map parser failures to a fixed message, preserving 400/413/415 status semantics | Source and unexecuted router tests |
| Mutation marker/CSRF duplicate values were not explicitly rejected | Require one exact Origin, marker and session-bound CSRF value | Existing guards retained; added unexecuted duplicate-header tests |
| Stale DOM/form values can outlive a visible logout screen | Scrub inputs/state, notify other tabs, reload root; docs clear schema/results on session change | Chromium script tests with simulated location/storage |
| New API docs would otherwise create another disclosure surface | Protect document, schema and every necessary asset with existing guard; no wildcard asset route | Route/schema contracts; vendor-renderer acceptance outstanding |
| Interactive docs can carry credentials into requests | Fixed same-origin schema, per-action session verification, no external validator/persisted auth, writes opt-in + CSRF | Custom interceptor tests use a vendor stub; server guard is the authority |
Updater used public version in /healthz |
Locally verify systemd MainPID executable against staged release after minimal readiness | Temporary-file and simulated-systemd tests; real deployment not run |
Deliberate public minimum
Anonymous login assets, favicon/shared CSS, setup-needed boolean, minimal health status, and guarded login/one-time setup POSTs remain. These are necessary for sign-in, initial administration and local readiness. Static CSS may contain UI selectors; it contains no runtime configuration or secrets. Invalid Host/Origin still returns generic 403 instead of bypassing the boundary.
Login/setup POST success is allowed to create/return session information only after credential/capability validation. No API Bearer token or setup token was added as an alternative authority for operational reads. Setup remains one-time, local-capability-based; password checking/rate limiting/session invalidation were not weakened or replaced by JavaScript-only checks.
Separate Prometheus listener
Admin /metrics and /api/metrics require the browser/admin session. The optional
standalone Prometheus listener remains independent, disabled by default, with
configured source CIDRs and its existing bearer-token policy. Non-loopback export
requires a token by the existing Rust validation. A loopback exporter can be
intentionally configured without a browser login. Do not treat it as an overlooked
admin API exception, and do not place it on an untrusted network without reviewing
its token, CIDRs and protected transport. This patch does not verify its runtime.
Outstanding acceptance and operational caveats
- Build and execute
dev.sh check/dev.sh test; runadmin_audit.pyagainst the actual upgraded service. Compare 401/no-store responses without cookies. - Open real
/docsin a normal browser; verify rendering, actual cookie+Origin+CSRF, logout, CSP console output and failure after revocation. Vendor assets were not downloaded/rendered here, and build dependency compatibility is unverified. - Test real install/update restart/rollback; local MainPID and
/procverification now fail closed when the expected executable cannot be established. - Retain loopback-only administration and use a protected tunnel. Cookie/session security does not protect a compromised local account, malicious browser extension, an administrator sharing exported configuration, or every possible web attack.
- No RBAC/read-only administrator role, general API token scopes, dependency CVE scan, fuzzing or proof of vulnerability absence is delivered by this small patch.
- Review a real resolved Cargo.lock and the pinned Swagger artifact before shipping binaries. Source review is not a substitute for release acceptance.
For the exact exposure matrix and test/build commands, read API_ACCESS.md. The review uses OWASP REST/session guidance as a checklist, not a certification: https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html