Send the 802.1X password over stdin instead of argv

argv is world-readable in /proc for every local process while the
connection attempt runs. Create the profile without the secret, then
set it through nmcli's scriptable connection editor, which reads from
stdin.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-07-24 10:50:58 -07:00
co-authored by Claude Fable 5
parent 840832cfde
commit 6963432600
2 changed files with 22 additions and 3 deletions
+7 -2
View File
@@ -232,11 +232,16 @@ function isProtected(security, openSecurity) {
return security !== openSecurity
}
// The password arrives on stdin and reaches nmcli through the scriptable
// `connection edit` editor -- argv is world-readable in /proc, so the secret
// must never be an argument (printf is a bash builtin, so no process spawns
// with it either).
var enterpriseConnectScript =
"u=$(uuidgen);" +
"u=$(uuidgen); IFS= read -r pw;" +
" nmcli connection add type wifi con-name \"$1\" ssid \"$1\" connection.uuid \"$u\"" +
" wifi-sec.key-mgmt wpa-eap 802-1x.eap peap 802-1x.phase2-auth mschapv2" +
" 802-1x.identity \"$2\" 802-1x.password \"$3\" 802-1x.auth-timeout 8" +
" 802-1x.identity \"$2\" 802-1x.auth-timeout 8 >/dev/null" +
" && printf 'set 802-1x.password %s\\nsave\\nquit\\n' \"$pw\" | nmcli connection edit uuid \"$u\" >/dev/null" +
" && nmcli connection up uuid \"$u\"" +
" || { nmcli connection delete uuid \"$u\" >/dev/null 2>&1; false; }"
+15 -1
View File
@@ -579,10 +579,24 @@ Panel {
function connectEnterprise(ssid, identity, passphrase) {
runNetworkAction("connect", networkForSsid(ssid), function(network) {
Quickshell.execDetached(["bash", "-c", Model.enterpriseConnectScript, "nmcli-eap", ssid, identity, passphrase])
enterpriseConnect.secret = passphrase
enterpriseConnect.command = ["bash", "-c", Model.enterpriseConnectScript, "nmcli-eap", ssid, identity]
enterpriseConnect.running = true
})
}
// Creates and activates the 802.1X profile (see Model.enterpriseConnectScript).
// The password goes over stdin, never argv.
Process {
id: enterpriseConnect
property string secret: ""
stdinEnabled: true
onStarted: {
write(secret + "\n")
secret = ""
}
}
function disconnect(network) {
runNetworkAction("disconnect", network || connectedWifiNetwork, function(net) { net.disconnect() })
}