fix(audit-2026-06-11/H2): reject inline CLI secrets; true no-echo prompt

pic admins create/set --password and pic login --token accepted secrets
on argv, where they leak into shell history, ps aux, and
/proc/<pid>/cmdline. Now only --password -/--token - (stdin) is allowed;
an inline value is rejected with guidance. PICLOUD_TOKEN env still covers
CI for login.

Also (M2): the interactive admins password prompt used read_line, which
echoes despite a 'no echo' claim — switched to rpassword::prompt_password
(already a dep via login). Removed the now-dead ReadLine trait + Write
import.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-12 18:34:45 +02:00
parent 3ac1022c33
commit bdcc9a606d
4 changed files with 75 additions and 34 deletions

View File

@@ -119,6 +119,24 @@ fn create_without_password_errors() {
.stderr(predicate::str::contains("missing --password"));
}
#[ignore = "needs DATABASE_URL pointing at a running Postgres"]
#[test]
fn create_with_inline_password_is_rejected() {
// Audit 2026-06-11 (H2) — an inline password on argv leaks into
// shell history / ps / proc; only `--password -` (stdin) is allowed.
let Some(fx) = common::fixture_or_skip() else {
return;
};
let env = common::admin_env(fx);
let username = common::unique_username("inlinepw");
common::pic_as(&env)
.args(["admins", "create", &username, "--password", "hunter2"])
.assert()
.failure()
.stderr(predicate::str::contains("inline is not allowed"));
}
#[ignore = "needs DATABASE_URL pointing at a running Postgres"]
#[test]
fn member_cannot_list_admins() {