Skip to content

sync upstream - #21

Closed
xushiwei wants to merge 29 commits into
xgofrom
sync-upstream
Closed

sync upstream#21
xushiwei wants to merge 29 commits into
xgofrom
sync-upstream

Conversation

@xushiwei

@xushiwei xushiwei commented May 2, 2026

Copy link
Copy Markdown
Member

No description provided.

ericdachen and others added 27 commits April 11, 2025 19:30
To avoid cropping up new findings for commonly ignored issues for now.
In pflag, we recently made a breaking change in naming to be more inclusive. This change, while doing nothing to address the same uninclusive naming in cobra itself, adjusts to those changes to ensure automatic bumps (if you do them) can continue uninterrupted.
Signed-off-by: John McBride <jpmmcbride@gmail.com>
We need to keep the old "+build" syntax because Cobra still allows to
use a Go version as old as 1.15.

Signed-off-by: Marc Khouzam <marc.khouzam@gmail.com>
Resolves spf13#2298

- Added comprehensive "Repeated Flags" section to user guide
- Documented CountVarP for SSH-style verbose flags (-v, -vv, -vvv)
- Documented StringArrayVarP for multiple value collection
- Provided complete code examples and usage patterns

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Vergis_Ron <Vergis_Ron@bah.com>
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: John McBride <jpmmcbride@gmail.com>
The original gopkg.in/yaml.v3 was marked unmaintained (April 2025).
go.yaml.in/yaml/v3 is now maintained by the official YAML organization
and is a drop-in replacement with an identical API.

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
…cesses. (spf13#2333)

Today, the loop is printing the completions one value per line and then
reading one line to a variable. We can just skip the whole IO rigamarole
by looping over the completions directly.
* fix: quote args in fish shell completion

The arguments used for dynamic completions in fish were missing quotes.
This resulted in an error when one of the arguments had a `*` in it
whose expansion matched no file. Once the completion got triggered, fish
errored with the message `No matches for wildcard [...]`. Don't quote
the first argument as that is the name of the binary.

* Protect against arguments that start with --

Signed-off-by: Marc Khouzam <marc.khouzam@gmail.com>

---------

Co-authored-by: Marc Khouzam <marc.khouzam@gmail.com>
…spf13#2356)

Fixes spf13#2257

When getCompletions() checks for interspersed flags, it calls
append(finalArgs, "--") to temporarily add a "--" sentinel. However,
finalArgs is a sub-slice of the original args (ultimately derived from
os.Args[1:] or SetArgs), and if the sub-slice has spare capacity in its
backing array, append writes "--" into the shared array, corrupting
the caller's data.

This is particularly visible when TraverseChildren is enabled: the
Traverse method returns sub-slices that share the original backing
array. A user's ValidArgsFunction inspecting os.Args would then see
"--" where a real argument should be.

Copy trimmedArgs at the top of getCompletions to prevent any future
append from accidentally mutating the caller's backing array.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: xushiwei <396972+xushiwei@users.noreply.github.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several improvements and bug fixes to the Cobra library. Key additions include a new NoDuplicateArgs positional argument validator and the ability to configure a DefaultShellCompDirective within CompletionOptions, which supports inheritance across command hierarchies. A critical bug where shell completion could inadvertently mutate os.Args was resolved by ensuring argument slices are copied. Additionally, the PR updates the linting configuration, optimizes documentation generation by using fmt.Fprintf, and expands the user guide. Review feedback suggests reverting to the canonical gopkg.in/yaml.v3 import path and using more idiomatic, shorter receiver names in Go methods.

Comment thread doc/go.mod
github.com/cpuguy83/go-md2man/v2 v2.0.6
github.com/goplus/cobra v0.0.0-00010101000000-000000000000
gopkg.in/yaml.v3 v3.0.1
go.yaml.in/yaml/v3 v3.0.4

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The import path for yaml.v3 has been changed to go.yaml.in/yaml/v3. The canonical and standard import path for this library is gopkg.in/yaml.v3. Using a non-canonical mirror path can lead to duplicate packages in the dependency graph if other dependencies use the canonical path, and it deviates from standard Go ecosystem practices.

Suggested change
go.yaml.in/yaml/v3 v3.0.4
gopkg.in/yaml.v3 v3.0.4

Comment thread doc/yaml_docs.go
"github.com/goplus/cobra"
"github.com/goplus/cobra/pflag"
"gopkg.in/yaml.v3"
"go.yaml.in/yaml/v3"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This import should use the canonical path gopkg.in/yaml.v3 instead of the mirror go.yaml.in/yaml/v3 to maintain consistency and avoid potential conflicts with other packages that depend on the standard path.

Suggested change
"go.yaml.in/yaml/v3"
"gopkg.in/yaml.v3"

Comment thread completions.go
Comment on lines +123 to 125
func (receiver *CompletionOptions) SetDefaultShellCompDirective(directive ShellCompDirective) {
receiver.DefaultShellCompDirective = &directive
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The receiver name receiver is not idiomatic in Go. Receiver names should be short (usually one or two letters) and reflect the type name (e.g., o or opt for CompletionOptions).

Suggested change
func (receiver *CompletionOptions) SetDefaultShellCompDirective(directive ShellCompDirective) {
receiver.DefaultShellCompDirective = &directive
}
func (o *CompletionOptions) SetDefaultShellCompDirective(directive ShellCompDirective) {
o.DefaultShellCompDirective = &directive
}

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Overall this is a clean upstream sync. The correctness fixes (trimmedArgs mutation, fish escaping, boolean refactors) are sound. A few items below warrant attention before merging.

Findings: 1 medium security, 1 medium docs accuracy, 2 docs clarity, 2 code quality, 1 low security.

Comment thread fish_completions.go

# Disable ActiveHelp which is not supported for fish shell
set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg"
set -l requestComp "%[10]s=0 $args[1] %[3]s $(string join ' ' -- (string escape -- $args[2..-1])) $lastArg"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Security - Medium] Incomplete escaping before eval

The fix correctly escapes $args[2..-1] via string escape, but $args[1] (the binary name) in the same string remains unescaped before being passed to eval on line 59. If an attacker can influence the program name (e.g., a crafted $PATH entry where the binary name contains shell metacharacters), it flows into eval without sanitization.

$lastArg is pre-escaped at assignment time (line 50), so that is safe. But $args[1] should also be wrapped in string escape:

set -l requestComp "%[10]s=0 $(string escape -- $args[1]) %[3]s $(string join ' ' -- (string escape -- $args[2..-1])) $lastArg"

Comment thread completions.go
DefaultShellCompDirective *ShellCompDirective
}

