Skip to content

Commit 7e0de36

Browse files
authored
Merge pull request #780 from gwijnja/allow-172-and-ipv6-private
Allow 172.16.0.0/12 and IPv6 private ranges
2 parents e567fc8 + 71340c6 commit 7e0de36

File tree

2 files changed

+39
-20
lines changed

2 files changed

+39
-20
lines changed

src/ToolbarService.php

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -113,48 +113,63 @@ public function isEnabled()
113113
}
114114

115115
/**
116-
* Returns true if this applications is being executed on a domain with a TLD
117-
* that is commonly associated with a production environment.
116+
* Returns true if this application is being executed on a domain with a TLD
117+
* that is commonly associated with a production environment, or if the IP
118+
* address is not in a private or reserved range.
119+
*
120+
* Private IPv4 = 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16
121+
* Reserved IPv4 = 0.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8 and 240.0.0.0/4
122+
*
123+
* Private IPv6 = fc00::/7
124+
* Reserved IPv6 = ::1/128, ::/128, ::ffff:0:0/96 and fe80::/10
118125
*
119126
* @return bool
120127
*/
121128
protected function isSuspiciouslyProduction()
122129
{
123-
$url = parse_url('http://' . env('HTTP_HOST'), PHP_URL_HOST);
124-
if ($url === false) {
130+
$host = parse_url('http://' . env('HTTP_HOST'), PHP_URL_HOST);
131+
if ($host === false) {
125132
return false;
126133
}
127134

128-
$host = explode('.', $url);
129-
$first = current($host);
130-
$isIP = is_numeric(implode('', $host));
135+
// IPv6 addresses in URLs are enclosed in brackets. Remove them.
136+
$host = trim($host, '[]');
131137

132-
if (count($host) === 1) {
133-
return false;
138+
// Check if the host is a private or reserved IPv4/6 address.
139+
$isIp = filter_var($host, FILTER_VALIDATE_IP) !== false;
140+
if ($isIp) {
141+
$flags = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
142+
$isPublicIp = filter_var($host, FILTER_VALIDATE_IP, $flags) !== false;
143+
144+
return $isPublicIp;
134145
}
135146

136-
if ($isIP && in_array($first, ['192', '10', '127'])) {
137-
// Accessing the app by private IP, this is safe
147+
// So it's not an IP address. It must be a domain name.
148+
$parts = explode('.', $host);
149+
if (count($parts) == 1) {
138150
return false;
139151
}
140152

141-
$tld = end($host);
142-
$safeTopLevelDomains = ['localhost', 'invalid', 'test', 'example', 'local'];
143-
$safeTopLevelDomains = array_merge($safeTopLevelDomains, (array)$this->getConfig('safeTld'));
153+
// Check if the TLD is in the list of safe TLDs.
154+
$tld = end($parts);
155+
$safeTlds = ['localhost', 'invalid', 'test', 'example', 'local'];
156+
$safeTlds = array_merge($safeTlds, (array)$this->getConfig('safeTld'));
157+
158+
if (in_array($tld, $safeTlds, true)) {
159+
return false;
160+
}
144161

145-
if (!in_array($tld, $safeTopLevelDomains, true) && !$this->getConfig('forceEnable')) {
146-
$host = implode('.', $host);
147-
$safeList = implode(', ', $safeTopLevelDomains);
162+
// Don't log a warning if forceEnable is set.
163+
if (!$this->getConfig('forceEnable')) {
164+
$safeList = implode(', ', $safeTlds);
148165
Log::warning(
149166
"DebugKit is disabling itself as your host `{$host}` " .
150167
"is not in the known safe list of top-level-domains ({$safeList}). " .
151168
'If you would like to force DebugKit on use the `DebugKit.forceEnable` Configure option.'
152169
);
153-
154-
return true;
155170
}
156171

157-
return false;
172+
return true;
158173
}
159174

160175
/**

tests/TestCase/ToolbarServiceTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,12 @@ public function domainsProvider()
398398
['myapp.com', false],
399399
['myapp.io', false],
400400
['myapp.net', false],
401+
['172.18.0.10', true],
401402
['172.112.34.2', false],
402403
['6.112.34.2', false],
404+
['[abcd::]', false], // public
405+
['[fc00::]', true], // private
406+
['[::1]', true], // localhost
403407
];
404408
}
405409

0 commit comments

Comments
 (0)