Skip to content

Commit 9f94cd1

Browse files
authored
Merge pull request #673 from ColdBox/copilot/coldbox-1406-fix-method-spoofing
fix(COLDBOX-1406): restrict HTTP method spoofing to POST requests only
2 parents 2d1f983 + 70fc3f7 commit 9f94cd1

2 files changed

Lines changed: 78 additions & 2 deletions

File tree

system/web/context/RequestContext.cfc

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,10 +1799,34 @@ component serializable="false" accessors="true" {
17991799
}
18001800

18011801
/**
1802-
* Get the HTTP Request Method Type
1802+
* Get the original (transport-level) HTTP Request Method Type, ignoring any _method override.
1803+
*/
1804+
string function getOriginalHTTPMethod(){
1805+
return uCase( CGI.REQUEST_METHOD );
1806+
}
1807+
1808+
/**
1809+
* Get the effective HTTP Request Method Type.
1810+
* Method spoofing via the _method parameter is only honored when the original
1811+
* transport-level request method is POST, and only for PUT, PATCH, and DELETE overrides.
1812+
* This prevents GET requests from spoofing destructive HTTP methods.
18031813
*/
18041814
string function getHTTPMethod(){
1805-
return getValue( "_method", CGI.REQUEST_METHOD );
1815+
var originalMethod = getOriginalHTTPMethod();
1816+
1817+
// Only honor _method override on POST requests
1818+
if ( originalMethod != "POST" ) {
1819+
return originalMethod;
1820+
}
1821+
1822+
var overriddenMethod = uCase( trim( getValue( "_method", "" ) ) );
1823+
1824+
// Only allow overriding to PUT, PATCH, or DELETE from POST
1825+
if ( listFindNoCase( "PUT,PATCH,DELETE", overriddenMethod ) ) {
1826+
return overriddenMethod;
1827+
}
1828+
1829+
return originalMethod;
18061830
}
18071831

18081832
/**

tests/specs/web/context/RequestContextTest.cfc

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,4 +856,56 @@ component extends="coldbox.system.testing.BaseModelTest" {
856856
expect( event.getSesBaseUrl() ).toInclude( event.getSESBasePath() );
857857
}
858858

859+
/**
860+
* Tests for method spoofing security fix (COLDBOX-1406).
861+
* _method override should only be honored when the original request is POST.
862+
*/
863+
function testGetHTTPMethodNoOverrideOnGET(){
864+
var event = getRequestContext().$( "getOriginalHTTPMethod", "GET" );
865+
event.setValue( "_method", "DELETE" );
866+
expect( event.getHTTPMethod() ).toBe( "GET" );
867+
}
868+
869+
function testGetHTTPMethodNoOverrideOnHEAD(){
870+
var event = getRequestContext().$( "getOriginalHTTPMethod", "HEAD" );
871+
event.setValue( "_method", "DELETE" );
872+
expect( event.getHTTPMethod() ).toBe( "HEAD" );
873+
}
874+
875+
function testGetHTTPMethodNoOverrideOnPUT(){
876+
var event = getRequestContext().$( "getOriginalHTTPMethod", "PUT" );
877+
event.setValue( "_method", "DELETE" );
878+
expect( event.getHTTPMethod() ).toBe( "PUT" );
879+
}
880+
881+
function testGetHTTPMethodPostDeleteOverride(){
882+
var event = getRequestContext().$( "getOriginalHTTPMethod", "POST" );
883+
event.setValue( "_method", "DELETE" );
884+
expect( event.getHTTPMethod() ).toBe( "DELETE" );
885+
}
886+
887+
function testGetHTTPMethodPostPutOverride(){
888+
var event = getRequestContext().$( "getOriginalHTTPMethod", "POST" );
889+
event.setValue( "_method", "PUT" );
890+
expect( event.getHTTPMethod() ).toBe( "PUT" );
891+
}
892+
893+
function testGetHTTPMethodPostPatchOverride(){
894+
var event = getRequestContext().$( "getOriginalHTTPMethod", "POST" );
895+
event.setValue( "_method", "PATCH" );
896+
expect( event.getHTTPMethod() ).toBe( "PATCH" );
897+
}
898+
899+
function testGetHTTPMethodPostWithNoOverride(){
900+
var event = getRequestContext().$( "getOriginalHTTPMethod", "POST" );
901+
expect( event.getHTTPMethod() ).toBe( "POST" );
902+
}
903+
904+
function testGetHTTPMethodPostGetOverrideIgnored(){
905+
// POST _method=GET should not be honored; result stays POST
906+
var event = getRequestContext().$( "getOriginalHTTPMethod", "POST" );
907+
event.setValue( "_method", "GET" );
908+
expect( event.getHTTPMethod() ).toBe( "POST" );
909+
}
910+
859911
}

0 commit comments

Comments
 (0)