Skip to content

Commit c37c5ca

Browse files
authored
k8s: handle $ symbols in environment variable names and values (#74)
* Add test cases * Handle $ symbols in environment variable names and values
1 parent 04b58be commit c37c5ca

File tree

3 files changed

+108
-3
lines changed

3 files changed

+108
-3
lines changed

packages/k8s/src/k8s/utils.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,21 @@ export function writeEntryPointScript(
111111
if (environmentVariables && Object.entries(environmentVariables).length) {
112112
const envBuffer: string[] = []
113113
for (const [key, value] of Object.entries(environmentVariables)) {
114-
if (key.includes(`=`) || key.includes(`'`) || key.includes(`"`)) {
114+
if (
115+
key.includes(`=`) ||
116+
key.includes(`'`) ||
117+
key.includes(`"`) ||
118+
key.includes(`$`)
119+
) {
115120
throw new Error(
116-
`environment key ${key} is invalid - the key must not contain =, ' or "`
121+
`environment key ${key} is invalid - the key must not contain =, $, ', or "`
117122
)
118123
}
119124
envBuffer.push(
120-
`"${key}=${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`
125+
`"${key}=${value
126+
.replace(/\\/g, '\\\\')
127+
.replace(/"/g, '\\"')
128+
.replace(/\$/g, '\\$')}"`
121129
)
122130
}
123131
environmentPrefix = `env ${envBuffer.join(' ')} `

packages/k8s/tests/k8s-utils-test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,81 @@ describe('k8s utils', () => {
4949
).toThrow()
5050
})
5151

52+
it('should throw if environment variable name contains double quote', () => {
53+
expect(() =>
54+
writeEntryPointScript(
55+
'/test',
56+
'sh',
57+
['-e', 'script.sh'],
58+
['/prepend/path'],
59+
{
60+
'SOME"_ENV': 'SOME_VALUE'
61+
}
62+
)
63+
).toThrow()
64+
})
65+
66+
it('should throw if environment variable name contains =', () => {
67+
expect(() =>
68+
writeEntryPointScript(
69+
'/test',
70+
'sh',
71+
['-e', 'script.sh'],
72+
['/prepend/path'],
73+
{
74+
'SOME=ENV': 'SOME_VALUE'
75+
}
76+
)
77+
).toThrow()
78+
})
79+
80+
it('should throw if environment variable name contains single quote', () => {
81+
expect(() =>
82+
writeEntryPointScript(
83+
'/test',
84+
'sh',
85+
['-e', 'script.sh'],
86+
['/prepend/path'],
87+
{
88+
"SOME'_ENV": 'SOME_VALUE'
89+
}
90+
)
91+
).toThrow()
92+
})
93+
94+
it('should throw if environment variable name contains dollar', () => {
95+
expect(() =>
96+
writeEntryPointScript(
97+
'/test',
98+
'sh',
99+
['-e', 'script.sh'],
100+
['/prepend/path'],
101+
{
102+
SOME_$_ENV: 'SOME_VALUE'
103+
}
104+
)
105+
).toThrow()
106+
})
107+
108+
it('should escape double quote, dollar and backslash in environment variable values', () => {
109+
const { runnerPath } = writeEntryPointScript(
110+
'/test',
111+
'sh',
112+
['-e', 'script.sh'],
113+
['/prepend/path'],
114+
{
115+
DQUOTE: '"',
116+
BACK_SLASH: '\\',
117+
DOLLAR: '$'
118+
}
119+
)
120+
expect(fs.existsSync(runnerPath)).toBe(true)
121+
const script = fs.readFileSync(runnerPath, 'utf8')
122+
expect(script).toContain('"DQUOTE=\\"')
123+
expect(script).toContain('"BACK_SLASH=\\\\"')
124+
expect(script).toContain('"DOLLAR=\\$"')
125+
})
126+
52127
it('should return object with containerPath and runnerPath', () => {
53128
const { containerPath, runnerPath } = writeEntryPointScript(
54129
'/test',

packages/k8s/tests/run-script-step-test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,28 @@ describe('Run script step', () => {
8989
).resolves.not.toThrow()
9090
})
9191

92+
it('Dollar symbols in environment variables should not be expanded', async () => {
93+
runScriptStepDefinition.args.environmentVariables = {
94+
VARIABLE1: '$VAR',
95+
VARIABLE2: '${VAR}',
96+
VARIABLE3: '$(VAR)'
97+
}
98+
runScriptStepDefinition.args.entryPointArgs = [
99+
'-c',
100+
'\'if [[ -z "$VARIABLE1" ]]; then exit 1; fi\'',
101+
'\'if [[ -z "$VARIABLE2" ]]; then exit 2; fi\'',
102+
'\'if [[ -z "$VARIABLE3" ]]; then exit 3; fi\''
103+
]
104+
105+
await expect(
106+
runScriptStep(
107+
runScriptStepDefinition.args,
108+
prepareJobOutputData.state,
109+
null
110+
)
111+
).resolves.not.toThrow()
112+
})
113+
92114
it('Should have path variable changed in container with prepend path string array', async () => {
93115
runScriptStepDefinition.args.prependPath = ['/some/other/path']
94116
runScriptStepDefinition.args.entryPoint = '/bin/bash'

0 commit comments

Comments
 (0)