Skip to content

Top-level unsafe_macos_seatbelt_rules appear to be overridden by later generated denies #1566

Description

@nichenke

What happened?

A top-level unsafe_macos_seatbelt_rules entry is accepted, survives into the resolved profile, and
has no effect on the access it names.

Tried against a profile that was reporting a denial on ~/.claude.json.tmp.<pid>.<hex>:

"unsafe_macos_seatbelt_rules": [
  "(allow file-write* (regex #\"^/Users/nic/\\.claude\\.json\\.tmp\\.[0-9]+\\.[0-9a-f]+$\"))"
]

nono profile show lists it under "Raw Seatbelt rules (unsafe_macos_seatbelt_rules)", so it is not
being stripped by strip_untrusted_unsafe_seatbelt_rules. The denial was unchanged.

A deliberately blunt rule used as a diagnostic — (allow file-write* (subpath "/Users/nic"))
also made no difference, referenced both by profile name and by file path.

What did you expect to happen?

Either the rule takes effect, or nono declines it with a reason.

Possible cause

crates/nono/src/sandbox/macos.rs emits platform rules "last so targeted denies win under Seatbelt's
last-rule-wins semantics. See #970", and the same platform_rules list carries nono's own
protected-root denies. If a deny is appended after a user-supplied allow, the allow can never win.

Note the schema documents last-wins placement only for the CommandSandboxConfig variant — "emitted
after the generated denies (including the exec gate's (deny process-exec*)), so a later (allow …)
wins" — while the top-level field's description makes no such promise. That asymmetry is consistent
with what I observed, though I did not trace which specific deny wins.

Why it matters

The field is documented as an "expert escape hatch", and an escape hatch that is silently inert is
worse than one that refuses: it looks like coverage. If top-level rules genuinely cannot override
generated denies, saying so in the field description would be enough.

nono version

0.71.0 (code read at main f6a1519)

Operating system

macOS (Apple silicon)

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageNewly opened, not yet reviewed or assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions