Summary
The interactive authentication URL extractor accepts non-local http:// URLs and exposes them as authUrl / verificationUrl.
Local callback/listener URLs are already filtered by hostname, but an external plaintext HTTP destination survives the same parser even though authentication instructions should not direct a user to an unencrypted remote endpoint.
Reproduction / evidence
Current upstream main at 37bf87a692fc72d41f7312cc48808d699d204fba scans terminal output with:
and accepts the first parsed URL whose hostname is not local/loopback. There is no protocol check after new URL(url).
A deterministic process-boundary reproduction is a fake Codex login child that prints:
Open http://auth.example.test/device
User code: ABCD-EFGH
and exits successfully. CodexLoginHandle.wait() then leaves:
handle.verificationUrl === "http://auth.example.test/device"
The existing authentication tests already demonstrate that local HTTP listener URLs should be ignored while a later HTTPS verification URL is retained.
Expected behavior
Remote authentication metadata should accept HTTPS only. HTTP loopback/listener lines may continue to be parsed and ignored, but an external plaintext HTTP URL must not become the URL presented to callers.
Root cause
preferredAuthUrl() validates hostname locality but not the parsed URL protocol. Because the initial regex admits both HTTP and HTTPS, any syntactically valid external HTTP URL passes.
Suggested fix
After parsing each candidate URL, require parsed.protocol === "https:" before accepting its hostname. Keep the existing loopback and local-host exclusions unchanged.
Add a regression using a real child process that emits an external HTTP URL and a user code, then assert the login result does not expose that URL.
Impact
This is an authentication-boundary hardening/correctness issue. Codex Security does not itself navigate to the URL, but SDK/UI consumers can present verificationUrl to a user. Accepting a plaintext remote destination makes terminal output capable of steering that user toward an unencrypted authentication endpoint.
Summary
The interactive authentication URL extractor accepts non-local
http://URLs and exposes them asauthUrl/verificationUrl.Local callback/listener URLs are already filtered by hostname, but an external plaintext HTTP destination survives the same parser even though authentication instructions should not direct a user to an unencrypted remote endpoint.
Reproduction / evidence
Current upstream
mainat37bf87a692fc72d41f7312cc48808d699d204fbascans terminal output with:/https?:\/\/[^\s<>"']+/gand accepts the first parsed URL whose hostname is not local/loopback. There is no protocol check after
new URL(url).A deterministic process-boundary reproduction is a fake Codex login child that prints:
and exits successfully.
CodexLoginHandle.wait()then leaves:The existing authentication tests already demonstrate that local HTTP listener URLs should be ignored while a later HTTPS verification URL is retained.
Expected behavior
Remote authentication metadata should accept HTTPS only. HTTP loopback/listener lines may continue to be parsed and ignored, but an external plaintext HTTP URL must not become the URL presented to callers.
Root cause
preferredAuthUrl()validates hostname locality but not the parsed URL protocol. Because the initial regex admits both HTTP and HTTPS, any syntactically valid external HTTP URL passes.Suggested fix
After parsing each candidate URL, require
parsed.protocol === "https:"before accepting its hostname. Keep the existing loopback and local-host exclusions unchanged.Add a regression using a real child process that emits an external HTTP URL and a user code, then assert the login result does not expose that URL.
Impact
This is an authentication-boundary hardening/correctness issue. Codex Security does not itself navigate to the URL, but SDK/UI consumers can present
verificationUrlto a user. Accepting a plaintext remote destination makes terminal output capable of steering that user toward an unencrypted authentication endpoint.