From 25c2afc3e95f07b3fc0d5b7e8bbd42eaec99ec22 Mon Sep 17 00:00:00 2001
From: KaraZajac
Date: Thu, 28 May 2026 21:50:26 -0400
Subject: [PATCH] release v0.9.6: --auto no longer prompts for sudo password
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
sudo_runas_neg1 and sudoedit_editor's detect() bodies invoked
'sudo -ln' (intending list + non-interactive). Some sudoers / PAM
configurations have been observed prompting for a password anyway
when the flags are bundled. That meant skeletonkey --auto --i-know
could hang on a sudo password prompt during the corpus scan — bad
ergonomics for an LPE tool whose whole point is to get root without
already having it.
Fix: write '-n -l' as separate flags, redirect stdin from /dev/null
so sudo cannot fall back to reading the tty even if PAM tries to
coerce one. Belt-and-suspenders against any tty prompt during --auto.
---
README.md | 2 +-
docs/RELEASE_NOTES.md | 23 +++++++++++++++++++
docs/index.html | 4 ++--
.../skeletonkey_modules.c | 4 +++-
.../skeletonkey_modules.c | 9 ++++++--
skeletonkey.c | 2 +-
6 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index f69ab31..8e07792 100644
--- a/README.md
+++ b/README.md
@@ -202,7 +202,7 @@ also compile (modules with Linux-only headers stub out gracefully).
## Status
-**v0.9.5 cut 2026-05-28.** 39 modules across 34 CVEs — **every
+**v0.9.6 cut 2026-05-28.** 39 modules across 34 CVEs — **every
year 2016 → 2026 now covered**. v0.9.0 added 5 gap-fillers
(`mutagen_astronomy` / `sudo_runas_neg1` / `tioscpgrp` / `vsock_uaf` /
`nft_pipapo`); v0.8.0 added 3 (`sudo_chwoot` / `udisks_libblockdev` /
diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md
index 4b9dca7..cbe7813 100644
--- a/docs/RELEASE_NOTES.md
+++ b/docs/RELEASE_NOTES.md
@@ -1,3 +1,26 @@
+## SKELETONKEY v0.9.6 — `--auto` no longer prompts for sudo password
+
+Two sudo modules' `detect()` bodies invoked `sudo -ln` to read the
+user's allowed-commands list. The intent was non-interactive — `-ln`
+should parse as `-l -n` (list + non-interactive). But some sudoers /
+PAM configurations have been observed prompting for a password
+anyway when the flags are bundled, defeating the point.
+
+That meant `skeletonkey --auto --i-know` could hang on a sudo
+password prompt during the corpus scan, even though the whole point
+of an LPE tool is to *get* root without already having it.
+
+Fix in `sudo_runas_neg1` and `sudoedit_editor`:
+
+- `-n -l` written as separate flags (instead of bundled `-ln`)
+- `
- v0.9.5 — released 2026-05-28
+ v0.9.6 — released 2026-05-28
SKELETONKEY
@@ -598,7 +598,7 @@ uid=0(root) gid=0(root)
who found the bugs.
diff --git a/modules/sudo_runas_neg1_cve_2019_14287/skeletonkey_modules.c b/modules/sudo_runas_neg1_cve_2019_14287/skeletonkey_modules.c
index 1992852..ffd607e 100644
--- a/modules/sudo_runas_neg1_cve_2019_14287/skeletonkey_modules.c
+++ b/modules/sudo_runas_neg1_cve_2019_14287/skeletonkey_modules.c
@@ -106,7 +106,9 @@ static bool get_sudo_version(const char *sudo_path, char *out, size_t outsz)
static bool find_runas_blacklist_grant(const char *sudo_path, char *cmd_out, size_t cap)
{
char cmd[512];
- snprintf(cmd, sizeof cmd, "%s -ln 2>/dev/null", sudo_path);
+ /* -n -l separated + stdin closed: see sudoedit_editor for the same
+ * pattern + rationale. `--auto` must never block on a tty prompt. */
+ snprintf(cmd, sizeof cmd, "%s -n -l /dev/null", sudo_path);
FILE *p = popen(cmd, "r");
if (!p) return false;
char line[512];
diff --git a/modules/sudoedit_editor_cve_2023_22809/skeletonkey_modules.c b/modules/sudoedit_editor_cve_2023_22809/skeletonkey_modules.c
index 261721e..11a8cb9 100644
--- a/modules/sudoedit_editor_cve_2023_22809/skeletonkey_modules.c
+++ b/modules/sudoedit_editor_cve_2023_22809/skeletonkey_modules.c
@@ -149,8 +149,13 @@ static bool get_sudo_version(const char *sudo_path, char *out, size_t outsz)
static bool find_sudoedit_target(const char *sudo_path, char *out, size_t outsz)
{
char cmd[512];
- /* -n: non-interactive (no password prompt); -l: list. */
- snprintf(cmd, sizeof cmd, "%s -ln 2>&1", sudo_path);
+ /* -n: non-interactive (no password prompt); -l: list. The two flags
+ * are written separately and stdin is redirected from /dev/null so
+ * sudo cannot fall back to a tty prompt even if the local PAM stack
+ * tries to coerce one (some sudoers + pam_unix configurations have
+ * been observed prompting despite `-n` when the flags are bundled
+ * as `-ln`). Belt-and-suspenders so `--auto` never blocks on input. */
+ snprintf(cmd, sizeof cmd, "%s -n -l &1", sudo_path);
FILE *p = popen(cmd, "r");
if (!p) return false;
diff --git a/skeletonkey.c b/skeletonkey.c
index 255a0d1..9f1c7da 100644
--- a/skeletonkey.c
+++ b/skeletonkey.c
@@ -35,7 +35,7 @@
#include
#include
-#define SKELETONKEY_VERSION "0.9.5"
+#define SKELETONKEY_VERSION "0.9.6"
static const char BANNER[] =
"\n"