.NET: DevUI: add configurable access controls for the DevUI HTTP surface#5739
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a configurable access-control surface for the .NET DevUI HTTP endpoints so hosts can restrict remote exposure and optionally require authentication when DevUI is enabled.
Changes:
- Introduces
DevUIOptionsand aDevUIAuthFilterendpoint filter to enforce loopback-only defaults plus optional bearer-token auth. - Extends
AddDevUIto accept configuration callbacks (services + host builder) and wires options/filter intoMapDevUI. - Adds DevUI access-control unit tests and documents the new security posture in the package README.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| dotnet/tests/Microsoft.Agents.AI.DevUI.UnitTests/DevUIAccessControlTests.cs | Adds unit tests covering loopback vs remote access and bearer-token enforcement. |
| dotnet/src/Microsoft.Agents.AI.DevUI/ServiceCollectionsExtensions.cs | Updates AddDevUI to configure DevUIOptions and register the auth filter. |
| dotnet/src/Microsoft.Agents.AI.DevUI/HostApplicationBuilderExtensions.cs | Updates host-builder AddDevUI to accept DevUIOptions configuration. |
| dotnet/src/Microsoft.Agents.AI.DevUI/DevUIOptions.cs | New options type controlling DevUI access posture and endpoint conventions. |
| dotnet/src/Microsoft.Agents.AI.DevUI/DevUIAuthFilter.cs | New endpoint filter implementing loopback restriction + optional bearer-token auth. |
| dotnet/src/Microsoft.Agents.AI.DevUI/DevUIExtensions.cs | Wraps DevUI routes in a group, applies the auth filter, and emits a warning for insecure configuration. |
| dotnet/src/Microsoft.Agents.AI.DevUI/README.md | Documents DevUI security defaults and configuration knobs. |
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 91%
✓ Correctness
The DevUI access control implementation is well-designed and correct. The DevUIAuthFilter properly enforces lopback-only access by default and optional bearer-token authentication. Token comparison uses CryptographicOperations.FixedTimeEquals. The singleton filter is thread-safe since InvokeAsync only reads immutable state set in the constructor. Service registration, options plumbing, and the endpoint filter attachment all look correct. Tests cover the key paths: remote-blocked-by-default, AllowRemoteAccess bypass, token-required, correct-token-accepted, wrong-token-rejected. No correctness issues found.
✓ Security Reliability
The DevUI access control implementation is well-structured for its stated purpose as a development-only tool. The lopback-by-default posture, constant-time token comparison via CryptographicOperations.FixedTimeEquals, credential-free logging, and startup misconfiguration warning are all sound. The singleton DevUIAuthFilter correctly captures IOptions at construction time. The bearer token parsing is lenient but correct, handling extra whitespace and multiple Authorization headers gracefully. No blocking security issues found.
✓ Test Coverage
The new
DevUIAccessControlTestscover the five core access-control paths well (default lopback rejection, AllowRemoteAccess bypass, missing token → 401, correct token → 200, wrong token → 401). Two notable behavioral code paths introduced by this PR lack any test coverage: (1) theDEVUI_AUTH_TOKENenvironment variable fallback inDevUIAuthFilter, which can silently enable token-based auth whenAuthTokenis not set in code, and (2) theConfigureEndpointscallback, which lets hosts attach authorization policies to the DevUI route group. Neither is exercised by the existing or new tests.
✗ Design Approach
The access-control feature is headed in the right direction, but the current design applies the new auth filter to
/metaas well as the protected DevUI APIs. That breaks the existing frontend contract, which relies on an unauthenticated/metacall to discover whetherauth_requiredis true before prompting for a token.
Flagged Issues
-
DevUIExtensions.cs:49applies the auth filter to the root route group, which also covers/meta. The frontend fetches/metaunauthenticated to discover whetherauth_requiredis true (App.tsx:96-107,222-223), andMetaResponsedocuments this as the endpoint to 'Verify authentication requirements' (MetaResponse.cs:12-16). In token-protected deployments this returns 401 before the client can bootstrap the auth flow. Keep/metapublic and scope the filter to the protected endpoints only.
Automated review by moonbox3's agents
- Restore parameterless AddDevUI overloads for binary compatibility on IServiceCollection and IHostApplicationBuilder. - Keep /meta outside the auth-filtered group so the frontend can discover whether a bearer token is required before prompting for one. Surface the actual requirement via MetaResponse.auth_required. - Invoke DevUIOptions.ConfigureEndpoints before mapping protected endpoints so RouteGroupBuilder conventions (RequireAuthorization, rate limiting) reliably apply. - Treat a null RemoteIpAddress as non-loopback in DevUIAuthFilter; tests now set IPAddress.Loopback explicitly when exercising the loopback path. - Add a DEVUI_AUTH_TOKEN env-var fallback test and a /meta-public test. - Fix dotnet format: add UTF-8 BOM to new files, simplify a cref in DevUIOptions, and drop an unused using in the new test.
…efault DevUIIntegrationTests use the default TestServer which leaves RemoteIpAddress null. With the new conservative loopback default those tests now hit 403; set AllowRemoteAccess on the option since those tests are not exercising access control. Also add the missing SimulateRemoteIp call in the wrong-bearer test.
… see it The env-var test was leaking DEVUI_AUTH_TOKEN into parallel DevUIIntegrationTests, intermittently causing their requests to be rejected as 401. Eagerly resolve the singleton DevUIAuthFilter so its constructor captures the token, then restore the env var before any HTTP requests run.
Motivation and Context
Microsoft.Agents.AI.DevUIis a development-time package that maps/devui,/v1/entities, and related endpoints into an ASP.NET Core host. Today these endpoints have no built-in configurability around who can reach them, so hosts have to bolt on conventions themselves. This PR adds a smallDevUIOptionssurface so hosts can declare intent up front and so the defaults are more conservative when DevUI is referenced from non-development environments.Description
DevUIOptionswithAllowRemoteAccess,AuthToken, and aConfigureEndpointscallback for plugging in real authorization policies.DevUIAuthFilter(registered as a singleton) attached as an endpoint filter on the DevUI route group, so it covers every endpoint mapped byMapDevUI.AddDevUI(this IServiceCollection, Action<DevUIOptions>?)andAddDevUI(this IHostApplicationBuilder, Action<DevUIOptions>?)overloads. The original parameterless overload keeps working.DevUIAccessControlTestscovers the five paths: non-loopback rejected by default,AllowRemoteAccessbypasses the check, token required when configured, correct token accepted, wrong token rejected. Verified RED→GREEN by toggling the filter and watching the assertions flip.Defaults are loopback-only; the bearer-token check is constant-time and falls back to the
DEVUI_AUTH_TOKENenvironment variable when no token is configured in code.Contribution Checklist