Skip to content

Forum

AI Assistant
Notifications
Clear all

Guide: Hardening Claude Code's subprocess execution with AppArmor

4 Posts
4 Users
0 Reactions
1 Views
(@newb_selfhost_kat)
Eminent Member
Joined: 1 week ago
Posts: 22
Topic starter
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
  [#385]

Hi everyone. I'm pretty new to OpenClaw and trying to secure my setup. I'm running the Nano Claw on a home Ubuntu server.

I saw that Claude Code can execute subprocess commands, which is powerful but also a bit scary. I read about AppArmor being a way to lock that down. Can someone walk me through the basic steps? Like, how do I create a profile for it, and what kind of rules should I start with to allow it to work but not do anything risky? I learn best with concrete examples.



   
Quote
(@tinker_selfhost_anna)
Active Member
Joined: 1 week ago
Posts: 7
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

Hey, great question! AppArmor is a solid choice for this. I ran into a similar need when I was playing with Claude Code in my own lab.

Start by checking if it's already confined: `aa-status | grep -i claw`. If not, you can generate a base profile with `aa-genprof` while running some typical tasks. But for a tighter fit, I'd write a minimal one manually. Here's a skeleton to put in `/etc/apparmor.d/claude-code`:

```
profile claude-code /usr/local/bin/claude-code {
# Basic runtime access
/usr/local/bin/claude-code mr,
/usr/lib/**.so* mr,

# Allow writing to its own cache/tmp, deny elsewhere
/tmp/claude-* rw,
deny /etc/** w,
deny /home/*/** wlx,

# Maybe allow read for your project dirs only
/home/user503/projects/** r,
}
```

Reload with `sudo apparmor_parser -r /etc/apparmor.d/claude-code`. The key is to start super restrictive, then watch `/var/log/audit/audit.log` or `journalctl` for denials when you run actual tasks, and loosen only what's needed.

Honestly, after my own near-miss, I'd also pair this with a dedicated network namespace and cgroups limits. AppArmor stops file system mischief, but won't limit fork bombs or network calls.


Better safe than pwned.


   
ReplyQuote
(@new_hamster)
Eminent Member
Joined: 1 week ago
Posts: 22
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

That's a really helpful skeleton, thanks! I'm definitely trying this on my test VM first.

I'm a bit nervous about manually editing the profile though. You mentioned starting restrictive and watching for denials. If I lock it down too much and Claude Code can't start at all, how do I even see the logs to fix it? Do I need to have a separate terminal open with `journalctl -f` running before I launch it, or is there a better way?



   
ReplyQuote
(@ghost_wrangler)
Eminent Member
Joined: 1 week ago
Posts: 20
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

Good skeleton, but the `/usr/lib/**.so*` rule is a bit too permissive for a hardening exercise. It grants memory read access to all shared objects under `/usr/lib`, which includes a vast number of unrelated libraries. A more precise baseline would be to allow `/**/lib*.so*` for standard linker resolution, then specifically deny sensitive paths like `/usr/lib/debug/**`.

Also, the mention of network namespaces is critical. An AppArmor profile without network rules defaults to allowing all network access. You need explicit `deny network` or specific `network` rules to restrict that vector.



   
ReplyQuote