feat: allow safe environment variable defaults in array-format volumes
Changes:
- Extended validateDockerComposeForInjection to recognize env vars with defaults
- Added pattern check for ${VAR:-default} format alongside simple ${VAR} check
- Maintains consistency with parseDockerVolumeString behavior for string format
Test coverage:
- Added test for safe environment variable defaults in array format
- Verifies ${DATA_PATH:-./data} is allowed in array-format volumes
- All 79 security tests pass (215 assertions)
This allows users to specify environment variables with safe default values
in array-format Docker Compose volumes, matching the behavior already
supported in string-format volumes.
This commit is contained in:
parent
728f261316
commit
97868c3264
2 changed files with 27 additions and 1 deletions
|
|
@ -59,8 +59,11 @@ function validateDockerComposeForInjection(string $composeYaml): void
|
||||||
if (isset($volume['source'])) {
|
if (isset($volume['source'])) {
|
||||||
$source = $volume['source'];
|
$source = $volume['source'];
|
||||||
if (is_string($source)) {
|
if (is_string($source)) {
|
||||||
|
// Allow simple env vars and env vars with defaults (validated in parseDockerVolumeString)
|
||||||
$isSimpleEnvVar = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/', $source);
|
$isSimpleEnvVar = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/', $source);
|
||||||
if (! $isSimpleEnvVar) {
|
$isEnvVarWithDefault = preg_match('/^\$\{[^}]+:-[^}]*\}$/', $source);
|
||||||
|
|
||||||
|
if (! $isSimpleEnvVar && ! $isEnvVarWithDefault) {
|
||||||
try {
|
try {
|
||||||
validateShellSafePath($source, 'volume source');
|
validateShellSafePath($source, 'volume source');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,29 @@
|
||||||
expect($isSimpleEnvVar)->toBe(1); // preg_match returns 1 on success, not true
|
expect($isSimpleEnvVar)->toBe(1); // preg_match returns 1 on success, not true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('array-format with safe environment variable default', function () {
|
||||||
|
$dockerComposeYaml = <<<'YAML'
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: nginx
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: '${DATA_PATH:-./data}'
|
||||||
|
target: /app/data
|
||||||
|
YAML;
|
||||||
|
|
||||||
|
$parsed = Yaml::parse($dockerComposeYaml);
|
||||||
|
$source = $parsed['services']['web']['volumes'][0]['source'];
|
||||||
|
|
||||||
|
// Parse correctly extracts the source value
|
||||||
|
expect($source)->toBe('${DATA_PATH:-./data}');
|
||||||
|
|
||||||
|
// Safe environment variable with benign default should be allowed
|
||||||
|
// The pre-save validation skips env vars with safe defaults
|
||||||
|
expect(fn () => validateDockerComposeForInjection($dockerComposeYaml))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
test('array-format with malicious environment variable default', function () {
|
test('array-format with malicious environment variable default', function () {
|
||||||
$dockerComposeYaml = <<<'YAML'
|
$dockerComposeYaml = <<<'YAML'
|
||||||
services:
|
services:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue