Security boundaries
See nah docs threat-model for adversary/trust assumptions.
nah evaluates calls reaching a loaded adapter and blocks definite findings and protected-state changes outside maintenance.
Enforced
- 46 guards span seven classes; 29 default on.
- nah only blocks/delegates; guards never authorize.
- Project guards need trust/activation and pin bundle bytes.
- Analyzer/custom-guard failure adds no finding by default; other evidence
decides.
--fail-closedblocks explicit failures/bounded refusals. Completed live failures enter the redacted log when writable. - Understood nah-state/executable/authority changes and host power block;
optional
sys-service-stopcovers service and stop-all container shutdown. - Active adapters protect reviewed hook/loading paths, lifecycle/removal, and bypass launches.
- When space allows, the 8 MiB redacted log prioritizes up to 200 recent blocks
on compaction.
nah test --json/custom guards may expose unredacted modeled input and inline code. - Credential and network-flow guards block modeled access to dangerous sinks.
secrets-store-readdefaults on; its evidence feedssecrets-exfileven when disabled. - Hosted Git guards cover exact repositories (on) and reviewed static resources (off).
registry-unpublishdefaults on for npm unpublish, RubyGems yank, and published-name owner changes.registry-publishdefaults off for reviewed publishing; supported dry runs delegate.- Filesystem guards cover auth/identity, profiles, startup, outside-project
recursive deletion, and provable world-write or setuid/setgid
chmod; profile, startup-management, outside-workspace, and permission-weaken guards default off. infra-container-reset(on) blocks Podman reset;infra-container-volume-delete(off), broad volume prune and Composedown/rmvolume removal;infra-iac-destroy(off), whole-stack IaC. Compose files are not inspected, and Compose excludes external volumes fromdown -v. Narrow/dry-run and named container or volume removal, plus targeted/saved/ambient/other IaC, delegates.infra-k8s-deletedefaults off and blocks static namespace deletion, reviewed cluster-resource deletion, and bulk reviewed namespaced-resource deletion throughkubectl. Named application resources and client/server dry runs delegate; manifest, kustomize, stdin, raw, dynamic, and unknown-kind selections are partial and do not reach the guard.storage-backup-destroyis on for whole Borg repos or all Restic/Velero backups.storage-recursive-deleteis off: deletion/sync is routine; argv hides purpose.storage-snapshot-deleteis off: backup rotation routinely deletes snapshots.
Not enforced
- Runtime hook/trust, UI, approvals/permissions, deadlines, and configuration outside interception.
- Unhooked/remote/human calls; runtime bugs/trusted plugins/opaque programs; unobservable effects/filesystems.
- Secret content under unclassified names: guards inspect paths/effects, not contents.
- Secret-store gaps: KMS/access removal, REST, dynamic/unreviewed syntax.
- Custom guards are trusted, unsandboxed executables.
- Unmodeled remote deletion routes, unresolved targets, branches, tags, renames, and transfers.
- Registry excludes reversible yanks/deprecations, listing/admin, ambiguous targets, web/REST-only changes, and unmodeled ecosystems. Unknown/opaque input delegates. Fail-closed denies malformed/no-decision input only when loaded; missing hooks/binaries, runtime failure/bypass, and broken pipes remain outside.
Delegate is not approval
delegate means no guard blocked. The runtime applies its sandbox or approval;
some execute delegated calls by default. Read nah docs runtimes.
nah log and the TUI summarize failures retained in the audit log;
nah why <id> shows the typed failures attached to one decision.
Credential and network flow
secrets-credentials covers paths, not CLIs; secrets-env covers .env
reads/copies and credential-variable output, not presence or writes.
secrets-store-read covers value reads except run/inject and concealed
listings. secrets-store-destroy covers permanent destruction;
secrets-store-delete, other reviewed deletes. Both exclude archive/non-executing forms.
Network guards follow visible data/code through modeled shell flows. Opaque and
prior provenance remain boundaries. Unresolved/bounded analysis is partial;
uncertainty doesn't block; recognized danger still reaches guards.
See nah docs guards.
PowerShell and cmd lower reviewed operations and exact argv into typed effects;
unproven behavior stays partial. powershell and pwsh differ; ambiguous
curl/wget aliases never invent writes.
Trust and configuration
nah blocks understood agent attempts to trust or untrust projects, change guard
state or runtime wiring, open nah tui, start a nap, or edit protected state.
Agents may edit inert user or project .nah/guards/ proposals and give the
human an exact out-of-band command. Before trust, .nah/project.toml may only
enable built-ins; an explicit global disable overrides it.
Path guards exclude reads. Gaps include Windows Run keys, schtasks,
runtime/offline/editor systemctl, launchctl bootstrap/bootout, dynamic input,
arbitrary executables, and scripted editors without a proven classified write.
Operator maintenance
nah nap pauses self-protection user-wide for 10 minutes; guards keep running.
nah nap --all pauses all non-permanent enforcement and does not run custom
guards. nah wake ends either nap.
Starting or extending a nap needs an operator terminal. Invalid or expired authenticated state fails awake; direct mutation of its state, key, or lock always blocks. A nap is user-global, and its changes persist.
Self-protection blocks understood mutation of nah, active wiring, executable
aliases, and ancestors. Windows drive/UNC paths normalize; device/reparse paths
fail. %USERPROFILE%\.nah has an inheritable user/SYSTEM/Administrators
DACL; nap keys allow only their owner. Opaque or unhooked work remains the
user's responsibility.