--- title: "Security Design" html_title: "Enroll Security Design" description: "Threat model, trust boundaries, dangerous mode, SOPS, root PATH safety, and manifest safety for Enroll." ---
Security design

Safe-by-default collection, explicit trust at apply time.

Enroll tries hard not to accidentally copy secrets or follow hostile paths, but it cannot decide whether a structurally valid host snapshot is safe to reproduce.

The most important warning

When manifesting, Enroll prints:

This harvest is structurally valid, but Enroll cannot prove it is semantically safe.
Only apply manifests generated from harvests whose provenance you trust.

Validation checks shape and consistency. It does not prove the captured configuration is a good idea, that service files are benign, or that the host was not already compromised.

Default secret avoidance

In normal mode, Enroll uses path deny-lists, symlink-safe file opening, file size limits, binary detection, and sampled content sniffing to avoid likely secrets and noisy data.

Safe-mode scanning treats common credential-looking assignments as sensitive, including password/pass/passwd/pwd/pw forms, API keys, auth tokens, client secrets, secret keys, cloud access key names, service-account key names, and similar patterns.

Comment caveat: Enroll ignores comments during the sensitive-content scan. If a real secret is commented out, it may still be captured in safe mode. Use SOPS or your own encryption when in doubt.

--dangerous

--dangerous disables likely-secret checks. It may copy private keys, TLS key material, tokens, passwords, cloud credentials, and user shell dotfiles into the harvest in plaintext.

Use it only when you intentionally want an aggressive disaster-recovery snapshot and you already know how the output will be protected.

SOPS is storage-at-rest protection

--sops writes encrypted .tar.gz.sops bundles for harvest and manifest outputs. It is not the same as generating Ansible Vault or SOPS-managed inventory variables.

enroll harvest --out ./secure-harvest --dangerous --sops <GPG_FINGERPRINT>
enroll manifest --harvest ./secure-harvest/harvest.tar.gz.sops \
  --out ./secure-manifest --sops <GPG_FINGERPRINT>

Decrypt and extract an encrypted manifest before running Ansible.

Filesystem and rendering hardening

  • Plaintext harvest/manifest output directories are created private and are refused when unsafe or unexpectedly pre-existing.
  • Root-run output refuses parent directories controlled by unprivileged users, except safe sticky boundaries such as /tmp with further child checks.
  • Source and artifact reads use no-follow semantics and reject symlinked components, non-regular files, hardlinks, and unexpected large inputs.
  • Directory harvests are frozen into a private temporary copy before validation and rendering to avoid post-validation swaps.
  • Tar/SOPS/remote inputs are extracted through safe extraction rules.
  • Harvested strings that look like Jinja are emitted as Ansible !unsafe data, while generated task scaffolding only accepts strict Enroll-controlled tokens.
Recommended workflow
  1. Harvest in normal mode first.
  2. Run enroll explain and enroll validate.
  3. Use targeted --include-path instead of broad --dangerous where possible.
  4. Encrypt outputs if they may contain sensitive data or leave the host.
  5. Run Ansible with --check --diff and review before applying.
Root PATH safety

When run as root, Enroll checks PATH for empty, relative, current-directory, or group/world-writable entries that could cause host tools to resolve to attacker-controlled binaries.

Use --assume-safe-path only in trusted automation where the PATH is intentional.

Out of scope
  • Proving harvested config is semantically safe
  • Protecting against a fully compromised root account
  • Guaranteeing generated Ansible is an ideal long-term design
  • Secret management after you intentionally disable safety checks