Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
dab1dff
models R&D: pluggable registry, roster, training loop, benchmark, gov…
ringzerosec Sep 26, 2026
207c621
models: the RLCD brain is the product — document it, align every file…
ringzerosec Oct 2, 2026
bca286b
models: Laya fine-tune loop proven end to end on MPS — feeder, eval, …
ringzerosec Oct 3, 2026
2b1ad9d
models: replace Laya size/latency estimates with measured shipping-pa…
ringzerosec Oct 3, 2026
2b046b6
course: move into the private fork; add the private research track (P…
ringzerosec Oct 3, 2026
9dc6a79
course/private: add the Laya track L1-L10 (paper to implementation to…
ringzerosec Oct 3, 2026
6de5201
models: RESEARCH.md — System 1/2 direction, perception-stack architec…
ringzerosec Oct 3, 2026
3e7bfe2
models: Gero-4B zero-shot baseline (E0) and head-design lessons
ringzerosec Oct 4, 2026
a521ace
Discovery: inventory of AI agents, MCP servers, editor extensions and…
ringzerosec Oct 7, 2026
b24c35c
Prompt guard: secrets pasted into an agent prompt are stopped locally
ringzerosec Oct 7, 2026
774846f
postinst: register rz-hook for Claude Code UserPromptSubmit (prompt g…
ringzerosec Oct 7, 2026
a0c7deb
Capability profiles (observe): what each agent and MCP server may do
ringzerosec Oct 7, 2026
df7ccd6
Policy screen: one place for what AI on this machine may do
ringzerosec Oct 7, 2026
1df990e
UI copy: stop claiming enforcement the product does not do
ringzerosec Oct 7, 2026
4a3e5cf
Profiles become settable: watch/enforce modes, IP ranges, save from C…
ringzerosec Oct 7, 2026
374c71c
Self-protection: Ring Zero's config, token and unit are off-limits to…
ringzerosec Oct 7, 2026
2f38435
Tamper protection: the daemon cannot be killed, frozen or debugged, a…
ringzerosec Oct 7, 2026
7b4d5b7
Design review fixes: Discovery, Threats, Sessions
ringzerosec Oct 7, 2026
0313831
Policy screen redesign: posture strip, Protected data panel, chip cards
ringzerosec Oct 7, 2026
2d064c9
Protected data: hide the legacy [blockdir] marker too
ringzerosec Oct 7, 2026
17a15e5
Policy: switches for tamper protection, prompts and agent permissions…
ringzerosec Oct 7, 2026
85ceb37
UI: make opacity variants of theme colors render
ringzerosec Oct 8, 2026
23e5a31
App: plain message when the password window cannot open
ringzerosec Oct 8, 2026
86ec820
Agent controls: kernel blocks for admin tools, escape tools, instruct…
ringzerosec Oct 8, 2026
3545da5
Threats: say what was refused for agent-control blocks
ringzerosec Oct 8, 2026
022fedf
Permissions: every switch means limit; say watching, not would block
ringzerosec Oct 8, 2026
f7ef120
Profiles enforced in the kernel: programs and network per agent
ringzerosec Oct 8, 2026
aab6065
Live commentary: the agent's work narrated as it happens
ringzerosec Oct 8, 2026
2225292
Voice: pw-play needs --raw to read raw audio from stdin
ringzerosec Oct 8, 2026
f12ccd7
Voice: Kokoro-82M (af_heart) as the commentary voice, Piper as fallback
ringzerosec Oct 8, 2026
64d7988
Agents: judge by process, not thread; re-tag running agents at start
ringzerosec Oct 8, 2026
4fec024
Commentary for every agent, not only Claude Code
ringzerosec Oct 8, 2026
5ffd980
Refusal notices replace the threat modal
ringzerosec Oct 8, 2026
431fb3a
Agent permissions redesign: every agent, one choice per limit
ringzerosec Oct 8, 2026
5b2f4e9
Sessions: commentary tab, blocked events in red, working Terminate
ringzerosec Oct 8, 2026
170cb7a
Live commentary is text only: remove the voice
ringzerosec Oct 8, 2026
b7b87db
Narrator test: build the fake key at run time, not as a literal
ringzerosec Oct 8, 2026
2a555e2
Overview: an agent's connections to this machine itself are not secur…
ringzerosec Oct 8, 2026
30e774f
Discovery: list Hermes Agent and OpenClaw
ringzerosec Oct 9, 2026
6d41295
Agents can't install packages; package managers are never agents
ringzerosec Oct 9, 2026
a7dd828
Security history: every refusal, never hidden, with honest actions
ringzerosec Oct 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ GPL/bpf/vmlinux.h
.venv/
**/__pycache__/
*.pyc
models/data/
models/weights/
models/**/*.pt
models/**/*.safetensors
# course lab build artifacts — regenerable in the lab VM; keep the sources
course/labs/**/vmlinux.h
course/labs/**/*.o
course/labs/**/target/
course/labs/00-setup/hello
145 changes: 145 additions & 0 deletions GPL/bpf/agent_names.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/* SPDX-License-Identifier: GPL-2.0 */
// agent_names.h — which process names are AI agents. Shared by ringzero.bpf.c
// and stdiocap.bpf.c so both objects agree on what an agent is.
#ifndef RZ_AGENT_NAMES_H
#define RZ_AGENT_NAMES_H

#ifndef MAX_COMM_LEN
#define MAX_COMM_LEN 16
#endif

// End of the first word of a comm: NUL or space.
#define RZ_WORD_END(c, i) ((c)[i] == '\0' || (c)[i] == ' ')

// Package managers. They are never an agent by their own name: npm sets its
// process name to its command line ("npm i openclaw@"), so the package being
// installed would otherwise make npm look like the agent it installs. A package
// manager an agent starts is still part of that agent's tree (inherited at fork).
static __always_inline int is_package_manager(const char *c) {
// npm, npx
if (c[0] == 'n' && c[1] == 'p' && (c[2] == 'm' || c[2] == 'x') && RZ_WORD_END(c, 3))
return 1;
// pnpm, pnpx
if (c[0] == 'p' && c[1] == 'n' && c[2] == 'p' && (c[3] == 'm' || c[3] == 'x') && RZ_WORD_END(c, 4))
return 1;
// yarn
if (c[0] == 'y' && c[1] == 'a' && c[2] == 'r' && c[3] == 'n' && RZ_WORD_END(c, 4))
return 1;
// bun, bunx
if (c[0] == 'b' && c[1] == 'u' && c[2] == 'n' && (RZ_WORD_END(c, 3) || (c[3] == 'x' && RZ_WORD_END(c, 4))))
return 1;
// pip, pip3, pipx
if (c[0] == 'p' && c[1] == 'i' && c[2] == 'p' &&
(RZ_WORD_END(c, 3) || ((c[3] == '3' || c[3] == 'x') && RZ_WORD_END(c, 4))))
return 1;
// uv, uvx
if (c[0] == 'u' && c[1] == 'v' && (RZ_WORD_END(c, 2) || (c[2] == 'x' && RZ_WORD_END(c, 3))))
return 1;
// poetry
if (c[0] == 'p' && c[1] == 'o' && c[2] == 'e' && c[3] == 't' && c[4] == 'r' && c[5] == 'y' && RZ_WORD_END(c, 6))
return 1;
// cargo
if (c[0] == 'c' && c[1] == 'a' && c[2] == 'r' && c[3] == 'g' && c[4] == 'o' && RZ_WORD_END(c, 5))
return 1;
// gem
if (c[0] == 'g' && c[1] == 'e' && c[2] == 'm' && RZ_WORD_END(c, 3))
return 1;
return 0;
}

static __always_inline int is_ai_agent(const char *comm) {
if (is_package_manager(comm))
return 0;

// Known AI agent process names

// "claude" (matches claude, claude.real, claude-code, etc.)
if (comm[0] == 'c' && comm[1] == 'l' && comm[2] == 'a' && comm[3] == 'u' && comm[4] == 'd' && comm[5] == 'e')
return 1;

// "cursor"
if (comm[0] == 'c' && comm[1] == 'u' && comm[2] == 'r' && comm[3] == 's' && comm[4] == 'o' && comm[5] == 'r')
return 1;

// "copilot"
if (comm[0] == 'c' && comm[1] == 'o' && comm[2] == 'p' && comm[3] == 'i' && comm[4] == 'l' && comm[5] == 'o')
return 1;

// "codex"
if (comm[0] == 'c' && comm[1] == 'o' && comm[2] == 'd' && comm[3] == 'e' && comm[4] == 'x')
return 1;

// "ChatGPT" — OpenAI ChatGPT/Codex desktop app (Electron). Every process it
// spawns (main, zygote, renderer, gpu, network/storage utility) shares the
// comm "ChatGPT", so this one prefix covers the whole app. comm is compared
// case-sensitively, so match the app's real casing, plus the lowercase form.
if (comm[0] == 'C' && comm[1] == 'h' && comm[2] == 'a' && comm[3] == 't' &&
comm[4] == 'G' && comm[5] == 'P' && comm[6] == 'T')
return 1;
if (comm[0] == 'c' && comm[1] == 'h' && comm[2] == 'a' && comm[3] == 't' &&
comm[4] == 'g' && comm[5] == 'p' && comm[6] == 't')
return 1;

// "devin"
if (comm[0] == 'd' && comm[1] == 'e' && comm[2] == 'v' && comm[3] == 'i' && comm[4] == 'n')
return 1;

// "aider"
if (comm[0] == 'a' && comm[1] == 'i' && comm[2] == 'd' && comm[3] == 'e' && comm[4] == 'r')
return 1;

// "windsurf" (Codeium IDE)
if (comm[0] == 'w' && comm[1] == 'i' && comm[2] == 'n' && comm[3] == 'd' && comm[4] == 's')
return 1;

// "agy" (Antigravity CLI — Google Gemini successor)
if (comm[0] == 'a' && comm[1] == 'g' && comm[2] == 'y')
return 1;

// "antigravity"
if (comm[0] == 'a' && comm[1] == 'n' && comm[2] == 't' && comm[3] == 'i' && comm[4] == 'g')
return 1;

// "gemini" (legacy)
if (comm[0] == 'g' && comm[1] == 'e' && comm[2] == 'm' && comm[3] == 'i' && comm[4] == 'n' && comm[5] == 'i')
return 1;

// "gemini" (Gemini CLI)
if (comm[0] == 'g' && comm[1] == 'e' && comm[2] == 'm' && comm[3] == 'i' && comm[4] == 'n' && comm[5] == 'i')
return 1;

// "agent" — Cursor CLI binary (cursor-agent renames to "agent")
if (comm[0] == 'a' && comm[1] == 'g' && comm[2] == 'e' && comm[3] == 'n' && comm[4] == 't' && comm[5] == '\0')
return 1;

// "MainThread" — Cursor/Python agent main process (Python renames comm via prctl).
// Must be in is_ai_agent (not just is_runtime) because this IS the top-level
// agent process — it has no agent ancestor, so is_agent_child() would fail.
if (comm[0] == 'M' && comm[1] == 'a' && comm[2] == 'i' && comm[3] == 'n' &&
comm[4] == 'T' && comm[5] == 'h' && comm[6] == 'r' && comm[7] == 'e')
return 1;

// "opencode"
if (comm[0] == 'o' && comm[1] == 'p' && comm[2] == 'e' && comm[3] == 'n' && comm[4] == 'c')
return 1;

// "hermes"
if (comm[0] == 'h' && comm[1] == 'e' && comm[2] == 'r' && comm[3] == 'm' && comm[4] == 'e' && comm[5] == 's')
return 1;

// Any "claw"-family agent: the comm's FIRST WORD contains "claw"
// (nanoclaw, nemoclaw, openclaw, closedclaw, trustclaw, ...). Only the first
// word: a later word is an argument a program put in its own name, not who
// it is. Bounded scan over the 16-byte comm; unrolled for the verifier.
#pragma unroll
for (int i = 0; i + 3 < MAX_COMM_LEN; i++) {
if (comm[i] == '\0' || comm[i] == ' ')
break;
if (comm[i] == 'c' && comm[i+1] == 'l' && comm[i+2] == 'a' && comm[i+3] == 'w')
return 1;
}

return 0;
}

#endif
Loading
Loading