SettingSecrecy
in package
Defines in one place which setting keys must never reach a browser response.
IMPORTANT: this is neither authorization nor the main filter. The authority is the column
cms_system_settings.is_public (fail-closed, default 0) and above it
SettingManager::getAllPublic(). The pattern here is
a second, independent layer for places that work with an already merged map without the
flag, typically the Latte variable $settings
(SettingInitTrait), which is also filled in the
Admin, Api and Cron contexts where the map legitimately holds secrets.
SettingPublicExposureTest keeps the two layers independent: it checks both the pattern and a named list of ten known secrets.
Table of Contents
Constants
- CREDENTIAL_KEY_PATTERN : string = '~(secret|password|token|salt|credential|smtp)~i'
- Wider pattern for places that decide without the `is_public` flag; the only such place is the migration shim in {@see \App\UI\Api\System\Models\Managers\SettingManager}.
- SECRET_KEY_PATTERN : string = '~(secret|password|token|salt|credential)~i'
- Matches keys that must never reach a browser, not even by mistake or temporarily.
Methods
- isCredentialKey() : bool
- Returns whether the key looks like part of credentials; see {@see self::CREDENTIAL_KEY_PATTERN}.
- isSecretKey() : bool
- stripSecrets() : array<int|string, mixed>
- Removes every secret-looking key from a `module => key => value` map.
Constants
CREDENTIAL_KEY_PATTERN
Wider pattern for places that decide without the `is_public` flag; the only such place is the migration shim in {@see \App\UI\Api\System\Models\Managers\SettingManager}.
public
string
CREDENTIAL_KEY_PATTERN
= '~(secret|password|token|salt|credential|smtp)~i'
Unlike self::SECRET_KEY_PATTERN it also matches smtp: email.smtp.host and
email.smtp.username have no "secret" in the name but belong to the same credentials as
email.smtp.password, and SettingPublicExposureTest caught
the shim on exactly these.
IMPORTANT: do not widen the narrower pattern the same way. It is a contract used by the
test and by self::stripSecrets(); with smtp added there, a guarded name could no
longer be told apart from a deliberately wider heuristic.
SECRET_KEY_PATTERN
Matches keys that must never reach a browser, not even by mistake or temporarily.
public
string
SECRET_KEY_PATTERN
= '~(secret|password|token|salt|credential)~i'
Covers email.smtp.password, cron.token, *LoginClientSecret and
googleReCaptchaSecretKey.
Methods
isCredentialKey()
Returns whether the key looks like part of credentials; see {@see self::CREDENTIAL_KEY_PATTERN}.
public
static isCredentialKey(string $key) : bool
Parameters
- $key : string
Return values
boolisSecretKey()
public
static isSecretKey(string $key) : bool
Parameters
- $key : string
Return values
boolstripSecrets()
Removes every secret-looking key from a `module => key => value` map.
public
static stripSecrets(array<int|string, mixed> $settings) : array<int|string, mixed>
The structure stays; only the offending keys disappear.
Parameters
- $settings : array<int|string, mixed>