Skip to content

Commit cf59b55

Browse files
committed
Escape additional comment args.
Remove extra quoting and instead add a backslach to each character in the extra args before appending it to the command. ex. atlantis plan -- -var key=val will result in: sh -c "atlantis plan \-\v\a\r \k\e\y\=\v\a\l" Fixes #697.
1 parent dd02dea commit cf59b55

12 files changed

+324
-263
lines changed

server/events/comment_parser.go

+3-9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"regexp"
2222
"strings"
2323

24-
shlex "github.com/flynn-archive/go-shlex"
24+
"github.com/flynn-archive/go-shlex"
2525
"github.com/runatlantis/atlantis/server/events/models"
2626
"github.com/runatlantis/atlantis/server/events/yaml"
2727
"github.com/spf13/pflag"
@@ -162,7 +162,6 @@ func (e *CommentParser) Parse(comment string, vcsHost models.VCSHostType) Commen
162162
var dir string
163163
var project string
164164
var verbose bool
165-
var extraArgs []string
166165
var flagSet *pflag.FlagSet
167166
var name models.CommandName
168167

@@ -208,14 +207,9 @@ func (e *CommentParser) Parse(comment string, vcsHost models.VCSHostType) Commen
208207
return CommentParseResult{CommentResponse: e.errMarkdown(fmt.Sprintf("unknown argument(s) – %s", strings.Join(unusedArgs, " ")), command, flagSet)}
209208
}
210209

210+
var extraArgs []string
211211
if flagSet.ArgsLenAtDash() != -1 {
212-
extraArgsUnsafe := flagSet.Args()[flagSet.ArgsLenAtDash():]
213-
// Quote all extra args so there isn't a security issue when we append
214-
// them to the terraform commands, ex. "; cat /etc/passwd"
215-
for _, arg := range extraArgsUnsafe {
216-
quotesEscaped := strings.Replace(arg, `"`, `\"`, -1)
217-
extraArgs = append(extraArgs, fmt.Sprintf(`"%s"`, quotesEscaped))
218-
}
212+
extraArgs = flagSet.Args()[flagSet.ArgsLenAtDash():]
219213
}
220214

221215
dir, err = e.validateDir(dir)

server/events/comment_parser_test.go

+5-14
Original file line numberDiff line numberDiff line change
@@ -418,15 +418,15 @@ func TestParse_Parsing(t *testing.T) {
418418
"workspace",
419419
"dir",
420420
false,
421-
"\"--verbose\"",
421+
"--verbose",
422422
"",
423423
},
424424
{
425425
"-w workspace -- -d dir --verbose",
426426
"workspace",
427427
"",
428428
false,
429-
"\"-d\" \"dir\" \"--verbose\"",
429+
"-d dir --verbose",
430430
"",
431431
},
432432
// Test the extra args parsing.
@@ -438,21 +438,12 @@ func TestParse_Parsing(t *testing.T) {
438438
"",
439439
"",
440440
},
441-
// Test trying to escape quoting
442-
{
443-
"-- \";echo \"hi",
444-
"",
445-
"",
446-
false,
447-
`";echo hi"`,
448-
"",
449-
},
450441
{
451442
"-w workspace -d dir --verbose -- arg one -two --three &&",
452443
"workspace",
453444
"dir",
454445
true,
455-
"\"arg\" \"one\" \"-two\" \"--three\" \"&&\"",
446+
"arg one -two --three &&",
456447
"",
457448
},
458449
// Test whitespace.
@@ -461,15 +452,15 @@ func TestParse_Parsing(t *testing.T) {
461452
"workspace",
462453
"dir",
463454
true,
464-
"\"arg\" \"one\" \"-two\" \"--three\" \"&&\"",
455+
"arg one -two --three &&",
465456
"",
466457
},
467458
{
468459
" -w workspace -d dir --verbose -- arg one -two --three &&",
469460
"workspace",
470461
"dir",
471462
true,
472-
"\"arg\" \"one\" \"-two\" \"--three\" \"&&\"",
463+
"arg one -two --three &&",
473464
"",
474465
},
475466
// Test that the dir string is normalized.

server/events/models/models.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,11 @@ type ProjectCommandContext struct {
305305
AutoplanEnabled bool
306306
// BaseRepo is the repository that the pull request will be merged into.
307307
BaseRepo Repo
308-
// CommentArgs are the extra arguments appended to comment,
309-
// ex. atlantis plan -- -target=resource
310-
CommentArgs []string
308+
// EscapedCommentArgs are the extra arguments that were added to the atlantis
309+
// command, ex. atlantis plan -- -target=resource. We then escape them
310+
// by adding a \ before each character so that they can be used within
311+
// sh -c safely, i.e. sh -c "terraform plan $(touch bad)".
312+
EscapedCommentArgs []string
311313
// HeadRepo is the repository that is getting merged into the BaseRepo.
312314
// If the pull request branch is from the same repository then HeadRepo will
313315
// be the same as BaseRepo.

server/events/project_command_builder.go

+31-19
Original file line numberDiff line numberDiff line change
@@ -382,24 +382,36 @@ func (p *DefaultProjectCommandBuilder) buildCtx(ctx *CommandContext,
382382
}
383383

384384
return models.ProjectCommandContext{
385-
ApplyCmd: p.CommentBuilder.BuildApplyComment(projCfg.RepoRelDir, projCfg.Workspace, projCfg.Name),
386-
BaseRepo: ctx.BaseRepo,
387-
CommentArgs: commentArgs,
388-
AutomergeEnabled: automergeEnabled,
389-
AutoplanEnabled: projCfg.AutoplanEnabled,
390-
Steps: steps,
391-
HeadRepo: ctx.HeadRepo,
392-
Log: ctx.Log,
393-
PullMergeable: ctx.PullMergeable,
394-
Pull: ctx.Pull,
395-
ProjectName: projCfg.Name,
396-
ApplyRequirements: projCfg.ApplyRequirements,
397-
RePlanCmd: p.CommentBuilder.BuildPlanComment(projCfg.RepoRelDir, projCfg.Workspace, projCfg.Name, commentArgs),
398-
RepoRelDir: projCfg.RepoRelDir,
399-
RepoConfigVersion: projCfg.RepoCfgVersion,
400-
TerraformVersion: projCfg.TerraformVersion,
401-
User: ctx.User,
402-
Verbose: verbose,
403-
Workspace: projCfg.Workspace,
385+
ApplyCmd: p.CommentBuilder.BuildApplyComment(projCfg.RepoRelDir, projCfg.Workspace, projCfg.Name),
386+
BaseRepo: ctx.BaseRepo,
387+
EscapedCommentArgs: p.escapeArgs(commentArgs),
388+
AutomergeEnabled: automergeEnabled,
389+
AutoplanEnabled: projCfg.AutoplanEnabled,
390+
Steps: steps,
391+
HeadRepo: ctx.HeadRepo,
392+
Log: ctx.Log,
393+
PullMergeable: ctx.PullMergeable,
394+
Pull: ctx.Pull,
395+
ProjectName: projCfg.Name,
396+
ApplyRequirements: projCfg.ApplyRequirements,
397+
RePlanCmd: p.CommentBuilder.BuildPlanComment(projCfg.RepoRelDir, projCfg.Workspace, projCfg.Name, commentArgs),
398+
RepoRelDir: projCfg.RepoRelDir,
399+
RepoConfigVersion: projCfg.RepoCfgVersion,
400+
TerraformVersion: projCfg.TerraformVersion,
401+
User: ctx.User,
402+
Verbose: verbose,
403+
Workspace: projCfg.Workspace,
404404
}
405405
}
406+
407+
func (p *DefaultProjectCommandBuilder) escapeArgs(args []string) []string {
408+
var escaped []string
409+
for _, arg := range args {
410+
var escapedArg string
411+
for i := range arg {
412+
escapedArg += "\\" + string(arg[i])
413+
}
414+
escaped = append(escaped, escapedArg)
415+
}
416+
return escaped
417+
}

0 commit comments

Comments
 (0)