Repository navigation
fix: fall back to the first trusted domain whatever its array key - #41894
openefaadmin wants to merge 1 commit into
Conversation
Request::getServerHost() returns $trustedList[0] for an untrusted Host header. config.php's trusted_domains is commonly edited by hand or via `occ config:system:delete trusted_domains 0`, leaving e.g. [2 => 'host']; index 0 is then missing, getServerHost() returns null with an "Undefined array key 0" warning, and callers expecting a string fail. Return the first configured entry (reset()) instead, cast to string. Adds testGetServerHostWithUntrustedDomainAndNonSequentialKeys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Scott Barbour <scott@efasecurity.com>
423a27c to
5322f88
Compare
| // first configured entry, whatever its key: after entries are removed | ||
| // from config.php the list can be e.g. [2 => 'host'], where | ||
| // $trustedList[0] would be null | ||
| return (string)\reset($trustedList); |
There was a problem hiding this comment.
Note: reset goes to the first element of the array in the order in which they were declared.
If someone does something weird, like setting the keys out of order then:
[2 => 'firsthost.example`, 1 => 'anotherhost.example', 0 => 'hostzero.example']
Then the old code would have returned hostzero.example and this new code will return firsthost.example
I don't think that matters.
|
Agreed - reset() takes the first entry as it is written in config.php,
which matches what admins expect from "the first trusted domain". With
keys out of order the old code also only worked by accident of key 0
existing. Thanks for the review.
|
oc-tmueller
left a comment
There was a problem hiding this comment.
Thanks, this fixes the sparse-list case. One behaviour change and a test gap inline.
Follow-up, not for this PR: the root cause is DeleteConfig::removeSubValue() (core/Command/Config/System/DeleteConfig.php:103), which unset()s the sub-key without renumbering. So after occ config:system:delete trusted_domains 0, every reader of the list sees [1 => …, 2 => …], not just getServerHost(). Renumbering list-shaped arrays there would cover all of them. Happy to have that as a separate PR.
| // first configured entry, whatever its key: after entries are removed | ||
| // from config.php the list can be e.g. [2 => 'host'], where | ||
| // $trustedList[0] would be null | ||
| return (string)\reset($trustedList); |
There was a problem hiding this comment.
reset() returns the first entry by position, not key 0, which changes the result when key 0 exists but isn't first. For example: occ config:system:delete trusted_domains 0, then occ config:system:set trusted_domains 0 --value=new.example.com. PHP appends the new key 0 at the end, so the list is [1 => 'old.example.com', 0 => 'new.example.com']. Before this PR the fallback was new.example.com; now it's old.example.com.
Keeping key 0 when it exists avoids that:
| return (string)\reset($trustedList); | |
| return (string)($trustedList[0] ?? \reset($trustedList)); |
| $this->assertSame('my.trusted.host', $request->getServerHost()); | ||
| } | ||
|
|
||
| public function testGetServerHostWithUntrustedDomainAndNonSequentialKeys() { |
There was a problem hiding this comment.
Could you add a case for key 0 present but not first, e.g. [1 => 'other.host', 0 => 'my.trusted.host'] expecting my.trusted.host? With [2 => …] alone, both reset() and [0] ?? reset() pass, so the ordering question above isn't pinned down.
Request::getServerHost() returns $trustedList[0] for an untrusted Host header.
config.php's trusted_domains is commonly edited by hand or via
occ config:system:delete trusted_domains 0, leaving e.g. [2 => 'host'];index 0 is then missing, getServerHost() returns null with an "Undefined array
key 0" warning, and callers expecting a string fail. Return the first
configured entry (reset()) instead, cast to string.
Adds testGetServerHostWithUntrustedDomainAndNonSequentialKeys.
How this was tested
New test
testGetServerHostWithUntrustedDomainAndNonSequentialKeyserrors without the fix and passes with it; RequestTest: 127 tests OK (PHP 8.4, on top of the PHP 8.4 nullable PR so the suite can boot).A changelog entry is included in
changelog/unreleased/; it linkspull/TBDand can be renamed to the PR number.