mirror of
https://github.com/projectsend/projectsend.git
synced 2026-09-16 16:45:07 +00:00
e187513cdd
`env()` recognises the words "true" and "false" and returns everything
else as the string it was — and every non-empty string is truthy in PHP.
So `(bool) env('PROJECTSEND_CAPTCHA_DISABLED')` read all of these as "yes,
disabled":
PROJECTSEND_CAPTCHA_DISABLED=no
PROJECTSEND_CAPTCHA_DISABLED=off
PROJECTSEND_CAPTCHA_DISABLED=fasle
An operator who meant to say no took the bot protection off their login
and registration forms and had nothing to tell them so — the setting
screen still shows the CAPTCHA configured, because this is the escape
hatch that runs ahead of it.
For most settings the cast is a shrug: somebody notices the feature is on
and fixes the line. It stops being a shrug when the wrong answer is the
unsafe one, and this is one of those. EnvFlag lists what counts as yes —
`true` and `1`, either case, either type — and reads everything else,
recognised or not, as no. A value typed as `disabled` turns nothing off:
a configuration mistake to be found rather than guessed at.
Found while fixing the same bug in a new cloud-modules flag, where the
unsafe direction was publishing a customer's files rather than dropping a
CAPTCHA. Two of the four remaining `(bool) env()` casts are left alone on
purpose: a wrong S3 path-style value breaks storage loudly, and the
migration tool's direct mode defaults to true anyway, so neither fails
into an unsafe state.
49 lines
1.6 KiB
PHP
49 lines
1.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Support\EnvFlag;
|
|
|
|
/**
|
|
* An on/off environment variable, read strictly.
|
|
*
|
|
* `env()` recognises the words `true` and `false` and returns everything
|
|
* else as the string it was — and every non-empty string is truthy in
|
|
* PHP. So a plain `(bool)` cast reads `no`, `off` and a typo as *on*.
|
|
* That is a shrug on most settings and not a shrug on the ones that
|
|
* switch a protection off, which is what this is for.
|
|
*/
|
|
test('only an explicit yes is true', function (mixed $value, bool $expected) {
|
|
expect(EnvFlag::isTrue($value))->toBe($expected);
|
|
})->with([
|
|
'true' => [true, true],
|
|
'"true"' => ['true', true],
|
|
'"TRUE"' => ['TRUE', true],
|
|
'padded' => [' true ', true],
|
|
'"1"' => ['1', true],
|
|
'1' => [1, true],
|
|
|
|
'false' => [false, false],
|
|
'"false"' => ['false', false],
|
|
'"0"' => ['0', false],
|
|
'0' => [0, false],
|
|
'null' => [null, false],
|
|
'empty' => ['', false],
|
|
// The values a cast gets backwards, which is the whole reason for this.
|
|
'"no"' => ['no', false],
|
|
'"off"' => ['off', false],
|
|
'"disabled"' => ['disabled', false],
|
|
'a typo' => ['ture', false],
|
|
// Nothing exotic counts either.
|
|
'an array' => [['true'], false],
|
|
'a float' => [1.0, false],
|
|
]);
|
|
|
|
test('a mistyped captcha flag leaves the captcha alone', function () {
|
|
// The flag this exists for. `PROJECTSEND_CAPTCHA_DISABLED=no` used to
|
|
// read as "yes, disabled" and take the bot protection off the login
|
|
// and registration forms without anybody asking for that.
|
|
expect(EnvFlag::isTrue('no'))->toBeFalse()
|
|
->and(config('projectsend.captcha.disabled'))->toBeFalse();
|
|
});
|