Files
Panama/tests/quickshell/ssh-keys-contract
T
Gabriel Brown 12f6b2a310 Let the contracts assert properties, not the machine they were written on
The first run of the suite on a laptop found five contracts asserting the
desktop instead of the code. settings-system pinned DP-2 at 4500x3000 in
XRGB2101010; it now asks Hyprland what is actually primary. ssh-keys hardcoded
id_ed25519; it now uses whichever key exists. switcher's live half stepped a
session with one window, which step() deliberately refuses. displays raced the
service's revert readback -- the compositor looks restored while verification
still holds busy, so an immediate apply was refused with its error already
cleared; the harness now exposes settled and the contract waits for it.

declared-dependencies gets an OPTIONAL list for docker: the aliases serve
machines that run Docker deliberately, Panama's runtime is rootless podman,
and a missing docker fails by naming the command, which is loud enough.

Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
2026-08-23 10:32:17 -04:00

121 lines
5.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# SSH keys, and the two things this page must never do.
#
# The rules:
#
# 1. A private key is never read for its contents and never leaves the
# machine's disk. Fingerprints and comments come from the .pub file.
# 2. No passphrase passes through this tool. Adding an encrypted key lets
# ssh-add prompt through the system's own askpass; collecting one here and
# handing it on would be a worse place for it to live, and putting one in
# argv would publish it to every process on the machine.
# 3. Key paths are confined to ~/.ssh, resolved and compared, so a name cannot
# walk out of the directory.
# 4. A control that cannot do what it says is not offered. gnome-keyring's
# agent lists every key it finds in ~/.ssh, so `ssh-add -d` reports
# "Identity removed" and the key is still offered a second later. Measured
# on this machine: a plain ssh-agent removes durably, that one does not.
# 5. Copying a public key never splices a path into shell source.
#
# Read-only against the real configuration. Nothing here adds, removes or
# rewrites a key, an agent entry, or a known host.
set -uo pipefail
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
helper="$repo_dir/config/dot/quickshell/scripts/panama-ssh-keys"
service="$repo_dir/config/dot/quickshell/services/SshKeys.qml"
page="$repo_dir/config/dot/quickshell/modules/settings/SshKeysPage.qml"
fail() {
printf 'ssh keys contract: %s\n' "$1" >&2
exit 1
}
for path in "$helper" "$service" "$page"; do
[[ -r "$path" ]] || fail "missing $path"
done
[[ -x "$helper" ]] || fail 'panama-ssh-keys is not executable'
field() { python3 -c "import json,sys; print(json.load(sys.stdin)$1)"; }
state="$("$helper" snapshot)" || fail 'snapshot failed'
# ── 1. Private key material never surfaces ──────────────────────────────────
#
# Checked against the payload rather than the source: whatever the code intends,
# what actually reaches the page must not contain key material.
printf '%s' "$state" | python3 -c "
import json, sys
raw = sys.stdin.read()
for marker in ('BEGIN OPENSSH PRIVATE KEY', 'BEGIN RSA PRIVATE KEY', 'BEGIN EC PRIVATE KEY'):
if marker in raw:
raise SystemExit(f'the snapshot contains {marker}')
state = json.loads(raw)
for key in state['keys']:
for name, value in key.items():
if isinstance(value, str) and len(value) > 200:
raise SystemExit(f'{name} is long enough to be key material')
" || fail 'private key material reached the snapshot'
# The helper must never read a private key for its bytes. The one place it opens
# one is ssh-keygen -y, which can only ever emit the public half.
grep -q 'read_text' "$helper" && ! grep -q 'KNOWN_HOSTS.read_text' "$helper" \
&& fail 'something reads a file directly that is not known_hosts'
# ── 2. No passphrase anywhere ───────────────────────────────────────────────
grep -qE '\-N["'"'"' ]' "$helper" \
&& fail 'ssh-keygen -N appears, which would put a passphrase in argv'
grep -qi 'passphrase' "$service" && ! grep -qi 'never\|prompt' "$service" \
&& fail 'the service mentions passphrases without saying it does not handle them'
# ── 3. Paths are confined ───────────────────────────────────────────────────
grep -q 'def resolve_key' "$helper" || fail 'key paths are not resolved before use'
grep -q 'resolved.parent != SSH_DIR' "$helper" \
|| fail 'a key path is not compared against the SSH directory, so it could escape'
reason="$(printf '%s' "$("$helper" agent-add /etc/hostname)" | field "['error']")"
[[ "$reason" == *"not in the SSH directory"* ]] \
|| fail "a path outside ~/.ssh was not refused with a reason (got: $reason)"
reason="$(printf '%s' "$("$helper" agent-add /home/nonexistent/.ssh/nope)" | field "['error']")"
[[ -n "$reason" ]] || fail 'a missing key was accepted'
reason="$(printf '%s' "$("$helper" forget-host 'not a host name')" | field "['error']")"
[[ "$reason" == *"not a host name"* ]] \
|| fail "an invalid host was not refused with a reason (got: $reason)"
# ── 4. A control that cannot deliver is not offered ─────────────────────────
grep -q 'durableRemoval' "$helper" \
|| fail 'the helper does not record whether removal from this agent sticks'
kind="$(printf '%s' "$state" | field "['agent'].get('kind','')")"
if [[ "$kind" == "gnome-keyring" ]]; then
# Whichever key this machine actually has. This used to hardcode
# id_ed25519, which asserted the author's machine: any other key name
# earned "That key no longer exists" instead of the refusal under test.
# No key at all means the property cannot be exercised here, not that it
# failed.
real_key="$(compgen -G "$HOME/.ssh/id_*.pub" | head -1)"
real_key="${real_key%.pub}"
if [[ -n "$real_key" ]]; then
reason="$(printf '%s' "$("$helper" agent-remove "$real_key")" | field "['error']")"
[[ "$reason" == *"does not stick"* ]] \
|| fail "removal against a keyring agent was not refused with its reason (got: $reason)"
fi
grep -q 'does not stick' "$page" \
|| fail 'the page does not say that removing a key from this agent has no effect'
fi
# ── 5. Copying does not build shell source from a path ──────────────────────
grep -q 'exec wl-copy < "\$1"' "$service" \
|| fail 'the public key copy does not pass its path as an argument'
printf 'ssh keys contract: ok\n'