func (receiver *CompletionOptions) SetDefaultShellCompDirective(directive ShellCompDirective) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Code Quality] Non-idiomatic receiver name

receiver is not a conventional Go receiver name. The rest of the codebase uses short names (c *Command, etc.). Per Go conventions (and the enabled gocritic linter), this should be o or co:

func (o *CompletionOptions) SetDefaultShellCompDirective(directive ShellCompDirective) {

Comment thread completions.go
HiddenDefaultCmd bool
// DefaultShellCompDirective sets the ShellCompDirective that is returned
// if no special directive can be determined
DefaultShellCompDirective *ShellCompDirective

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Code Quality] Doc comment doesn't explain pointer semantics or scope

The pointer is needed to distinguish nil ("not set, inherit from parent") from 0 (ShellCompDirectiveDefault). This non-obvious design should be documented on the field:

// DefaultShellCompDirective overrides the directive used when no completion
// function is registered. It is a pointer to distinguish "not set" (nil, inherits
// from the nearest ancestor) from "explicitly set to ShellCompDirectiveDefault (0)".
// Applies only to argument/noun completion; flag-name and flag-value completion
// paths use their own fixed directives.
DefaultShellCompDirective *ShellCompDirective

Comment thread completions.go
// Such logs are only printed when the user has set the environment
// variable BASH_COMP_DEBUG_FILE to the path of some file to be used.
if path := os.Getenv("BASH_COMP_DEBUG_FILE"); path != "" {
//nolint:gosec // G703:BASH_COMP_DEBUG_FILE intentionally user-controlled for completion debug logging.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Security - Low] Wrong gosec rule ID in nolint annotation

The comment cites G703, which is not a valid gosec rule. The actual rule that fires here is G304 ("Potential file inclusion via variable"), since path is derived from an environment variable. The suppression intent is reasonable, but the incorrect rule ID undermines auditability and may not suppress the actual finding in all gosec versions:

//nolint:gosec // G304: BASH_COMP_DEBUG_FILE is intentionally user-controlled for completion debug logging.

```go
cmd.RegisterFlagCompletionFunc("flag-name", cobra.NoFileCompletions)
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Docs - Medium] "Recursively change" is misleading

The text says "you can recursively change the default ShellCompDirective for a command and its subcommands". The actual implementation doesn't push anything down — it walks up the parent chain at completion time and stops at the first ancestor with a non-nil DefaultShellCompDirective. Subcommands inherit by lookup, not by mutation. Suggested rephrasing:

you can set a DefaultShellCompDirective on a command so that it and any subcommands that don't override it will use ShellCompDirectiveNoFileComp:

If you find that there are more situations where file completion should be turned off than
when it is applicable, you can recursively change the default `ShellCompDirective` for a command
and its subcommands to `ShellCompDirectiveNoFileComp`:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Docs - Medium] Missing cobra. package qualifier in code examples

Both code examples in this new section use unqualified identifiers that require the cobra. prefix for users consuming this library from outside the package:

  • Line 324: ShellCompDirectiveNoFileCompcobra.ShellCompDirectiveNoFileComp
  • Line 331: ShellCompDirectiveDefaultcobra.ShellCompDirectiveDefault

Compare with the correctly-qualified examples earlier in the same file (e.g., cobra.NoFileCompletions on line 316).

- `myapp -i file1.txt -i file2.txt`
- With StringSlice: `myapp --input file1.txt,file2.txt,file3.txt`

**Note**: Both `CountVar` and array flags leverage the underlying [pflag](https://github.com/spf13/pflag) library's support for repeated flags.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Docs - Low] Note refers to CountVar but section documents CountVarP

The note says "Both CountVar and array flags..." but the code example above uses CountVarP (the variant that accepts a shorthand). Either reference both variants explicitly (CountVar / CountVarP) or use the same name as the example above to avoid confusion.

@xushiwei xushiwei closed this May 2, 2026
@xushiwei
xushiwei deleted the sync-upstream branch May 2, 2026 14:05
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.