Skip to content

Commit 19511aa

Browse files
authored
Escape and enclose containerEnv in quotes when writing to Dockerfile (#454)
1 parent 1380704 commit 19511aa

4 files changed

Lines changed: 33 additions & 8 deletions

File tree

src/spec-node/imageMetadata.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,9 @@ export function getContainerEnvMetadata(containerEnv: Record<string, string> | u
489489
if (!containerEnv) {
490490
return '';
491491
}
492-
493492
const keys = Object.keys(containerEnv);
494-
const concatenatedEnv = keys.map(k => `ENV ${k}=${containerEnv![k]}`).join('\n');
495-
return concatenatedEnv;
493+
// https://docs.docker.com/engine/reference/builder/#envs
494+
return keys.map(k => `ENV ${k}="${containerEnv[k]
495+
.replace(/(?=["\\$])/g, '\\') // escape double quotes, back slash, and dollar sign
496+
}"`).join('\n');
496497
}

src/test/cli.build.test.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,20 @@ describe('Dev Containers CLI', function () {
232232
const containerId: string = resRun.stdout.split('\n')[0];
233233
assert.ok(containerId, 'Container id not found.');
234234

235-
const result = await shellExec(`docker exec ${containerId} bash -c 'echo $JAVA_HOME'`);
236-
assert.equal('/usr/lib/jvm/msopenjdk-current\n', result.stdout);
235+
const expectedContainerEnv = {
236+
'JAVA_HOME': '/usr/lib/jvm/msopenjdk-current',
237+
'VAR_WITH_SPACES': 'value with spaces',
238+
'VAR_WITH_LOTS_OF_SPACES': ' value with lots of spaces. ',
239+
'VAR_WITH_QUOTES_WE_WANT_TO_KEEP': 'value with "quotes" we want to keep',
240+
'VAR_WITH_DOLLAR_SIGN': 'value with $dollar sign',
241+
'VAR_WITH_BACK_SLASH': 'value with \\back slash',
242+
'ENV_WITH_COMMAND': 'bash -c \'echo -n "Hello, World!"\''
243+
};
244+
245+
for (const [key, value] of Object.entries(expectedContainerEnv)) {
246+
const result = await shellExec(`docker exec ${containerId} bash -c 'echo $${key}'`);
247+
assert.equal(result.stdout, `${value.trim()}\n`);
248+
}
237249

238250
await shellExec(`docker rm -f ${containerId}`);
239251
});

src/test/cli.up.test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,14 @@ describe('Dev Containers CLI', function () {
173173
const containerId: string = response.containerId;
174174
assert.ok(containerId, 'Container id not found.');
175175

176-
const result = await shellExec(`docker exec ${containerId} bash -c 'echo $JAVA_HOME'`);
177-
assert.equal('/usr/lib/jvm/msopenjdk-current\n', result.stdout);
176+
const javaHome = await shellExec(`docker exec ${containerId} bash -c 'echo -n $JAVA_HOME'`);
177+
assert.equal('/usr/lib/jvm/msopenjdk-current', javaHome.stdout);
178+
179+
const envWithSpaces = await shellExec(`docker exec ${containerId} bash -c 'echo -n $VAR_WITH_SPACES'`);
180+
assert.equal('value with spaces', envWithSpaces.stdout);
181+
182+
const evalEnvWithCommand = await shellExec(`docker exec ${containerId} bash -c 'eval $ENV_WITH_COMMAND'`);
183+
assert.equal('Hello, World!', evalEnvWithCommand.stdout);
178184

179185
await shellExec(`docker rm -f ${containerId}`);
180186
});

src/test/configs/image-metadata-containerEnv/.devcontainer/devcontainer.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
}
77
},
88
"containerEnv": {
9-
"JAVA_HOME": "/usr/lib/jvm/msopenjdk-current"
9+
"JAVA_HOME": "/usr/lib/jvm/msopenjdk-current",
10+
"VAR_WITH_SPACES": "value with spaces",
11+
"VAR_WITH_LOTS_OF_SPACES": " value with lots of spaces. ",
12+
"VAR_WITH_QUOTES_WE_WANT_TO_KEEP": "value with \"quotes\" we want to keep",
13+
"VAR_WITH_DOLLAR_SIGN": "value with $dollar sign",
14+
"VAR_WITH_BACK_SLASH": "value with \\back slash",
15+
"ENV_WITH_COMMAND": "bash -c 'echo -n \"Hello, World!\"'"
1016
}
1117
}

0 commit comments

Comments
 (0)