@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorSecurityConfigOptions
4 extends PhabricatorApplicationConfigOptions {
5
6 public function getName() {
7 return pht('Security');
8 }
9
10 public function getDescription() {
11 return pht('Security options.');
12 }
13
14 public function getIcon() {
15 return 'fa-lock';
16 }
17
18 public function getGroup() {
19 return 'core';
20 }
21
22 public function getOptions() {
23 $doc_href = PhabricatorEnv::getDoclink('Configuring a File Domain');
24 $doc_name = pht('Configuration Guide: Configuring a File Domain');
25
26 $default_address_blacklist = array(
27 // This is all of the IANA special/reserved blocks in IPv4 space.
28 '0.0.0.0/8',
29 '10.0.0.0/8',
30 '100.64.0.0/10',
31 '127.0.0.0/8',
32 '169.254.0.0/16',
33 '172.16.0.0/12',
34 '192.0.0.0/24',
35 '192.0.2.0/24',
36 '192.88.99.0/24',
37 '192.168.0.0/16',
38 '198.18.0.0/15',
39 '198.51.100.0/24',
40 '203.0.113.0/24',
41 '224.0.0.0/4',
42 '240.0.0.0/4',
43 '255.255.255.255/32',
44
45 // And these are the IANA special/reserved blocks in IPv6 space.
46 '::/128',
47 '::1/128',
48 '::ffff:0:0/96',
49 '100::/64',
50 '64:ff9b::/96',
51 '2001::/32',
52 '2001:10::/28',
53 '2001:20::/28',
54 '2001:db8::/32',
55 '2002::/16',
56 'fc00::/7',
57 'fe80::/10',
58 'ff00::/8',
59 );
60
61 $keyring_type = 'custom:PhabricatorKeyringConfigOptionType';
62 $keyring_description = $this->deformat(pht(<<<EOTEXT
63The keyring stores master encryption keys. For help with configuring a keyring
64and encryption, see **[[ %s | Configuring Encryption ]]**.
65EOTEXT
66 ,
67 PhabricatorEnv::getDoclink('Configuring Encryption')));
68
69 $require_mfa_description = $this->deformat(pht(<<<EOTEXT
70By default, this software allows users to add multi-factor authentication to
71their accounts, but does not require it. By enabling this option, you can
72force all users to add at least one authentication factor before they can use
73their accounts.
74
75Administrators can query a list of users who do not have MFA configured in
76{nav People}:
77
78 - **[[ %s | %s ]]**
79EOTEXT
80 ,
81 '/people/?mfa=false',
82 pht('List of Users Without MFA')));
83
84 return array(
85 $this->newOption('security.alternate-file-domain', 'string', null)
86 ->setLocked(true)
87 ->setSummary(pht('Alternate domain to serve files from.'))
88 ->setDescription(
89 pht(
90 'By default, this software serves files from the same domain '.
91 'the application is served from. This is convenient, but '.
92 'presents a security risk.'.
93 "\n\n".
94 'You should configure a CDN or alternate file domain to mitigate '.
95 'this risk. Configuring a CDN will also improve performance. See '.
96 '[[ %s | %s ]] for instructions.',
97 $doc_href,
98 $doc_name))
99 ->addExample('https://files.phabcdn.net/', pht('Valid Setting')),
100 $this->newOption(
101 'security.hmac-key',
102 'string',
103 '[D\t~Y7eNmnQGJ;rnH6aF;m2!vJ8@v8C=Cs:aQS\.Qw')
104 ->setHidden(true)
105 ->setSummary(
106 pht('Key for HMAC digests.'))
107 ->setDescription(
108 pht(
109 'Default key for HMAC digests where the key is not important '.
110 '(i.e., the hash itself is secret). You can change this if you '.
111 'want (to any other string), but doing so will break existing '.
112 'sessions and CSRF tokens. This option is deprecated. Newer '.
113 'code automatically manages HMAC keys.')),
114 $this->newOption('security.require-https', 'bool', false)
115 ->setLocked(true)
116 ->setSummary(
117 pht('Force users to connect via HTTPS instead of HTTP.'))
118 ->setDescription(
119 pht(
120 "If the web server responds to both HTTP and HTTPS requests but ".
121 "you want users to connect with only HTTPS, you can set this ".
122 "to `true` to make this service redirect HTTP requests to HTTPS.".
123 "\n\n".
124 "Normally, you should just configure your server not to accept ".
125 "HTTP traffic, but this setting may be useful if you originally ".
126 "used HTTP and have now switched to HTTPS but don't want to ".
127 "break old links, or if your webserver sits behind a load ".
128 "balancer which terminates HTTPS connections and you can not ".
129 "reasonably configure more granular behavior there.".
130 "\n\n".
131 "IMPORTANT: A request is identified as HTTP or HTTPS by examining ".
132 "the PHP `%s` variable. If you run Apache/mod_php this will ".
133 "probably be set correctly for you automatically, but if you run ".
134 "as CGI/FCGI (e.g., through nginx or lighttpd), you need to ".
135 "configure your web server so that it passes the value correctly ".
136 "based on the connection type.".
137 "\n\n".
138 "If you configure clustering, note that this ".
139 "setting is ignored by intracluster requests.",
140 "\$_SERVER['HTTPS']"))
141 ->setBoolOptions(
142 array(
143 pht('Force HTTPS'),
144 pht('Allow HTTP'),
145 )),
146 $this->newOption('security.require-multi-factor-auth', 'bool', false)
147 ->setLocked(true)
148 ->setSummary(
149 pht('Require all users to configure multi-factor authentication.'))
150 ->setDescription($require_mfa_description)
151 ->setBoolOptions(
152 array(
153 pht('Multi-Factor Required'),
154 pht('Multi-Factor Optional'),
155 )),
156 $this->newOption(
157 'uri.allowed-protocols',
158 'set',
159 array(
160 'http' => true,
161 'https' => true,
162 'mailto' => true,
163 ))
164 ->setSummary(
165 pht(
166 'Determines which URI protocols are valid for links and '.
167 'redirects.'))
168 ->setDescription(
169 pht(
170 'When users write comments which have URIs, they will be '.
171 'automatically turned into clickable links if the URI protocol '.
172 'appears in this set.'.
173 "\n\n".
174 'This set of allowed protocols is primarily intended to prevent '.
175 'security issues with "javascript:" and other potentially '.
176 'dangerous URI handlers.'.
177 "\n\n".
178 'This set is also used to enforce valid redirect URIs. '.
179 'This service will refuse to issue a HTTP "Location" redirect '.
180 'to a URI with a protocol not on this set.'.
181 "\n\n".
182 'Usually, "http" and "https" should be present in this set. If '.
183 'you remove one or both protocols, some features which rely on '.
184 'links or redirects may not work.'))
185 ->addExample("http\nhttps", pht('Valid Setting'))
186 ->setLocked(true),
187 $this->newOption(
188 'uri.allowed-editor-protocols',
189 'set',
190 array(
191 'http' => true,
192 'https' => true,
193
194 // This handler is installed by Textmate.
195 'txmt' => true,
196
197 // This handler is for MacVim.
198 'mvim' => true,
199
200 // Unofficial handler for Vim.
201 'vim' => true,
202
203 // Unofficial handler for Sublime.
204 'subl' => true,
205
206 // Unofficial handler for Emacs.
207 'emacs' => true,
208
209 // This isn't a standard handler installed by an application, but
210 // is a reasonable name for a user-installed handler.
211 'editor' => true,
212
213 // This handler is for Visual Studio Code.
214 'vscode' => true,
215
216 // This is for IntelliJ IDEA.
217 'idea' => true,
218
219 // This handler is installed by the Zed Editor
220 'zed' => true,
221 ))
222 ->setSummary(pht('Whitelists editor protocols for "Open in Editor".'))
223 ->setDescription(
224 pht(
225 'Users can configure a URI pattern to open files in a text '.
226 'editor. The URI must use a protocol on this whitelist.'))
227 ->setLocked(true),
228 $this->newOption('remarkup.enable-embedded-youtube', 'bool', false)
229 ->setBoolOptions(
230 array(
231 pht('Embed YouTube videos'),
232 pht("Don't embed YouTube videos"),
233 ))
234 ->setSummary(
235 pht('Determines whether or not YouTube videos get embedded.'))
236 ->setDescription(
237 pht(
238 "If you enable this, linked YouTube videos will be embedded ".
239 "inline. This has mild security implications (you'll leak ".
240 "referrers to YouTube) and is pretty silly (but sort of ".
241 "awesome).")),
242 $this->newOption(
243 'security.outbound-blacklist',
244 'list<string>',
245 $default_address_blacklist)
246 ->setLocked(true)
247 ->setSummary(
248 pht(
249 'Blacklist subnets to prevent user-initiated outbound '.
250 'requests.'))
251 ->setDescription(
252 pht(
253 'Users can make requests to other services from '.
254 'service hosts in some circumstances (for example, by '.
255 'creating a repository with a remote URL).'.
256 "\n\n".
257 'This may represent a security vulnerability if services on '.
258 'the same subnet will accept commands or reveal private '.
259 'information over unauthenticated HTTP GET, based on the source '.
260 'IP address. In particular, all hosts in EC2 have access to '.
261 'such a service.'.
262 "\n\n".
263 'This option defines a list of netblocks which requests will '.
264 'never be issued to. Generally, you should list all '.
265 'private IP space here.'))
266 ->addExample(array('0.0.0.0/0'), pht('No Outbound Requests')),
267 $this->newOption('security.strict-transport-security', 'bool', false)
268 ->setLocked(true)
269 ->setBoolOptions(
270 array(
271 pht('Use HSTS'),
272 pht('Do Not Use HSTS'),
273 ))
274 ->setSummary(pht('Enable HTTP Strict Transport Security (HSTS).'))
275 ->setDescription(
276 pht(
277 'HTTP Strict Transport Security (HSTS) sends a header which '.
278 'instructs browsers that the site should only be accessed '.
279 'over HTTPS, never HTTP. This defuses an attack where an '.
280 'adversary gains access to your network, then proxies requests '.
281 'through an unsecured link.'.
282 "\n\n".
283 'Do not enable this option if you serve (or plan to ever serve) '.
284 'unsecured content over plain HTTP. It is very difficult to '.
285 'undo this change once users\' browsers have accepted the '.
286 'setting.')),
287 $this->newOption('keyring', $keyring_type, array())
288 ->setHidden(true)
289 ->setSummary(pht('Configure master encryption keys.'))
290 ->setDescription($keyring_description),
291 );
292 }
293
294 protected function didValidateOption(
295 PhabricatorConfigOption $option,
296 $value) {
297
298 $key = $option->getKey();
299 if ($key == 'security.alternate-file-domain') {
300
301 $uri = new PhutilURI($value);
302 $protocol = $uri->getProtocol();
303 if ($protocol !== 'http' && $protocol !== 'https') {
304 throw new PhabricatorConfigValidationException(
305 pht(
306 "Config option '%s' is invalid. The URI must start with ".
307 "'%s' or '%s'.",
308 $key,
309 'http://',
310 'https://'));
311 }
312
313 $domain = $uri->getDomain();
314 if (strpos($domain, '.') === false) {
315 throw new PhabricatorConfigValidationException(
316 pht(
317 "Config option '%s' is invalid. The URI must contain a dot ('.'), ".
318 "like '%s', not just a bare name like '%s'. ".
319 "Some web browsers will not set cookies on domains with no TLD.",
320 $key,
321 'http://example.com/',
322 'http://example/'));
323 }
324
325 $path = $uri->getPath();
326 if ($path !== '' && $path !== '/') {
327 throw new PhabricatorConfigValidationException(
328 pht(
329 "Config option '%s' is invalid. The URI must NOT have a path, ".
330 "e.g. '%s' is OK, but '%s' is not. This software must be ".
331 "installed on an entire domain; it can not be installed on a path.",
332 $key,
333 'http://devtools.example.com/',
334 'http://example.com/devtools/'));
335 }
336 }
337 }
338
339
340}