jdx/mise · critical

refusing firewall default incoming {} without SSH_CONNECTION

Error message

refusing firewall default incoming {} without SSH_CONNECTION because process ancestry could not be inspected; set allow_lockout = true to acknowledge the lockout risk

What it means

The same lockout guard with an even weaker position: `SSH_CONNECTION` is absent and process-ancestry inspection returned no verdict (None), so mise cannot even tell whether the current process derives from SSH. Because an uninspectable session might be the one about to be cut off by a deny-by-default incoming policy, it fails closed and demands an explicit `allow_lockout = true` acknowledgment.

Source

Thrown at src/system/firewall.rs:477

        &self,
        rules: &[FirewallRule],
        backend: Option<FirewallBackend>,
        ssh_ancestor: Option<bool>,
    ) -> Result<()> {
        if self.state != FirewallState::Enabled
            || self.default_incoming == FirewallPolicy::Allow
            || self.allow_lockout
        {
            return Ok(());
        }
        let Some(connection) = &self.ssh_connection else {
            return match ssh_ancestor {
                Some(false) => Ok(()),
                Some(true) => bail!(
                    "refusing firewall default incoming {} from an SSH-derived process without SSH_CONNECTION: mise cannot verify that remote access will survive; preserve SSH_CONNECTION or set allow_lockout = true",
                    self.default_incoming.ufw()
                ),
                None => bail!(
                    "refusing firewall default incoming {} without SSH_CONNECTION because process ancestry could not be inspected; set allow_lockout = true to acknowledge the lockout risk",
                    self.default_incoming.ufw()
                ),
            };
        };
        let mut covered = false;
        for rule in rules.iter().filter(|rule| {
            rule.state == FirewallRuleState::Present
                && rule.direction == FirewallDirection::Incoming
                && rule
                    .protocol
                    .is_none_or(|protocol| protocol == FirewallProtocol::Tcp)
                && rule
                    .port
                    .is_none_or(|port| port.contains(connection.server_port))
                && rule
                    .source
                    .is_none_or(|source| source.contains(&connection.peer))

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Set `allow_lockout = true` in `[bootstrap.linux.firewall]` only once you can prove access survives (out-of-band console, or a pre-existing allow rule for your IP/port).
  2. Run from a normal interactive SSH login shell with SSH_CONNECTION preserved so the guard verifies rule coverage instead of failing closed.
  3. Relax the sandbox/hidepid restriction for this invocation so ancestry inspection works.
  4. Pre-add an unrestricted-interface TCP allow for your management peer and port, then re-run.

Example fix

# before
mise bootstrap firewall apply
# error: refusing firewall default incoming deny without SSH_CONNECTION because
# process ancestry could not be inspected ...

# after — from the direct SSH shell, with the variable intact
ssh host
mise bootstrap firewall apply
# or, with console access available, acknowledge the risk:
# [bootstrap.linux.firewall]
# allow_lockout = true
Defensive patterns

Strategy: try-catch

Validate before calling

# pre-flight in restricted environments: prove reachability or stop
[ -n "$SSH_CONNECTION" ] || { echo 'ancestry may be uninspectable here; run from the login shell or set allow_lockout'; exit 1; }

Try / catch

if ! mise bootstrap firewall apply 2>fw.err; then
  if grep -q "process ancestry could not be inspected" fw.err; then
    echo "sandboxed run; re-run from the SSH login shell or acknowledge via allow_lockout"; exit 1
  fi
  cat fw.err; exit 1
fi

Prevention

When it happens

Trigger: `mise bootstrap firewall apply` with deny-ish `default_incoming`, no `SSH_CONNECTION` in the environment, and the ssh_ancestor probe indeterminate — hardened /proc permissions (hidepid), containers/sandboxes hiding the parent chain, or unusual process trees that defeat inspection.

Common situations: Running inside containers, chroots, or restricted unprivileged environments where /proc ancestry is hidden; CI runners with strict sandboxing; environments where both environment variables and /proc are locked down for hygiene.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/f1e6fc9c8704006e. Report an issue: GitHub.