Skip to content

feat: add Command.ArgValidator for tree-wide argument validation - #2377

Merged
dearchap merged 3 commits into
urfave:mainfrom
dearchap:feat/2327-arg-validator
Aug 16, 2026
Merged

dearchap merged 3 commits into
urfave:mainfrom
dearchap:feat/2327-arg-validator

Conversation

@dearchap

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • feature

What this PR does / why we need it:

Adds ArgValidator to *cli.Command — an optional hook that runs before Before and Action. It is inherited by subcommands unless they set their own. Returning a non-nil error short-circuits the command and propagates as the exit error.

This is useful for security-boundary CLIs that need to reject shell metacharacters or other patterns before user-supplied bytes reach an exec call, as well as for tracing, metrics, or authz middleware that applies tree-wide.

root := &cli.Command{
    ArgValidator: func(ctx context.Context, cmd *cli.Command) error {
        for _, arg := range cmd.Args().Slice() {
            if containsMetachar(arg) {
                return fmt.Errorf("rejected: %q", arg)
            }
        }
        return nil
    },
}

Which issue(s) this PR fixes:

Closes #2327

Testing

  • go test ./... passes
  • go vet ./... passes
  • 5 new tests cover: runs before action, error short-circuits, inherits from parent, subcommand override, runs before Before hook
  • make v3diff shows only the new ArgValidatorFunc type and ArgValidator field
  • make v3approve run to update API surface docs

Release Notes

Add Command.ArgValidator for tree-wide argument validation with subcommand inheritance.

@dearchap
dearchap requested a review from a team as a code owner June 29, 2026 21:04
ArgValidator is an optional hook that runs before Before and Action.
It is inherited by subcommands unless they set their own. Returning
a non-nil error short-circuits the command.

Closes urfave#2327
@dearchap
dearchap force-pushed the feat/2327-arg-validator branch from 0454780 to 1efb810 Compare June 29, 2026 21:07
@dearchap
dearchap requested a review from coilysiren June 29, 2026 21:08
@dearchap
dearchap merged commit e53cec6 into urfave:main Aug 16, 2026
9 checks passed
Maks1mS pushed a commit to stplr-dev/stplr that referenced this pull request Oct 24, 2026
This PR contains the following updates:

| Package | Type | Update | Change | OpenSSF |
|---|---|---|---|---|
| [github.com/urfave/cli/v3](https://github.com/urfave/cli) | require | minor | `v3.10.1` → `v3.14.0` | [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/urfave/cli/badge)](https://securityscorecards.dev/viewer/?uri=github.com/urfave/cli) |

---

> ⚠️ **Warning**
>
> Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/23) for more information.

---

### Release Notes

<details>
<summary>urfave/cli (github.com/urfave/cli/v3)</summary>

### [`v3.14.0`](https://github.com/urfave/cli/releases/tag/v3.14.0)

[Compare Source](urfave/cli@v3.13.0...v3.14.0)

#### What's Changed

