Skip to content

fix: validate the pod name in emit_script, not only the CLI#36

Merged
lesnik512 merged 4 commits into
mainfrom
feat/validate-pod-name
Jul 12, 2026
Merged

fix: validate the pod name in emit_script, not only the CLI#36
lesnik512 merged 4 commits into
mainfrom
feat/validate-pod-name

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Summary

Make the public emit_script validate its pod name, closing the deferred "harden the pod-cleanup trap" item. The pod name is embedded into shell in several places — most fragile the single-quoted EXIT trap (trap '... podman pod rm -f <pod> ... ; podman secret rm <pod>-<name> ...' EXIT) and the raw <pod>-<name> store names in secret create/secret rm. The CLI already validated it, but emit_script/EmitOptions are public API, so a library caller could pass an unvalidated pod and produce a malformed/unsafe trap.

Design: planning/changes/2026-07-12.01-validate-pod-name-in-emit.md.

Fix — validate the identifier, don't shell-escape it

A pod name is an identifier, not free text, so the honest-subset move is to reject a bad one (exactly how the codebase already treats secret/config names) rather than contort the trap to survive arbitrary metacharacters:

  • POD_NAME_PATTERN (^[A-Za-z0-9][A-Za-z0-9_.-]*$) moves from cli.py to emit.py as the single source of truth; cli.py imports it.
  • emit_script's first statement validates options.pod and raises UnsupportedComposeError on a non-match, guarding every caller (library and CLI).
  • Both call sites use .fullmatch (not .match), closing the trailing-newline hole ("p\n" matches a $-anchored .match but breaks the trap) — the same lesson as the secret-name injection fix.
  • No trap or escaping changes: a validated pod name is charset-inert, so shlex.quote is a no-op and the existing emission is provably safe.

Testing

just test-ci at 100% coverage (354 tests), just lint-ci clean, just check-planning OK. emit_script now raises on six adversarial pod values (single-quote injection, space, $(...), empty, leading dash, trailing newline); a valid pod still emits; the CLI's existing rejection (exit 2, same message) is unchanged.

An adversarial whole-branch review confirmed the security property is fully closed — the guard is emit_script's unconditional first statement, every char the pattern admits is in shlex.quote's safe class (so no nested quote ever enters the single-quoted trap), and both halves of every <pod>-<name> store name are validated.

Docs / planning

Retires the trap-hardening entry from deferred.md (its revisit trigger — a library-API test with adversarial pod values — is now met), and records the pod-name identifier constraint in architecture/supported-subset.md.

@lesnik512 lesnik512 merged commit 9c05032 into main Jul 12, 2026
6 checks passed
@lesnik512 lesnik512 deleted the feat/validate-pod-name branch July 12, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant