Skip to content

Commit

Permalink
Unescape shell literal if it's not a placeholder (#717)
Browse files Browse the repository at this point in the history
Prompt messages are unquoted which requires them to be valid shell. Any
values not quoted become prompt messages and are exclusively for human
consumption. This is why we're removing backslashes from any form of
parentheses.

Fixes #709.
  • Loading branch information
sourishkrout authored Dec 17, 2024
1 parent 69760fe commit e462959
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
19 changes: 18 additions & 1 deletion internal/command/program_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,12 @@ func (r *ProgramResolver) findOriginalValue(decl *syntax.DeclClause) (string, bo
return true
})

return strings.Join(fragments, " "), isPlaceholder
v := strings.Join(fragments, " ")
if !isPlaceholder {
v = unescapeShellLiteral(v)
}

return v, isPlaceholder
}

func (r *ProgramResolver) findEnvValue(name string) (string, bool) {
Expand Down Expand Up @@ -378,3 +383,15 @@ func (r *ProgramResolver) hasExpr(node syntax.Node) (found bool) {
})
return
}

func unescapeShellLiteral(escaped string) string {
replacer := strings.NewReplacer(
`\(`, `(`,
`\)`, `)`,
`\{`, `{`,
`\}`, `}`,
`\[`, `[`,
`\]`, `]`,
)
return replacer.Replace(escaped)
}
24 changes: 24 additions & 0 deletions internal/command/program_resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,21 @@ func TestProgramResolverResolve(t *testing.T) {
},
modifiedProgram: "#\n# TEST_STRING_SGL_QUOTED_VALUE set in managed env store\n# \"export TEST_STRING_SGL_QUOTED_VALUE='value'\"\n\n",
},
{
name: "shell-escaped prompt message",
program: `export TYPE=[Guest type \(hyperv,proxmox,openstack\)]`,
result: &ProgramResolverResult{
ModifiedProgram: true,
Variables: []ProgramResolverVarResult{
{
Status: ProgramResolverStatusUnresolvedWithMessage,
Name: "TYPE",
OriginalValue: "[Guest type (hyperv,proxmox,openstack)]",
},
},
},
modifiedProgram: "#\n# TYPE set in managed env store\n# \"export TYPE=[Guest type \\\\(hyperv,proxmox,openstack\\\\)]\"\n\n",
},
{
name: "parameter expression",
program: `export TEST_PARAM_EXPR=${TEST:7:0}`,
Expand Down Expand Up @@ -315,3 +330,12 @@ func TestProgramResolverResolve_SensitiveEnvKeys(t *testing.T) {
require.EqualValues(t, "#\n# MY_PASSWORD set in managed env store\n# \"export MY_PASSWORD=super-secret\"\n#\n# MY_SECRET set in managed env store\n# \"export MY_SECRET=also-secret\"\n#\n# MY_PLAIN set in managed env store\n# \"export MY_PLAIN=text\"\n\n", buf.String())
})
}

func TestUnescapeShellLiteral(t *testing.T) {
assert.Equal(t, `echo "Hello World!"`, unescapeShellLiteral(`echo "Hello World!"`))
assert.Equal(t, `echo "Hello ${name}!"`, unescapeShellLiteral(`echo "Hello ${name}!"`))
assert.Equal(t, `[Guest type (hyperv,proxmox,openstack)]`, unescapeShellLiteral(`[Guest type \(hyperv,proxmox,openstack\)]`))
assert.Equal(t, `[IP of waiting server {foo}]`, unescapeShellLiteral(`[IP of waiting server \{foo\}]`))
assert.Equal(t, `[Guest\ Type]`, unescapeShellLiteral(`[Guest\ Type]`))
assert.Equal(t, `[Guest Type]`, unescapeShellLiteral(`\[Guest Type\]`))
}

0 comments on commit e462959

Please sign in to comment.