- chore(deps): bump mkdocs-git-revision-date-localized-plugin from 1.5.4 to 1.6.0 in the python-packages group by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2436](urfave/cli#2436)
- fix: set BoolWithInverseFlag in a short option group by [@&#8203;lazerg](https://github.com/lazerg) in [#&#8203;2440](urfave/cli#2440)
- Keep arguments after a bare dash by [@&#8203;official-burak](https://github.com/official-burak) in [#&#8203;2419](urfave/cli#2419)
- fix: handle a multi-byte flag at the end of a short option group by [@&#8203;SulimanAbdulrazzaq](https://github.com/SulimanAbdulrazzaq) in [#&#8203;2438](urfave/cli#2438)
- fix: complete persistent flags in shell completion by [@&#8203;sb123sb123](https://github.com/sb123sb123) in [#&#8203;2437](urfave/cli#2437)
- fix: restore Unwrap on the error returned by Exit by [@&#8203;fadiroot](https://github.com/fadiroot) in [#&#8203;2444](urfave/cli#2444)
- fix: reject a parent's Local flag inside a short option group by [@&#8203;fadiroot](https://github.com/fadiroot) in [#&#8203;2445](urfave/cli#2445)
- fix: report a flag that needs an argument but is not last in a short group by [@&#8203;yu2971512385-ui](https://github.com/yu2971512385-ui) in [#&#8203;2443](urfave/cli#2443)
- Use prefixFor so flag suggestions agree with help on rune count by [@&#8203;januththedev](https://github.com/januththedev) in [#&#8203;2448](urfave/cli#2448)
- fix: reject duplicate flag names by [@&#8203;deepakganesh78](https://github.com/deepakganesh78) in [#&#8203;2396](urfave/cli#2396)
- fix: date a time-only timestamp today when Timezone is not UTC by [@&#8203;breken-ai](https://github.com/breken-ai) in [#&#8203;2450](urfave/cli#2450)
- fix: let a subcommand's command-line value replace a persistent flag's env/file value by [@&#8203;breken-ai](https://github.com/breken-ai) in [#&#8203;2449](urfave/cli#2449)
- Add urfave_cli_no_template build tag by [@&#8203;kolyshkin](https://github.com/kolyshkin) in [#&#8203;2441](urfave/cli#2441)
- fix: skip empty source values for flags that cannot parse them by [@&#8203;abo3losh1](https://github.com/abo3losh1) in [#&#8203;2451](urfave/cli#2451)

#### New Contributors

- [@&#8203;lazerg](https://github.com/lazerg) made their first contribution in [#&#8203;2440](urfave/cli#2440)
- [@&#8203;official-burak](https://github.com/official-burak) made their first contribution in [#&#8203;2419](urfave/cli#2419)
- [@&#8203;SulimanAbdulrazzaq](https://github.com/SulimanAbdulrazzaq) made their first contribution in [#&#8203;2438](urfave/cli#2438)
- [@&#8203;sb123sb123](https://github.com/sb123sb123) made their first contribution in [#&#8203;2437](urfave/cli#2437)
- [@&#8203;fadiroot](https://github.com/fadiroot) made their first contribution in [#&#8203;2444](urfave/cli#2444)
- [@&#8203;yu2971512385-ui](https://github.com/yu2971512385-ui) made their first contribution in [#&#8203;2443](urfave/cli#2443)
- [@&#8203;januththedev](https://github.com/januththedev) made their first contribution in [#&#8203;2448](urfave/cli#2448)
- [@&#8203;deepakganesh78](https://github.com/deepakganesh78) made their first contribution in [#&#8203;2396](urfave/cli#2396)
- [@&#8203;breken-ai](https://github.com/breken-ai) made their first contribution in [#&#8203;2450](urfave/cli#2450)
- [@&#8203;abo3losh1](https://github.com/abo3losh1) made their first contribution in [#&#8203;2451](urfave/cli#2451)

**Full Changelog**: <urfave/cli@v3.13.0...v3.14.0>

### [`v3.13.0`](https://github.com/urfave/cli/releases/tag/v3.13.0)

[Compare Source](urfave/cli@v3.12.0...v3.13.0)

#### What's Changed

- Trim the key of a map flag when TrimSpace is set by [@&#8203;youdie006](https://github.com/youdie006) in [#&#8203;2431](urfave/cli#2431)
- Fix inverse bool flag counting with an external counter by [@&#8203;jakezwang](https://github.com/jakezwang) in [#&#8203;2432](urfave/cli#2432)
- feat: add Deprecated field to flags and commands by [@&#8203;anandghegde](https://github.com/anandghegde) in [#&#8203;2429](urfave/cli#2429)
- fix: parse single-rune Unicode flags by [@&#8203;znnnnnnn-wil](https://github.com/znnnnnnn-wil) in [#&#8203;2434](urfave/cli#2434)

#### New Contributors

- [@&#8203;jakezwang](https://github.com/jakezwang) made their first contribution in [#&#8203;2432](urfave/cli#2432)
- [@&#8203;anandghegde](https://github.com/anandghegde) made their first contribution in [#&#8203;2429](urfave/cli#2429)
- [@&#8203;znnnnnnn-wil](https://github.com/znnnnnnn-wil) made their first contribution in [#&#8203;2434](urfave/cli#2434)

**Full Changelog**: <urfave/cli@v3.12.0...v3.13.0>

### [`v3.12.0`](https://github.com/urfave/cli/releases/tag/v3.12.0)

[Compare Source](urfave/cli@v3.11.0...v3.12.0)

#### What's Changed

- feat: add Command.ArgValidator for tree-wide argument validation by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2377](urfave/cli#2377)
- Single-value arguments can be marked as required by [@&#8203;idelchi](https://github.com/idelchi) in [#&#8203;2393](urfave/cli#2393)
- docs: clarify that named Arguments are excluded from cmd.Args() by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2411](urfave/cli#2411)
- fix: never run command action on shell completion past a double dash by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2412](urfave/cli#2412)
- chore(deps): bump github.com/stretchr/testify from 1.11.1 to 1.12.0 by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;2413](urfave/cli#2413)
- Support custom FlagStringer for MutuallyExclusiveFlags by [@&#8203;SHIVANSHGARG07](https://github.com/SHIVANSHGARG07) in [#&#8203;2414](urfave/cli#2414)
- Add TextFlag for encoding.TextMarshaler/TextUnmarshaler values by [@&#8203;ChrisJr404](https://github.com/ChrisJr404) in [#&#8203;2415](urfave/cli#2415)
- chore(deps): bump github.com/stretchr/testify from 1.12.0 to 1.12.1 by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;2416](urfave/cli#2416)
- chore(deps): bump the python-packages group with 2 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;2417](urfave/cli#2417)
- Show inherited persistent flags in child help by [@&#8203;justadityaraj](https://github.com/justadityaraj) in [#&#8203;2421](urfave/cli#2421)
- fix: preserve whitespace in positional arguments by [@&#8203;lenamonj](https://github.com/lenamonj) in [#&#8203;2423](urfave/cli#2423)
- fix: preserve whitespace in equals-form flag values by [@&#8203;BenYang12](https://github.com/BenYang12) in [#&#8203;2425](urfave/cli#2425)
- fix: complete subcommand flags after positional arguments by [@&#8203;fzlzjerry](https://github.com/fzlzjerry) in [#&#8203;2426](urfave/cli#2426)
- Fix a year-less timestamp layout losing January 1 by [@&#8203;youdie006](https://github.com/youdie006) in [#&#8203;2427](urfave/cli#2427)
- docs: add go-size-analyzer, module version, and reflection by [@&#8203;imsumedhaa](https://github.com/imsumedhaa) in [#&#8203;2428](urfave/cli#2428)

#### New Contributors

- [@&#8203;idelchi](https://github.com/idelchi) made their first contribution in [#&#8203;2393](urfave/cli#2393)
- [@&#8203;SHIVANSHGARG07](https://github.com/SHIVANSHGARG07) made their first contribution in [#&#8203;2414](urfave/cli#2414)
- [@&#8203;ChrisJr404](https://github.com/ChrisJr404) made their first contribution in [#&#8203;2415](urfave/cli#2415)
- [@&#8203;justadityaraj](https://github.com/justadityaraj) made their first contribution in [#&#8203;2421](urfave/cli#2421)
- [@&#8203;lenamonj](https://github.com/lenamonj) made their first contribution in [#&#8203;2423](urfave/cli#2423)
- [@&#8203;BenYang12](https://github.com/BenYang12) made their first contribution in [#&#8203;2425](urfave/cli#2425)
- [@&#8203;youdie006](https://github.com/youdie006) made their first contribution in [#&#8203;2427](urfave/cli#2427)
- [@&#8203;imsumedhaa](https://github.com/imsumedhaa) made their first contribution in [#&#8203;2428](urfave/cli#2428)

**Full Changelog**: <urfave/cli@v3.11.0...v3.12.0>

### [`v3.11.0`](https://github.com/urfave/cli/releases/tag/v3.11.0)

[Compare Source](urfave/cli@v3.10.1...v3.11.0)

#### What's Changed

- fix: correct a typo in the help message for the powershell autocompletion by [@&#8203;suzuki-shunsuke](https://github.com/suzuki-shunsuke) in [#&#8203;2383](urfave/cli#2383)
- Escape backslashes in fish completion descriptions by [@&#8203;mahirhir](https://github.com/mahirhir) in [#&#8203;2378](urfave/cli#2378)
- chore(deps): bump actions/setup-go from 6 to 7 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2389](urfave/cli#2389)
- chore(deps): bump mkdocs-material from 9.7.6 to 9.7.7 in the python-packages group by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2391](urfave/cli#2391)
- chore(deps): bump actions/setup-python from 6 to 7 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2390](urfave/cli#2390)
- fix: skip all hidden flags in shell completion, not just bool flags by [@&#8203;vidigoat](https://github.com/vidigoat) in [#&#8203;2388](urfave/cli#2388)
- Fix nil pointer dereference for interface-typed flag values by [@&#8203;mrueg](https://github.com/mrueg) in [#&#8203;2400](urfave/cli#2400)
- Fix index out of range panic when Run is given no arguments by [@&#8203;mrueg](https://github.com/mrueg) in [#&#8203;2401](urfave/cli#2401)
- fix: honor BoolWithInverseFlag DefaultText by [@&#8203;fzlzjerry](https://github.com/fzlzjerry) in [#&#8203;2403](urfave/cli#2403)
- Fix Issue [#&#8203;2385](urfave/cli#2385) by [@&#8203;BrandonIrizarry](https://github.com/BrandonIrizarry) in [#&#8203;2386](urfave/cli#2386)
- fix: inherit HideHelpCommand in subcommands by [@&#8203;utkarshalpha](https://github.com/utkarshalpha) in [#&#8203;2395](urfave/cli#2395)
- test: cover Run-with-no-arguments paths ([#&#8203;2406](urfave/cli#2406)) by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2407](urfave/cli#2407)
- test: add shell-completion case for hidden BoolWithInverseFlag by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2408](urfave/cli#2408)
- test: fix ineffective mutex error-string assertion and add mirror cases by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2410](urfave/cli#2410)

#### New Contributors

- [@&#8203;mahirhir](https://github.com/mahirhir) made their first contribution in [#&#8203;2378](urfave/cli#2378)
- [@&#8203;vidigoat](https://github.com/vidigoat) made their first contribution in [#&#8203;2388](urfave/cli#2388)
- [@&#8203;fzlzjerry](https://github.com/fzlzjerry) made their first contribution in [#&#8203;2403](urfave/cli#2403)
- [@&#8203;BrandonIrizarry](https://github.com/BrandonIrizarry) made their first contribution in [#&#8203;2386](urfave/cli#2386)
- [@&#8203;utkarshalpha](https://github.com/utkarshalpha) made their first contribution in [#&#8203;2395](urfave/cli#2395)

**Full Changelog**: <urfave/cli@v3.10.1...v3.11.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At 12:00 AM through 04:59 AM and 10:00 PM through 11:59 PM, Monday through Friday (`* 0-4,22-23 * * 1-5`)
  - Only on Sunday and Saturday (`* * * * 0,6`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNTEuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjE1MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY2llcyJdfQ==-->

Reviewed-on: https://altlinux.space/stapler/stplr/pulls/503
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add tree-wide argv-validation hook / middleware

1 participant