From 8c6f1c4a210966c963e98acae4f632ce834e1cd6 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 21 Jul 2026 10:43:22 +0200 Subject: [PATCH] profile/systemd-osc-context: also escape $USER and $HOSTNAME Claude pointed out that while rather unlikely, it is possible for the USER and HOSTNAME environment variables to contain problematic characters that require escaping. Now that that escaping no longer involves the fork+exec overhead of calling sed, let's ensure those fields do get put through the escape routine. Refactor __systemd_osc_context_escape so that it not only takes the value and prints that, but also the format specifier used for emitting the field. That way, we avoid an extra subshell (i.e. fork+pipe and all that overhead), and combined with the previous commit, we now only spawn one subshell instead of two per start= sequence. That could be reduced to zero, if the "callers" were rewritten to something like printf "\033]3008;start=%.64s;type=shell" "$systemd_osc_context_shell_id" __systemd_osc_context_common printf "\033\\" but that will mean that the sequence is not emitted with a single write() system call [which isn't really guaranteed currently either, just very likely], so some background process could end up writing to the middle of the sequence, thus losing that output and mangling the OSC3008 info. This in turn could be overcome by building the whole sequence in a shell variable using 'printf -v' and only printing at the end, but that would be a somewhat invasive change. --- profile.d/80-systemd-osc-context.sh | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/profile.d/80-systemd-osc-context.sh b/profile.d/80-systemd-osc-context.sh index 6b4aa348cff..80c4740d47d 100644 --- a/profile.d/80-systemd-osc-context.sh +++ b/profile.d/80-systemd-osc-context.sh @@ -35,25 +35,27 @@ shopt -q promptvars || return 0 __systemd_osc_context_escape() { - # Escape according to the OSC 3008 spec. We'll only do it where it's - # strictly necessary, and skip it when processing strings we are pretty - # sure we won't need it for, such as uuids, id128, hostnames, usernames, - # since they all come with syntax requirements that exclude \ and ; - # anyway. This hence primarily is about escaping the current working - # directory. - local systemd_value="$1" + # Escape according to the OSC 3008 spec. We'll skip it when processing + # strings we are pretty sure we won't need it for, such as uuids + # (originating from /proc/sys/kernel/ or /etc/machine-id) and special shell + # variables such as $$ and $? that always expand to decimal numbers. + local systemd_format="$1" + local systemd_value="$2" systemd_value="${systemd_value//\\/\\x5c}" systemd_value="${systemd_value//;/\\x3b}" systemd_value="${systemd_value//[[:cntrl:]]/⍰}" - printf "%s" "$systemd_value" + # shellcheck disable=SC2059 # always called with fixed format strings with a single string specifier + printf "$systemd_format" "$systemd_value" } __systemd_osc_context_common() { if [ -f /etc/machine-id ]; then printf ";machineid=%.36s" "$(