Apply a Security Policy
Drop YAML fragments into /etc/dotsecenv/policy.d/ so an admin can constrain every dotsecenv user on a machine, then verify the merged result with dotsecenv policy validate.
Prerequisites
Section titled “Prerequisites”- dotsecenv v0.6.0 or later
sudoon the host (fragments must be owned by root)- The two fragments from
examples/04-policy-directory/:00-corp-baseline.yamland99-team-overrides.yaml
-
Create the policy directory
It must be owned by root and not writable by anyone else, or dotsecenv refuses to start.
Terminal window sudo install -d -o root -g root -m 0755 /etc/dotsecenv/policy.d -
Install the baseline fragment
00-corp-baseline.yamlsets the org-wide floor: FIPS-gradeapproved_algorithms, twoapproved_vault_pathspatterns, and twobehavior.*flags.Terminal window sudo install -m 0644 -o root -g root \00-corp-baseline.yaml /etc/dotsecenv/policy.d/00-corp-baseline.yaml -
Install the team override
99-team-overrides.yamlloads last. It pinsgpg.programand appends one moreapproved_vault_pathspattern.Terminal window sudo install -m 0644 -o root -g root \99-team-overrides.yaml /etc/dotsecenv/policy.d/99-team-overrides.yaml -
Validate the merge
Terminal window dotsecenv policy validate# ✓ policy valid (2 fragment(s) in /etc/dotsecenv/policy.d)This command does not load user config or open vaults, so it keeps working when the policy is broken and you need to inspect it.
-
Inspect the effective policy
Terminal window dotsecenv policy listEach field is annotated with the fragment it came from.
approved_vault_pathsshows the deduped union of both files;gpg.programshows99-team-overrides.yaml(last fragment to set a scalar wins).
How the two fragments combine
Section titled “How the two fragments combine”Filename order follows the Unix *.d convention (00-base, 50-team, 99-overrides), and that ordering does two different jobs depending on the field:
- Allow-list fields (
approved_algorithms,approved_vault_paths) take the union across fragments. The baseline’s two vault patterns plus the override’s one give three approved paths. Order does not matter here, and a later fragment cannot remove an entry an earlier one added. - Scalar fields (
gpg.program,behavior.*) take the last value set in lexical order.99-outranks00-, so the override’sgpg.programwins. The baseline’sbehavior.*flags survive because no later fragment touched them.
Exit codes
Section titled “Exit codes”policy validate returns a distinct exit code per failure category, so a CI job on the repo that ships your fragments can tell them apart:
| Condition | Exit code |
|---|---|
Valid policy (or no policy.d/ at all) | 0 |
Empty allow-list (approved_algorithms: []) | 1 (General error) |
Forbidden key (login:, vault:) or malformed YAML | 2 (Configuration error) |
| Insecure permissions or an unreadable fragment | 8 (Access denied) |
Policy is fail-closed. While a fragment is broken, every dotsecenv command on the machine refuses to run, including a routine secret get. A partially-readable policy directory is indistinguishable from tampering, so dotsecenv stops rather than fall back to user-only config. Fix or remove the offending file, then re-run dotsecenv policy validate until it returns 0.
Next steps
Section titled “Next steps”- Security Policies — the full merge contract, user-vs-policy intersection,
--jsonoutput, and path-matching rules. - Team Vault Setup — pin the same
approved_algorithmsfragment across development, staging, and production.