From 715035e9dad9c5ff09c09c89fba4b5b6c32827b1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 14 Jan 2026 18:07:42 +0000 Subject: [PATCH 1/2] Initial plan From 009d388986e07de89645a3a7b3c84bdd5a0522a6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 14 Jan 2026 18:10:39 +0000 Subject: [PATCH 2/2] Fix isSafeRedirectUrl host comparison for non-default ports - Strip port from getRealHost() before comparing with URI.getHost() - Add test cases for non-default port scenarios - Fixes issue where valid same-host redirects were rejected during dev Co-authored-by: lmajano <137111+lmajano@users.noreply.github.com> --- interceptors/Security.cfc | 4 ++- .../tests/specs/unit/SecurityTest.cfc | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/interceptors/Security.cfc b/interceptors/Security.cfc index 897fe3f..803ee3b 100644 --- a/interceptors/Security.cfc +++ b/interceptors/Security.cfc @@ -827,7 +827,9 @@ component accessors="true" extends="coldbox.system.Interceptor" { } // Get the current request's host for comparison - var currentHost = variables.cbSecurity.getRealHost(); + // Normalize host: urlToValidate.getHost() does not include port + // Strip port from .getRealHost() for compare + var currentHost = listFirst( variables.cbSecurity.getRealHost(), ":" ); // Compare hosts (case-insensitive) return compareNoCase( urlToValidate.getHost(), currentHost ) == 0; diff --git a/test-harness/tests/specs/unit/SecurityTest.cfc b/test-harness/tests/specs/unit/SecurityTest.cfc index d09fe80..37f0a81 100755 --- a/test-harness/tests/specs/unit/SecurityTest.cfc +++ b/test-harness/tests/specs/unit/SecurityTest.cfc @@ -342,6 +342,39 @@ component extends="coldbox.system.testing.BaseInterceptorTest" interceptor="cbse expect( result ).toBeTrue(); } ); + it( "allows URLs with non-default ports when host matches", () => { + // Simulate getRealHost returning host with port (e.g., during dev) + mockSecurityService.$( "getRealHost", "127.0.0.1:61910" ); + + var result = security.isSafeRedirectUrl( + targetUrl = "http://127.0.0.1:61910/account", + event = mockEvent + ); + expect( result ).toBeTrue(); + } ); + + it( "allows URLs with different ports when host matches", () => { + // getRealHost returns host with port + mockSecurityService.$( "getRealHost", "mysite.com:8080" ); + + // URL has a different port, but same host + var result = security.isSafeRedirectUrl( + targetUrl = "https://mysite.com:9000/account", + event = mockEvent + ); + expect( result ).toBeTrue(); + } ); + + it( "blocks URLs with different hosts even with same port", () => { + mockSecurityService.$( "getRealHost", "mysite.com:8080" ); + + var result = security.isSafeRedirectUrl( + targetUrl = "https://malicious.com:8080/phishing", + event = mockEvent + ); + expect( result ).toBeFalse(); + } ); + it( "handles invalid URLs gracefully", () => { var result = security.isSafeRedirectUrl( targetUrl = "not a valid url://", event = mockEvent ); expect( result ).toBeFalse();