Summary
Add a middleware-style argv-validation hook on *cli.Command:
// OnArgValidate, if non-nil, is called once per argv before Action runs.
// Returning a non-nil error short-circuits Action and propagates as the
// command's exit error. Inherited by subcommands unless they set their
// own. Useful for security-boundary CLIs that reject shell metacharacters
// or other patterns before the user-supplied bytes reach an exec call.
OnArgValidate func(argv []string) error
(or equivalently, a cli.Middleware interface that allows wrapping any Action.)
Motivation
cli-guard is a security-boundary framework for urfave/cli that wraps every command's Action with a fixed pipeline: argv validation → action → audit log. The argv-validation step rejects shell metacharacters before they can reach execve in a passthrough wrapper.
Today this is achieved by wrapping each Action with a verb.Wrap() helper:
&cli.Command{
Name: "aws",
Action: verb.Wrap(verb.Spec{
Name: "aws",
Action: realAction,
}, auditWriter),
}
Working but every command has to opt in by hand. A tree-wide middleware chain (or an OnArgValidate hook that subcommands inherit) would let consumers register the validation once at the root and have it apply automatically to every action in the tree.
This is the same shape as the "Before" hook, except:
Before is per-Command (no inheritance).
Before runs before Action but does not naturally short-circuit the action.
- A
Middleware interface is also more natural for the "wrap and observe" pattern (audit logging, tracing, metrics) than for the "validate and possibly reject" pattern.
Alternatives considered
- Make
Before inheritable. Cleaner but changes semantics; existing code that sets Before per-Command might be surprised.
- Document the manual-wrap pattern (
verb.Wrap-equivalent) as the supported approach. Works but is hand-pluming for every command.
Use cases beyond cli-guard
- Tracing (OpenTelemetry span per command, propagated via context).
- Metrics (Prometheus counter per command execution).
- Authz (per-command role gating beyond what
Hidden provides).
Happy to discuss API shape before sending a PR.
Summary
Add a middleware-style argv-validation hook on
*cli.Command:(or equivalently, a
cli.Middlewareinterface that allows wrapping any Action.)Motivation
cli-guard is a security-boundary framework for urfave/cli that wraps every command's Action with a fixed pipeline: argv validation → action → audit log. The argv-validation step rejects shell metacharacters before they can reach
execvein a passthrough wrapper.Today this is achieved by wrapping each
Actionwith averb.Wrap()helper:Working but every command has to opt in by hand. A tree-wide middleware chain (or an
OnArgValidatehook that subcommands inherit) would let consumers register the validation once at the root and have it apply automatically to every action in the tree.This is the same shape as the "Before" hook, except:
Beforeis per-Command (no inheritance).Beforeruns before Action but does not naturally short-circuit the action.Middlewareinterface is also more natural for the "wrap and observe" pattern (audit logging, tracing, metrics) than for the "validate and possibly reject" pattern.Alternatives considered
Beforeinheritable. Cleaner but changes semantics; existing code that setsBeforeper-Command might be surprised.verb.Wrap-equivalent) as the supported approach. Works but is hand-pluming for every command.Use cases beyond cli-guard
Hiddenprovides).Happy to discuss API shape before sending a PR.