Skip to content

security(low): shell injection patterns in cmd/nixfleet/internal/ #3

@nixfleet-rex

Description

@nixfleet-rex

Summary

Three unsafe shell-construction patterns found in cmd/nixfleet/internal/. Actual risk is low — all inputs are operator-controlled config, not network/user input — but the patterns are fragile and should be cleaned up to prevent future exposure if input sources change.

Findings

1. pullmode/pullmode.go — unquoted config values in shell commands

setupRepository builds commands via fmt.Sprintf with unescaped config values:

fmt.Sprintf("git clone -b %s %s %s", config.Branch, config.RepoURL, config.RepoPath)
fmt.Sprintf("bash -c 'cd %s && git fetch origin && git reset --hard origin/%s'", config.RepoPath, config.Branch)

If config.RepoPath contains a single quote, it breaks out of the bash -c '...' context. These commands are sent over SSH to remote hosts as root.

Fix: Pass args as separate strings to exec.Command (no shell interpolation needed for git commands):

exec.Command("git", "clone", "-b", config.Branch, config.RepoURL, config.RepoPath)
exec.Command("git", "-C", config.RepoPath, "fetch", "origin")
exec.Command("git", "-C", config.RepoPath, "reset", "--hard", "origin/"+config.Branch)

2. pullmode/pullscript template — config values embedded in bash via text/template

Config values (WebhookSecret, HostName, DotfilesPath, etc.) are embedded directly into a bash script using text/template (no escaping):

WEBHOOK_SECRET="{{.WebhookSecret}}"  # a " or $() in value = injection

Fix: Shell-quote embedded values using a template helper (e.g. shquote), or pass values as environment variables instead of inline substitution.

3. cache/cache.go/bin/sh -c with joined args

execLocalCommand runs:

exec.CommandContext(ctx, "/bin/sh", "-c", strings.Join(args, " "))

Joining args into a single string and passing to /bin/sh -c re-introduces word-splitting. Should use exec.Command with separate args directly.

Risk assessment

Low — all three paths take input from operator-controlled configuration files, not from network requests or user-supplied input. There is no network-facing attack surface for these paths in the current architecture.

Recommended fix priority

Low — address in a normal dev cycle, not a hotfix.

Filed by security-bot via controller — 2026-04-22

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions