Gitfed
bastien-mrq/gitfed / cmd / gitfed-ctl / exec_test.go
package main

import (
	"context"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

func TestRunPipedConnectsStdoutToStdin(t *testing.T) {
	err := runPiped(context.Background(),
		[]string{"echo", "-n", "hello"},
		[]string{"cat"},
	)
	if err != nil {
		t.Fatalf("runPiped: %v", err)
	}
}

// TestRunPipedNoShellInjection reproduces the real bug: the previous
// `sh -c "docker save '<tag>' | k3s ctr images import -"` pattern's
// quoting (shellQuote, a bare wrap in single quotes) didn't escape an
// embedded single quote, so a tag/version string containing one could
// break out and run arbitrary shell commands. runPiped never invokes a
// shell at all, so the same string is inert — it's just a literal
// argument to `cat`, not code.
func TestRunPipedNoShellInjection(t *testing.T) {
	dir := t.TempDir()
	proof := filepath.Join(dir, "proof")
	malicious := "gitfed:1.2.10'; touch " + proof + "; echo '"

	err := runPiped(context.Background(),
		[]string{"echo", "-n", malicious},
		[]string{"cat"},
	)
	if err != nil {
		t.Fatalf("runPiped: %v", err)
	}
	if _, statErr := os.Stat(proof); statErr == nil {
		t.Fatal("injection succeeded: a shell interpreted the piped argument")
	}
}

func TestRunPipedFirstCommandFails(t *testing.T) {
	err := runPiped(context.Background(),
		[]string{"sh", "-c", "echo bad-times >&2; exit 3"},
		[]string{"cat"},
	)
	if err == nil {
		t.Fatal("expected an error when the first command exits non-zero")
	}
	if !strings.Contains(err.Error(), "bad-times") {
		t.Errorf("expected the first command's stderr in the error, got: %v", err)
	}
}

func TestRunPipedSecondCommandFails(t *testing.T) {
	err := runPiped(context.Background(),
		[]string{"echo", "hi"},
		[]string{"sh", "-c", "echo nope >&2; exit 3"},
	)
	if err == nil {
		t.Fatal("expected an error when the second command exits non-zero")
	}
	if !strings.Contains(err.Error(), "nope") {
		t.Errorf("expected the second command's stderr in the error, got: %v", err)
	}
}