From 941ab121da6521f320a072466ffbc84993669231 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Tue, 26 May 2026 09:34:52 -0700 Subject: [PATCH] Reject shell-unsafe paths in FreeBSD rc.d install Validate executable and state directory paths before rendering the rc.d script so crafted values cannot inject shell syntax. Signed-off-by: Bryan Frimin --- pkg/deviceagent/service/service_freebsd.go | 4 ++ pkg/deviceagent/service/validate.go | 44 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 pkg/deviceagent/service/validate.go diff --git a/pkg/deviceagent/service/service_freebsd.go b/pkg/deviceagent/service/service_freebsd.go index a0115d0a3..6617c6f74 100644 --- a/pkg/deviceagent/service/service_freebsd.go +++ b/pkg/deviceagent/service/service_freebsd.go @@ -59,6 +59,10 @@ func Install(cfg Config) error { return errors.New("state directory is required") } + if err := validateServicePaths(cfg); err != nil { + return err + } + rcTmpl, err := template.New("rc").Parse(rcScriptTmpl) if err != nil { return fmt.Errorf("cannot parse rc.d template: %w", err) diff --git a/pkg/deviceagent/service/validate.go b/pkg/deviceagent/service/validate.go new file mode 100644 index 000000000..52dcb1873 --- /dev/null +++ b/pkg/deviceagent/service/validate.go @@ -0,0 +1,44 @@ +// Copyright (c) 2025-2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package service + +import "fmt" + +func validateServicePaths(cfg Config) error { + if err := validateShellSafePath("executable path", cfg.ExePath); err != nil { + return err + } + + return validateShellSafePath("state directory", cfg.Dir) +} + +func validateShellSafePath(label, path string) error { + if path == "" { + return nil + } + + for _, r := range path { + switch r { + case '"', '\'', '`', '$', ';', '\n', '\r', '\000': + return fmt.Errorf( + "%s contains shell-unsafe character %q", + label, + r, + ) + } + } + + return nil +}