fix(executor): always anchor custom regex patterns and harden shellAfterCompleted
Wrap regex: patterns in a non-capturing group before applying ^...$ so alternation cannot bypass full-string matching. Return template parse errors from buildShellAfterCommand, and guard nil binding/action before building shellAfterCompleted commands.
This commit is contained in:
parent
e421780c98
commit
1396184777
|
|
@ -385,7 +385,7 @@ func testWithEntity(t *testing.T, binding *executor.ActionBinding, rr *Dashboard
|
||||||
assert.Equal(t, expectedCanExec, actionResult.CanExec, message)
|
assert.Equal(t, expectedCanExec, actionResult.CanExec, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildExecWithoutLogsTestConfig returns config for GHSA-jm28: user "runner" may exec but not read logs.
|
// buildExecWithoutLogsTestConfig returns config for GHSA-jm28-2wcr-qf3h: user "runner" may exec but not read logs.
|
||||||
func buildExecWithoutLogsTestConfig(t *testing.T) (*config.Config, *authpublic.AuthenticatedUser) {
|
func buildExecWithoutLogsTestConfig(t *testing.T) (*config.Config, *authpublic.AuthenticatedUser) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
cfg := config.DefaultConfig()
|
cfg := config.DefaultConfig()
|
||||||
|
|
|
||||||
|
|
@ -315,10 +315,6 @@ func typeSafetyCheckDatetime(value string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func anchorCustomRegexPattern(pattern string) string {
|
func anchorCustomRegexPattern(pattern string) string {
|
||||||
if strings.HasPrefix(pattern, "^") && strings.HasSuffix(pattern, "$") {
|
|
||||||
return pattern
|
|
||||||
}
|
|
||||||
|
|
||||||
return "^(?:" + pattern + ")$"
|
return "^(?:" + pattern + ")$"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -596,6 +596,13 @@ func TestTypeSafetyCheckRegex(t *testing.T) {
|
||||||
value: "example.com; id",
|
value: "example.com; id",
|
||||||
hasError: true,
|
hasError: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "reject alternation bypass when pattern looks anchored",
|
||||||
|
field: "host",
|
||||||
|
pattern: "regex:^safe$|bad",
|
||||||
|
value: "xxxbad",
|
||||||
|
hasError: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
||||||
|
|
@ -1238,8 +1238,22 @@ func stepExecAfter(req *ExecutionRequest) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildShellAfterCommand(ctx context.Context, req *ExecutionRequest, stdout, stderr *bytes.Buffer) (*exec.Cmd, map[string]string, error) {
|
func shellAfterCompletedAction(req *ExecutionRequest) (*config.Action, bool) {
|
||||||
|
if req == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if !hasBindingAndAction(req) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
if req.Binding.Action.ShellAfterCompleted == "" {
|
if req.Binding.Action.ShellAfterCompleted == "" {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return req.Binding.Action, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildShellAfterCommand(ctx context.Context, req *ExecutionRequest, stdout, stderr *bytes.Buffer) (*exec.Cmd, map[string]string, error) {
|
||||||
|
action, ok := shellAfterCompletedAction(req)
|
||||||
|
if !ok {
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1248,14 +1262,14 @@ func buildShellAfterCommand(ctx context.Context, req *ExecutionRequest, stdout,
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
finalParsedCommand, err := tpl.ParseTemplateWithActionContext(req.Binding.Action.ShellAfterCompleted, req.Binding.Entity, args)
|
finalParsedCommand, err := tpl.ParseTemplateWithActionContext(action.ShellAfterCompleted, req.Binding.Entity, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "Could not prepare shellAfterCompleted command: " + err.Error() + "\n"
|
msg := "Could not prepare shellAfterCompleted command: " + err.Error() + "\n"
|
||||||
req.mutateLogEntry(func(entry *InternalLogEntry) {
|
req.mutateLogEntry(func(entry *InternalLogEntry) {
|
||||||
entry.Output += msg
|
entry.Output += msg
|
||||||
})
|
})
|
||||||
log.Warn(msg)
|
log.Warn(msg)
|
||||||
return nil, nil, nil
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := wrapCommandInShell(ctx, finalParsedCommand)
|
cmd := wrapCommandInShell(ctx, finalParsedCommand)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue