Skip to content

Agent era enhancements (exec, --output-format)#22

Open
mahmoud wants to merge 7 commits intoSimpleLegal:masterfrom
mahmoud:agent-era-enhancements
Open

Agent era enhancements (exec, --output-format)#22
mahmoud wants to merge 7 commits intoSimpleLegal:masterfrom
mahmoud:agent-era-enhancements

Conversation

@mahmoud
Copy link
Copy Markdown
Contributor

@mahmoud mahmoud commented Apr 2, 2026

decrypt-domain gains --output-format env|shell, --secret NAME (raw value, pipe-friendly), and a new exec subcommand:

  pprotect exec --domain prod -- ./myapp                                                                         

Decrypts domain, injects as env vars, scrubs PPROTECT_PASSPHRASE/PPROTECT_USER from child.

--prefix, --uppercase, --no-passthrough for name transformation and env isolation. execvpe on Unix, subprocess on Windows.

Added a bit about this to the README, plus 22 new tests including subprocess integration. Should be no breaking changes.

- Remove all Python 2 compat (unicode shims, cStringIO, imp, __future__)
- Add per-custodian KDF parameter storage (v1 pwdkm format)
 - v0 custodians (existing) continue using module-level OPSLIMIT/MEMLIMIT
 - v1 custodians store opslimit/memlimit in their pwdkm field
 - Backward compatible: v0 files load and work unchanged
- Add KDF_SENSITIVE and KDF_INTERACTIVE named parameter tuples
 - SENSITIVE: ~0.8s per KDF call (production default)
 - INTERACTIVE: ~0.1s per KDF call (dev/testing, 8x faster)
- Add --fast-crypto CLI flag for init/add-key-custodian
- Convert setup.py to pyproject.toml
- Modernize tox.ini (py39-py313)
- Expand test suite: 11 tests (was 4), covering v0/v1 round-trip,
 coexistence, KDF params, check_creds, audit log, error cases
- Bump version to 24.0.0dev
- KeyFile.migrate_owner: batch add owner across all domains
- KeyFile.get_custodian_domains: list domains a custodian owns
- set_key_custodian_passphrase: accept opslimit/memlimit params
- CLI: migrate-owner subcommand with confirmation prompt
- CLI: list-user-secrets subcommand (read-only)
- CLI: set-key-custodian-passphrase now supports --fast-crypto flag
- Tests for all new functionality
Raw-key custodians bypass argon2 entirely. The passphrase IS the
entropy (256 bits), so password stretching adds only latency.

Format: P<64 lowercase hex chars>P (e.g. P0a1b2c...P)

- v2 pwdkm format: version(1=0x02) + salt(8) + pubkey(32)
- _kdf_raw: sha512(passphrase + salt + name)[:32], no argon2
- generate_raw_passphrase(): creates P<64hex>P from os.urandom(32)
- is_raw_passphrase(): validates format
- KeyFile.add_raw_key_custodian(): creates v2 custodian
- CLI: add-raw-key-custodian subcommand
 - Generates key, displays once with stern warning
 - Requires typing YES to confirm key was saved
 - Aborts cleanly on decline
- v0/v1/v2 custodians coexist in same protected.yaml
- 22 tests (6 new)
Breaking change: --fast-crypto flag removed in favor of --key-type.

 pprotect add-key-custodian --key-type fast # was --fast-crypto
 pprotect add-key-custodian --key-type raw # was add-raw-key-custodian
 pprotect add-key-custodian # default: hard (unchanged)

New: rekey-custodian command
 Changes an existing custodian's key type and passphrase in one step.
 Re-encrypts all domain ownership keys automatically.

 pprotect rekey-custodian --key-type fast # move existing custodian to fast KDF
 pprotect rekey-custodian --key-type raw # move to raw key (generates P<hex>P)

Internal: KeyFile._replace_key_custodian extracted from
set_key_custodian_passphrase for reuse by rekey_custodian.

23 tests pass.
…mmand

Phase 1: Agent & Automation Security section in README.md
- Credential injection hierarchy (exec > passphrase-file > raw-key > env var)
- Output format examples for decrypt-domain
- Explicit non-goals (OAuth, SaaS, time-limited creds, per-secret ACL, MCP)
- Honest security note on exec vs adversarial exfiltration

Phase 2: decrypt-domain --output-format and --secret flags
- --output-format json (default) | env | shell
- env: double-quoted NAME="value" pairs, sorted by name
- shell: export NAME="value" pairs, eval-able
- --secret SECRET_NAME: single-secret filter
  - Without --output-format: raw value (for shell substitution)
  - With --output-format json: single-key JSON object
  - With --output-format env/shell: single formatted line
- Warns on stderr for secret names that aren't valid shell identifiers
- Escapes backslashes and double-quotes in env/shell output

Phase 3: pprotect exec subcommand
- pprotect exec --domain DOMAIN -- CMD [ARGS...]
- Decrypts domain, injects secrets as env vars into child process
- PPROTECT_PASSPHRASE and PPROTECT_USER always scrubbed from child env
- --no-passthrough: minimal env (PATH/HOME/TERM/LANG + secrets only)
- --prefix PREFIX: prepend PREFIX_ to secret env var names
- --uppercase: convert secret names to UPPER_CASE
- os.execvpe on Unix (replaces process), subprocess.run on Windows
- Testable _build_exec_env extracted for unit testing

Tests: 42 CLI tests (22 new), 66 total. All pass.
…sitive secret names

- --format → --output-format to match the implemented CLI flag
- Add note: secret names are case-sensitive, stored exactly as provided
- Use realistic example: db-pass (lowercase-hyphenated, the common convention)
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