Skip to content

Commit 4138a08

Browse files
committed
vyos-op-run: T8005: sanitize environment variables
to prevent malicious variable injection
1 parent 5285c78 commit 4138a08

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

debian/changelog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
vyos-utils (0.0.5) unstable; urgency=medium
2+
3+
* Sanitize the environment in vyos-op-run to prevent malicious variable injection
4+
5+
-- Daniil Baturin <[email protected]> Tue, 11 Nov 2025 13:46:05 +0000
6+
17
vyos-utils (0.0.4) unstable; urgency=medium
28

39
* Add an operational command runner.

src/vyos_op_run.ml

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,39 @@ let run_external_command opts env command_tmpl =
319319
let cmd = render_command opts env command_tmpl in
320320
if opts.dry_run then Printf.printf "%s\n%!" cmd else
321321
let () = Logs.debug @@ fun m -> m "Command to be executed %s" cmd in
322-
let res = Unix.system cmd in
322+
(* Get the user database entry to populate the basic environment from:
323+
we cannot trust an unprivileged user to supply $SHELL
324+
or allow them to impersonate someone else by setting custom $LOGNAME, etc.
325+
*)
326+
let user_pw_entry = Unix.getpwuid @@ Unix.getuid () in
327+
let make_var name value = Printf.sprintf "%s=%s" name value in
328+
let env = [|
329+
(* A knowingly safe executable lookup path.
330+
Since we do not use /usr/local, we do not need to include that.
331+
Executables in VyOS-specific directories are referred to by absolute paths
332+
in the operational command JSON cache,
333+
so we don't need to include those, either.
334+
*)
335+
make_var "PATH" "/usr/sbin:/usr/bin:/sbin:/bin";
336+
(* Standard UNIX variables *)
337+
make_var "HOME" user_pw_entry.pw_dir;
338+
make_var "USER" user_pw_entry.pw_name;
339+
make_var "LOGNAME" user_pw_entry.pw_name;
340+
make_var "SHELL" user_pw_entry.pw_shell;
341+
(* VyOS-specific variables *)
342+
make_var "vyos_data_dir" "/usr/share/vyos";
343+
make_var "vyos_validators_dir" "/usr/libexec/vyos/validators";
344+
make_var "vyos_completion_dir" "/usr/libexec/vyos/completion";
345+
make_var "vyos_libexec_dir" "/usr/libexec/vyos";
346+
make_var "vyos_op_scripts_dir" "/usr/libexec/vyos/op_mode";
347+
|]
348+
in
349+
let shell = "/bin/sh" in
350+
(* We use execve with an absolute path to Bourne shell rather than execvpe
351+
so that a user trying to do PATH=/bad/place vyos-op-run
352+
cannot achieve anything with that trick.
353+
*)
354+
let res = Unix.execve shell [|shell; "-c"; cmd|] env in
323355
match res with
324356
| Unix.WEXITED 0 -> ()
325357
| _ ->

0 commit comments

Comments
 (0)