feat(config): add cobra-probe-enabled toggle option and safeguard cobra probing (#133)

currently, every command that doesn't have a completion spec is assumed
to be a cobra cli and it gets ran with a `__complete` argument. for non
cobra clis this can cause problems if those non-cobra clis have
sideeffects even when ran with the `__complete` argument, and there is
no way to disable this.
one of these problems was solved at #111, but a full solution would
probably require actual sandboxing which is i think is an overkill just
for attempting to get suggestions for unrecognized commands. instead of
sandboxing, this pr adds a config option for allowing only selected
commands to be probed and disallowing the rest.
currently the default is still allowing all (`["*"]`) so default
behavior is the same, but it might be better to just have a long list of
known cobra clis as the default instead.

here's a demo of a side effect caused by the probing, in this case
"deleting" a file with rmtrash without actually trying to run the
command:

https://github.com/user-attachments/assets/5256d363-5291-42e8-bb4f-cf7467927246

---------

Co-authored-by: shemishtamesh <shemishtamail@gmail.com>
This commit is contained in:
shemishtamesh
2026-08-11 19:24:47 +07:00
committed by GitHub
co-authored by shemishtamesh
parent 0f173f78dc
commit 89fcd6f830
8 changed files with 103 additions and 18 deletions
+36
View File
@@ -8,6 +8,8 @@ import (
"path/filepath"
"testing"
"time"
"github.com/versenilvis/iris/internal/config"
)
func TestParseCobraOutput_ValidCobra(t *testing.T) {
@@ -166,6 +168,40 @@ func TestNewProbeCmd_NoControllingTerminal(t *testing.T) {
}
}
func TestQueryCobraComplete_ProbeDisabled(t *testing.T) {
t.Cleanup(ResetCobraCache)
original := config.Get()
t.Cleanup(func() { config.Init(original) })
cfg := config.DefaultConfig()
cfg.Core.CobraProbeEnabled = false
config.Init(cfg)
if result := QueryCobraComplete("non-go-binary", nil, ""); result != nil {
t.Errorf("expected nil when cobra probing is disabled, got %v", result)
}
}
func TestLooksLikeCobraBinary_NotGoBinary(t *testing.T) {
// 'ls' is a standard unix command that's not a go binary
if isLikelyCobraBinary("ls") {
t.Errorf("expected 'ls' to not look like a Cobra binary")
}
}
func TestLooksLikeCobraBinary_RealCobraBinary(t *testing.T) {
dir := t.TempDir()
binPath := filepath.Join(dir, "cobrafixture")
build := exec.CommandContext(context.Background(), "go", "build", "-o", binPath, "./testdata/cobrafixture")
if out, err := build.CombinedOutput(); err != nil {
t.Fatalf("could not build fixture binary: %v: %s", err, out)
}
if !isLikelyCobraBinary(binPath) {
t.Errorf("expected fixture binary linking Cobra to look like a Cobra binary")
}
}
func TestLookup_CobraGolangciLint(t *testing.T) {
results := Lookup("golangci-lint ")
if len(results) == 0 {