You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: THREAT_MODEL.md
+49Lines changed: 49 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -210,6 +210,55 @@ wraps armed runs in a hard 10-minute watchdog.
210
210
restrictive mode unless `--socket-mode 0660` is set; connecting is gated by
211
211
HMAC + peer-UID regardless, but operators on shared hosts should set it.
212
212
213
+
### Nested execution and sandbox escape
214
+
215
+
Jinn Guard's enforcement boundary is **processes in a governed cgroup, as seen by
216
+
the host kernel.** The userspace intent layer is opt-in; the floor that governs a
217
+
process which *doesn't ask* is the host BPF-LSM, applied to governed cgroups. The
218
+
guarantee therefore rests on three assumptions, and a nested execution context can
219
+
attack each one: the governed tag is **un-sheddable**, the kernel's **namespace
220
+
view is authoritative**, and **no second kernel** is introduced.
221
+
222
+
| Vector | How it escapes | Severity |
223
+
| --- | --- | --- |
224
+
| Nested VM / microVM (qemu, Firecracker, gVisor, Kata, `/dev/kvm`) | Work runs under a **second kernel**; host BPF-LSM never sees the guest's syscalls | Critical |
225
+
| cgroup migration | Process moves itself/a child to a cgroup outside `governed_scope`; LSM no longer gates it | Critical |
226
+
| User namespace (`unshare`/`clone``CLONE_NEWUSER`) | Unprivileged agent gains in-ns "root", then creates mount/cgroup/pid namespaces | High |
227
+
| Mount namespace / `pivot_root` / bind-mount | Remaps the filesystem so a denied path looks allowed (generalizes the mount-boundary item above) | High |
228
+
| Nested container runtime (runc/podman/nspawn) | Child runs in fresh namespaces + possibly a fresh cgroup → ungoverned unless the tag is inherited | High |
229
+
| Interpreter chains (JG-ADV-2026-001) | A child interpreter performs the real work; a "soft sandbox" | Medium |
230
+
231
+
**Hardening direction (tracked in the hardening backlog and §10):**
232
+
233
+
1.**Un-sheddable governance tag.** Tag the *task* (BPF task-local storage)
234
+
inherited on `clone`/`fork`/`exec`, rather than relying on cgroup membership
235
+
alone; deny `cgroup.procs` writes that move a governed task out of scope. The
236
+
tag follows the process tree and cannot be dropped.
237
+
2.**Deny the nesting primitives by default for governed agents.** Add LSM
238
+
mediation for `mount`/`move_mount`, `pivot_root`, `chroot`, `setns`, and
239
+
namespace-creating `clone`/`unshare` flags. A governed agent with no legitimate
240
+
need is denied these, collapsing most of the surface.
241
+
3.**Treat VM launch as a hard boundary.** Host BPF-LSM cannot see inside a guest
242
+
kernel. Deny `/dev/kvm` and `/dev/vhost-*` and VMM binaries for governed
243
+
agents. A VM-capable governed agent is **outside the single-host enforcement
244
+
model unless a nested Jinn Guard instance governs the guest** (recursive
245
+
governance). This is stated as an explicit scope limit, not a claim.
246
+
4.**Key path decisions on inode/superblock identity, not path strings**, so
247
+
bind-mount/`pivot_root` remapping cannot fool the denylist (deepens the
248
+
mount-boundary fix).
249
+
5.**Drop nesting-enabling capabilities** (`CAP_SYS_ADMIN`, `CAP_SYS_CHROOT`) and
250
+
restrict unprivileged user-namespace creation for governed workloads.
251
+
6.**Default-deny dangerous operations at the kernel floor for governed scope**, so
252
+
a nested process that never speaks the protocol still cannot exec/mount/connect
253
+
outside policy — i.e., non-cooperation is safe.
254
+
7.**Detect even where permitted:** namespace/cgroup/mount/VM-device creation by a
255
+
governed agent is a high-signal event and is logged/alerted (canary-style).
256
+
257
+
Until items 1–3 land, operators should run governed agents **without
258
+
`CAP_SYS_ADMIN`** and with unprivileged user namespaces disabled
259
+
(`kernel.unprivileged_userns_clone=0` where the workload permits), which blocks
260
+
the high-severity namespace and mount vectors at the OS level today.
261
+
213
262
---
214
263
215
264
## 8. Threats to validity — the risk model and the formal guarantee
0 commit comments