ask-password: refuse agent requests with unsafe characters in prompt fields

The message, icon and id fields are written verbatim into single-line
assignments of the [Ask] section of the agent request file, so a newline in
them lets the caller append arbitrary further assignments. Agents let a later
assignment override an earlier one, so an injected Socket= line redirects the
password to a path of the injector's choosing. Validate the fields and refuse
the request instead.
This commit is contained in:
Armaan Sandhu
2026-07-26 05:30:02 +09:00
committed by Yu Watanabe
parent a8e93919c3
commit 151dafcf16
4 changed files with 56 additions and 0 deletions
+19
View File
@@ -828,6 +828,21 @@ static int create_socket(const char *askpwdir, char **ret) {
return TAKE_FD(fd);
}
bool ask_password_agent_prompt_fields_are_safe(const AskPasswordRequest *req) {
/* These fields end up in single-line "Key=value" assignments in the agent request file, hence a
* newline (or any other control character) in them would let the caller add further assignments to
* the [Ask] section, which agents then happily honour. Only the characters string_is_safe() rejects
* by default matter here, the rest is fine to appear in a prompt. */
const StringSafeFlags flags = STRING_ALLOW_EMPTY | STRING_ALLOW_BACKSLASHES |
STRING_ALLOW_QUOTES | STRING_ALLOW_GLOBS;
assert(req);
return (!req->message || string_is_safe(req->message, flags)) &&
(!req->icon || string_is_safe(req->icon, flags)) &&
(!req->id || string_is_safe(req->id, flags));
}
int ask_password_agent(
const AskPasswordRequest *req,
AskPasswordFlags flags,
@@ -850,6 +865,10 @@ int ask_password_agent(
if (req->flag_file)
return -EOPNOTSUPP;
if (!ask_password_agent_prompt_fields_are_safe(req))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Password request contains unsafe characters, refusing.");
_cleanup_free_ char *askpwdir = NULL;
r = get_ask_password_directory_for_flags(flags, &askpwdir);
if (r < 0)
+1
View File
@@ -32,6 +32,7 @@ typedef struct AskPasswordRequest {
int ask_password_tty(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret);
int ask_password_plymouth(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret);
bool ask_password_agent_prompt_fields_are_safe(const AskPasswordRequest *req) _pure_;
int ask_password_agent(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret);
int ask_password_auto(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret);