Debian GNU/Linux · Boot & system hardening

Stop unconfined unprivileged processes from switching AppArmor profiles

When it fails: Unprivileged unconfined processes can move to a more permissive AppArmor profile. A process with no profile can use aa-exec or change_profile to pick a profile that grants rights it should not have.

CB-DEB-BOOT-009lowactiveautomatedautomated fixprofile core

As released in v0.1.1 beta · pre-release. Current state.

Description

kernel.apparmor_restrict_unprivileged_unconfined turns on the AppArmor restrictions for processes that are both unprivileged and unconfined (running without any profile). With 1, such a process cannot use change_profile (for example through aa-exec) to move itself to another profile.

Rationale

Some AppArmor profiles grant rights that unconfined processes do not have by default, such as creating user namespaces. Without this restriction, any local process could switch to such a profile and use those rights, which bypasses the policy.

Impact

Unprivileged users can no longer run programs under a chosen profile with aa-exec. Programs launched normally get their profile attached as usual.

Applies when

Versions: 13

The sysctl only exists in kernels that carry the AppArmor unprivileged restriction feature. The Debian 12 kernel does not have it.

Setting

Locationsysctl `kernel.apparmor_restrict_unprivileged_unconfined`, persisted in `/etc/sysctl.d/`
Default0
Recommended1

Audit

Run sysctl kernel.apparmor_restrict_unprivileged_unconfined. The value must be 1.

Automated: every check must pass. Scanners report each check by its id.

running

Running value of kernel.apparmor_restrict_unprivileged_unconfined.

key: kernel.apparmor_restrict_unprivileged_unconfined
value: 1

Remediation

Create /etc/sysctl.d/60-cirsec.conf containing kernel.apparmor_restrict_unprivileged_unconfined = 1, then run sysctl --system.

Restartnone
Disruptionlow

Rollback

Remove the line from /etc/sysctl.d/60-cirsec.conf and run sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0.

set

Generated from check running: the engine writes the fix for every output, it sets the expected value and the check runs again after.

Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.

References

Mappings

FrameworkIDRelationNote
NIST SP 800-53 Rev. 55.1.1AC-3related

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

People and lifecycle

Authors
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64, BIOS boot. Fails on a fresh install (0); generated fix sets 1; kept after reboot. Debian 12 reports not_applicable as expected.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr