Here’s a fix that I worked out in a chatgpt session over a couple of hours. It amalgamates elements of solutions posted by others on this forum. I do not pretend to understand all of it. So please verify and use at your own discretion.
The rest of this post was drafted by chatgpt, but I read through if carefully before posting and it does indeed reflect the fix that I implemented .
Ubuntu 24.04 (AppArmor 4.x) + kernel 6.2+ (e.g. 6.8): “Terminal sandbox could not start” / Step 2.5/7 loopback NETLINK_ROUTE bind fails
Symptoms / logs typically show:
-
Cursor popup: “Terminal sandbox could not start… AppArmor…”
-
~/.config/Cursor/logs/.../exthost.log:
Failed to apply sandbox: Step 2.5/7 (loopback setup) ... failed to bind NETLINK_ROUTE socket
-
kernel audit:
apparmor="DENIED" ... profile="cursor_sandbox" ... family="netlink" sock_type="raw" ... denied="bind"
Root cause (in this failure mode): Cursor’s shipped /etc/apparmor.d/cursor-sandbox is incomplete on Ubuntu 24.04+ and blocks the helper from doing rtnetlink/loopback setup (and sometimes userns / newuidmap/newgidmap bits). See related threads:
Below is an upgrade-resistant fix that avoids global sysctl weakening and avoids “allow-all”.
0) Confirm you have this exact failure mode
grep -R "Failed to apply sandbox" -n ~/.config/Cursor/logs | tail -n 60
sudo journalctl -k -b --since "10 minutes ago" --no-pager | \
grep -iE 'apparmor="DENIED"|cursor_sandbox|unprivileged_userns' | tail -n 200
If you see Step 2.5/7 (loopback setup) + netlink raw bind denied, proceed.
1) Make the AppArmor profile upgrade-resistant (dpkg diversion)
Rationale: Cursor updates can overwrite /etc/apparmor.d/cursor-sandbox without prompting. dpkg-divert preserves your maintained file while still letting the vendor’s new profile install alongside as .distrib for diff/merge. The .predivert.date file is your backup.
sudo cp -a /etc/apparmor.d/cursor-sandbox /etc/apparmor.d/cursor-sandbox.predivert.$(date +%F_%H%M%S)
sudo dpkg-divert --local --rename --add \
--divert /etc/apparmor.d/cursor-sandbox.distrib \
/etc/apparmor.d/cursor-sandbox
Then base your maintained file on the vendor profile:
sudo cp -a /etc/apparmor.d/cursor-sandbox.distrib /etc/apparmor.d/cursor-sandbox
2) Patch /etc/apparmor.d/cursor-sandbox structurally (minimal edits)
Rationale: keep the vendor file mostly intact, add only what’s needed for Ubuntu 24.04/AppArmor 4.x and future helper renames, and delegate permissions to a local include.
Edit:
sudoedit /etc/apparmor.d/cursor-sandbox
Make these changes:
(a) Add at top (AppArmor 4.x compatibility)
abi <abi/4.0>,
include <tunables/global>
(b) Attach profiles to both helper names (rename-proof)
Change the profile lines to:
profile cursor_sandbox /usr/share/cursor/resources/app/resources/helpers/{cursor-sandbox,cursorsandbox} {
...
}
profile cursor_sandbox_remote /home/*/.cursor-server/bin/*/*/resources/helpers/{cursor-sandbox,cursorsandbox} {
...
}
(c) Ensure userns, is enabled inside both blocks
Uncomment/add the following line to both blocks:
userns,
(d) Make the mr rule match the brace path in both blocks
/usr/share/cursor/resources/app/resources/helpers/{cursor-sandbox,cursorsandbox} mr,
and
/home/*/.cursor-server/bin/*/*/resources/helpers/{cursor-sandbox,cursorsandbox} mr,
(e) Add a local include in both blocks
Rationale: keep your policy deltas in one place.
#include if exists <local/cursor-sandbox>
Note: #include is an AppArmor preprocessor directive (not a comment).
(f) If you see capname="net_admin" denials in journalctl, add the following line to both profile blocks; otherwise you can omit it.
capability net_admin,
3) Put the actual missing permissions in /etc/apparmor.d/local/cursor-sandbox
Rationale: fix Step 2.5/7 (netlink) and common userns/newuidmap IPC needs without “allow all”.
sudo install -d -m 0755 /etc/apparmor.d/local
sudo tee /etc/apparmor.d/local/cursor-sandbox >/dev/null <<'EOF'
# Required on Ubuntu 24.04+ restricted userns
userns,
# Required for Step 2.5/7 loopback/rtnetlink setup
network netlink raw,
network netlink dgram,
# Commonly required for sandbox IPC
network unix stream,
network unix dgram,
# newuidmap/newgidmap may need this
capability dac_override,
# If you create cursor-system profile below:
signal (send, receive) peer=cursor-system,
EOF
4) Optional: add cursor-system to avoid disabling Ubuntu’s userns restriction globally
Rationale: some setups hit Ubuntu’s unprivileged_userns mediation; this avoids turning off kernel.apparmor_restrict_unprivileged_userns system-wide. This is “unconfined” for Cursor itself (which is typically unconfined anyway), but explicitly allows userns while keeping the global hardening on.
sudo tee /etc/apparmor.d/cursor-system >/dev/null <<'EOF'
abi <abi/4.0>,
include <tunables/global>
profile cursor-system "/usr/share/cursor/cursor" flags=(unconfined) {
userns,
}
EOF
5) Reload AppArmor profiles
sudo apparmor_parser -r /etc/apparmor.d/cursor-sandbox
sudo apparmor_parser -r /etc/apparmor.d/cursor-system
sudo aa-status | grep -i cursor
Restart Cursor.
6) Validate (no new denials)
sudo journalctl -k -b --since "2 minutes ago" --no-pager | \
grep -iE 'cursor_sandbox|apparmor="DENIED"|unprivileged_userns'
If clean and popup is gone, you’re done.
7) After each Cursor upgrade: diff & merge safely
Rationale: vendor may add new required rules in future; diversion keeps both versions available.
diff -u /etc/apparmor.d/cursor-sandbox.distrib /etc/apparmor.d/cursor-sandbox | less
Avoid the chattr +i /etc/apparmor.d/cursor-sandbox approach: it can cause apt/dpkg upgrade failures or leave the package half-configured. dpkg-divert is the packaging-native way to prevent overwrites while still receiving upstream changes for review.