Repository navigation
First Light: kernel controls, live commentary, package-install control, Security history - #4
Closed
abhiabhijit wants to merge 41 commits into
Closed
abhiabhijit wants to merge 41 commits into
abhiabhijit wants to merge 41 commits into
Conversation
…ernance, CIS-MCP map Uncommitted research parked off main. NOT for main as-is — experimental. - checks/src/registry.rs — pluggable model-provider registry: one option-scoring contract for every model, raise-only clamp enforced centrally (41 tests pass). - models/schema.py, build_dataset.py — the 13 EnforcementCategories as option sets + a synthetic bootstrap dataset builder. - models/ROSTER.md — base models: reflex = Laya (Apache-2.0 ModernBERT encoder, 5/5 vs Tev1 3/5 zero-shot on our contract, calibrated, local); DLP = GLiNER; judgment = Span-1-style TBD; malware = YARA-labelled encoder. - models/TRAINING-LOOP.md + trigger_retrain.py + misses/ — miss-driven flywheel: miss taxonomy (model_miss→train, evasion→fix detection first, false_positive→ train), manual trigger, benchmark gate before promote, hackathon design. - models/malware/ — bounded (agent file/exec only, not EDR) YARA-as-labels track, license-filtered, sandbox-guarded. - models/bench/ — two-axis benchmark (enforcement outcome vs model detection) + attack scenarios. - docs/data-governance-and-flywheel.md — consent tiers, redact-before-train, the red lines for a released-model data pipeline. - docs/cis-mcp-coverage.md — CIS MCP Server Benchmark -> Ring Zero coverage map (kernel-enforce / detect / roadmap / server-author's-job).
…, seed the circumvention scenarios Add models/THE-BRAIN.md as the single source of truth: the RLCD intent models decide (off the hot path) and the kernel executes the precomputed bit (direction A). Tighten-only is not advisory-only; add the calibrated-confidence enforce / contain / review tiers and the anti-patterns that caused the drift. Honest status kept per CONTRIBUTING: no weights ship yet, enforce bit is pattern-set today, model->enforce is the next target. Align the rest to it: ROSTER.md rewritten (13 categories = one reflex model, ~1 GB on-device, judgment tier self-hosted, sizing follows the task, caveats on the 5-case smoke test and GPU-vs-CPU latency); registry.rs doc comments; schema.py docstring; TRAINING-LOOP, bench/README, models/README, cis coverage and the root README's one-rule line. Seed the five multi_step_evasion scenarios (staged-for-subagent, side-channel device, deferred job, laundered artifact, delegation) in bench/scenarios.jsonl and matching human_seed rows in misses/misses.jsonl. Also commit the enterprise-ai-threat-model.md doc that was untracked. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
…smoke result Add laya_feed.py: builds the upstream MPS trainer's item cache from our oracle-labelled rows (misses/ + optional Laya-shape JSONL), one score question per category with criteria = ordered options and one-hot gold on the rank, so the gold score is the severity rank (tighten-only by construction). Add laya_eval.py: accuracy, mean P(gold), and the bench's shuffled-context control for any checkpoint dir, base vs fine-tuned. Record the smoke result in ROSTER.md status: from typed-decisions on the 9 seed rows (Apple M5/MPS, 2 epochs, loss 1.02 -> 0.37): training-set fit 4/9 -> 9/9, mean P(gold) 0.42 -> 0.85, shuffled-context delta +0.22 -> +0.56. Labelled a smoke test on the training rows, not a benchmark: no held-out or calibration rows. Gitignore generated data/weights/ONNX (model IP, kept outside git). Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
…th numbers Measured 2026-10-03 on Apple M5: the fine-tuned int8 ONNX export is 571 MB and self-contained (fp32 pair not needed to ship); single-row CPU latency via onnxruntime is ~160 ms (min 152 ms) for a 68-token row; the int8 decision matches fp32 (same argmax, P(gold) 0.56 vs 0.60). On-device total revised to ~0.9-1.2 GB. Remaining to measure: batch-of-10, MPS, DLP/malware encoders. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
…1-P3) Move the 17-chapter course out of the loose workspace folder into the private fork on models-rnd, excluding the lab build artifacts (vmlinux.h, .o, the compiled hello binary) from git. Add course/private/ — model IP, never in a public zip: P1 the brain and where a decision model fits (System 1 vs 2, 13 categories = one model, where the model may act, tighten-only != advisory-only, the calibrated-confidence tiers, shipped vs designed); P2 why the state space does not hit the model (the standard doubter objection answered from the mechanisms, where state persists, the real gaps, the eight-question drill); P3 research basis and the lab plan (SalesRLAgent -> Laya lineage, what transfers, measured results with their honest label, the six-stage Inception compute plan, why not pretrain now). private/README.md carries the rule and the public-zip recipe with a zero-leak check; the public syllabus gets a Part VII pointer. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
… kernel bit) Ten chapters reading the decision model's source end to end: the idea and RLCD (L1), sequence layout (L2), forward pass (L3), the objective — proper scoring rules and what RL does, deferred to the source via exercises (L4), calibration/confidence/abstention (L5), the runtime (L6), training with our feeder and the measured MPS run (L7), evaluation incl. the shuffled-context control and held-out attack families (L8), ONNX int8 export + serving with measured artifact size and latency (L9), and the bridge into the registry contract, write-scan decide() and the BPF verdict — shipped vs designed as an enumerated gap list (L10). README index updated. agent/write_scan: reword the decide() doc comment so it no longer calls the model layer "optional" — it is the reflex tier run off the hot path; the enforce-from-patterns-alone behaviour is described as v1-as-shipped with a pointer to THE-BRAIN.md §5/§7. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
…ture Captures the 2026-10-03 critique (Laya/SalesRLAgent too shallow for all agents) and the resulting direction: the reflex tier as a Kahneman System 1 perception stack — kernel-event tower first, text tower, then SigLIP2 vision and Whisper audio — fused into one state vector with Laya's typed heads, abstain head and per-bucket calibration kept on top; System 2 (session judge) triggered by System 1's abstention. States what survives from the Laya work, footprint targets, the first five experiments, and the anti-patterns. THE-BRAIN.md §6 and ROSTER.md now describe the reflex as System 1 with Laya v1 as the text-only baseline; the private course index points to RESEARCH.md. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
Add gero_eval.py — runs a Gero-style branch scorer (Qwen3ForSequenceClassification, num_labels=1) on our rows with the same metrics as laya_eval.py. Measured zero-shot on 9 rows: 2/9, mean P(gold) 0.29, shuffled-context delta 0.00 — a generic 4B decision model answers from option priors on security situations; data, not recipe, is the moat. Recorded in RESEARCH.md §6 as E0 with caveats (n=9, label format, swap-bound latency). RESEARCH.md §3 gains the design lessons worth keeping from Gero: the branch readout (zero position bias by construction), the pre-train data checker, the reward fixed-point test, the zero-gradient-at-truth rule, Murphy reliability/resolution, and System 2 as a scorer head rather than a chatbot. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
… local models New read-only endpoint GET /api/v1/discovery/inventory (scanner/inventory.rs) reports, for every user on the host: installed AI agents with whether Ring Zero's enforcement covers each one; MCP servers from Claude Code (user and project scope), Cursor, Windsurf, Gemini, Codex (TOML), Claude Desktop, VS Code and opencode configs, with transport and risk flags (remote, credentials in config, unpinned package); AI extensions in VS Code, VS Code Server, Cursor and Windsurf; and local model runtimes (Ollama, LM Studio, llama.cpp, Hugging Face cache). Discovery reads directory listings and config files only and never executes a binary it finds. MCP environment variables are reported by name, never value, URLs lose their query string, and credential-like arguments are redacted before they leave the daemon. The desktop app's "Agent Skills" page becomes "Discovery": the inventory at the top, the existing skills and instructions audit below it. agent_detect: the install-path test behind is_agent_by_binary is exposed as is_agent_path so inventory can use it without a live pid. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
The agent's UserPromptSubmit hook already posts the prompt to the local
daemon. It is now scanned with the same secret patterns the file scanner uses
(new detector::find_spans returns value spans), and [dlp] prompt_guard
decides what happens: off, warn (record, let it through; the default), or
block (rz-hook returns Claude Code's {"decision":"block","reason":...} so the
prompt is not sent and the person sees why). No network call is made.
The trace now stores the REDACTED prompt. Before this, a prompt event stored
the raw text, which would have put the very secret into Ring Zero's own logs.
A finding is recorded as a denied (block) or flagged (warn) event with the
kinds found and masked previews; values never appear in the event, the reason,
or the hook response.
The on-device span model (GLiNER-small, DLP tier) is the next layer on the
same function and may only add findings.
Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
…uard) The opt-in Claude Code hook installer registered PreToolUse and PostToolUse only, so prompts never reached the daemon and the prompt guard could not run. UserPromptSubmit is added as a matcher-less group, merged into the user's existing settings like the others. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
A profile, written as [[profiles]] in daemon.toml, attaches to one agent or one MCP server and says which hosts it may connect to, whether it may start other programs, and if so which ones. Every connection and program start inside an agent's process tree is attributed to the nearest profiled MCP server or agent (MCP servers first, since they run inside an agent's tree), checked against its profile, and a mismatch is recorded on the event as "Would block — <profile>: <detail>". Per-profile counts (allowed / would block) and the latest violations are served at GET /api/v1/policy/profiles together with the daemon mode and the prompt-guard setting, for the Policy screen. This is stage 1 and refuses nothing: it observes, which is also how a profile is rolled out against real work before it is enforced. Host names are resolved to IPs in the background every five minutes because connect events carry addresses. Kernel enforcement is stage 2: the network half maps onto the connect hook's existing IP allowlist, the program half needs a new exec denial and its own review. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
Replaces the separate Enforcement and File Access pages with one Policy
page that answers four questions in order:
1. Mode — enforcing or watching only.
2. Protected data — the kernel-enforced file rules (the File Access
editor, embedded).
3. Agent & tool permissions — one card per agent and per MCP server:
allowed hosts, whether it may start programs and which, and live
"allowed / would block" counts with the latest violations
(GET /api/v1/policy/profiles, refreshed every 5 s). Labelled
"Watching" because stage 1 records and refuses nothing.
4. Prompts — the prompt-guard setting in plain words.
The per-category settings move to a collapsed "Alert categories" section,
labelled as recording rather than refusing, and their "Block" option is
renamed "Violation": nothing in the event pipeline enforced it, and the old
label put a false claim on screen. Old page ids route to Policy.
Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
Policy page header said everything on it was enforced in the kernel and editable with an admin password; only Protected data is both. It now says each section states whether it is enforced or only watched, and the mode card scopes "refused by the kernel" to protected files. Overview showed "All 13 categories: BLOCK" for a setting that records a violation and refuses nothing. Reworded to "record as violation" / "flag for review". Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
…LI and app ProfileConfig gains network_mode and programs_mode (watch | enforce, default watch) and CIDR ranges in allow_hosts. Every write is validated (name, agent xor MCP match, host entries, program names) and saved atomically to /etc/ringzero/profiles.json, which becomes the complete list once present; daemon.toml [[profiles]] only seeds it. Changes apply live. New: PUT /api/v1/policy/profiles, DELETE /api/v1/policy/profiles/:name (full token only), rz profile show|set --json|remove, and the two write commands on the app's polkit allow-list. The enforce mode is stored here; the kernel side that acts on it follows. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
… agents Policy changes are meant to have one road: the admin-password prompt from a process that is not an agent. The API already needs the root-only token and refuses writes from agent callers, but an agent running where the operator recently used sudo could skip the API: read the token, or edit profiles.json / daemon.toml / the service unit directly. /etc/ringzero, /var/lib/ringzero and the ringzero-daemon unit (and its drop-in directory) are now blocked for every agent process tree, by tree membership rather than uid, so it holds for an agent running as root. Always on, not removable from the app or CLI, and re-applied when the operator's directory rules are cleared (clearing them used to drop the switch that directory blocking hangs on). Measured on Ubuntu 26.04 / kernel 7.0: an agent process running as root is refused the token, daemon.toml, a write into /etc/ringzero and the unit file; an ordinary file and a non-agent `sudo cat` are unaffected. Not covered, stated in the code: the binaries (a file block also refuses exec, and agents must run rz and rz-hook), and stopping the service through systemd, which delivers the signal itself. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
…nd agents cannot use bpf()
New kernel switch, tamper_protect (the last reserved config byte, so the
struct size and its Rust mirror are unchanged), separate from enforce_blocks
so it holds even when every other rule is only observing. Set from
[daemon] tamper_protection, on by default.
task_kill any non-zero signal to the daemon is refused unless it
comes from the daemon itself or pid 1 (systemd, which
delivers reload, shutdown and the operator's stop).
Root included.
ptrace_access_check nobody may ptrace the daemon or open its memory.
bpf (new hook) an agent process tree, root or not, may not make the
bpf() syscall, so it cannot detach a Ring Zero program
or rewrite one of its maps. The daemon and a human's
root shell outside any agent are unaffected.
Measured on Ubuntu 26.04 / kernel 7.0 / arm64: root kill -TERM, kill -9 and
pkill -STOP of the daemon are refused and it keeps running; root opening
/proc/<pid>/mem is refused; an agent running as root gets EACCES from
bpftool, while root bpftool outside an agent still works; systemctl restart
still works. Not refused, observed: reading /proc/<pid>/environ.
The previous observe-only lines in these hooks are left as they were; this
is a new, separately gated path.
Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
Discovery: an environment variable is treated as a credential only when a whole word of its name is one (TOKEN, KEY, PAT, PASSWORD, ...). The old substring match flagged PATH, so Codex's node_repl MCP server was wrongly shown as "credentials in config". MCP variable names collapse into an expandable count instead of a wall of text. Page width matches the others. Threats: plain titles for a secret stopped in a prompt, a refused tamper attempt, and an agent refused Ring Zero's own files; the line under each threat names the agent and what happened instead of the raw event target. Page width standardised. Sessions: an ended session shows a neutral grey "Ended" instead of a red "Terminated", which read as if Ring Zero had killed it; agents show by product name (Claude Code, ChatGPT, Codex CLI, ...). Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
- Posture strip at the top: mode, tamper protection, secrets in prompts, agent permissions, each green/amber at a glance (the policy endpoint now reports tamper_protection). The separate Mode section it duplicated is gone. - Protected data is a new panel instead of the old File Access page embedded whole: one list (File/Folder, Enforced / Not found on disk / Not saved), one-click common protections (SSH keys, cloud credentials, .env files), a File/Folder add field, and one "Save and enforce" bar that appears only when something changed. Saving uses the same rz file-access add/remove commands through polkit as before, so the password is asked once per save. The legacy [dir-block] marker is no longer shown in notes. - Permission cards: hosts and programs as chips with "+N more", a large would-block count, allowed beneath it. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
…; OS-neutral text Following how established security products lay out settings (one switch and one sentence per protection, Detect vs Block, administrator-protected controls marked, a banner when a protection is off, product security as its own group): - Product security group: a Tamper protection switch. Turning it on or off asks for the administrator password every time (rz settings set tamper_protection on|off through polkit) and applies live in the kernel. - Prompts: Off / Detect / Block, same password path. - Agent & tool permissions are a table of switches (agents: any host vs approved hosts only, any program vs approved only; MCP servers: network access, can start programs) with the lists behind "Edit". One Save sends each changed profile with rz profile set, one password prompt. - "Watching" is now "Detect only — nothing is blocked yet". - A banner lists any protection that is off. Backend: settings.json beside daemon.toml overrides it for the switches the app can change, so the operator's daemon.toml is never rewritten. PUT /api/v1/policy/settings (full token, agent callers refused) saves and applies; rz settings set; allow-listed in the app. User-facing text no longer shows sudo, systemctl or Linux paths. Signed-off-by: Ring Zero Security <abhijit@ringzerosecurity.com>
Theme colors are hex CSS variables, so Tailwind emitted no rule for classes like bg-muted-foreground/30 or bg-primary/5. Off switches were invisible and tinted save bars and focus rings were missing. Wrap each color in color-mix with the alpha placeholder.
pkexec exits 127 with a terminal error when the app runs outside the desktop session. Show what to do instead of polkit's text and a shell command; keep polkit's words in the app log.
…ion files Replace the 13 threat-category settings, which never refused anything, with controls the kernel enforces on agent process trees: - admin tools (sudo, su, pkexec, doas, run0), on by default - escape tools (systemd-run, at, batch, crontab), on by default - agent instruction files (CLAUDE.md, AGENTS.md, .cursorrules, ...): read allowed; write, create, rename, delete and hardlink refused. Off by default. - quarantine of flagged agent-written files, now a switch Each is a switch on Policy behind the administrator password (rz settings set). Threat categories become labels from a narrow rule-based classifier on recorded events, shown on Threats; trained classifiers replace the rules per category. Overview shows the controls that are blocking. Tamper protection now allows read-only process metadata to non-agent processes; journald hit it on every log line. Attach (debug, memory) stays refused to everyone.
The network switch meant 'restricted' while the programs switch meant 'allowed', so the same green switch read as opposite things. Now on always limits the agent to its approved list (empty list = none), amber because the limits are watched, not enforced. 'would block' becomes a count of times outside the limits since start, which opens the recorded events.
Each process in an agent tree now carries its profile's slot (set when the agent starts, by name or by command line for node/python agents and MCP servers, copied at fork). A profile in Block mode is enforced at the call: - programs: exec outside the approved list is refused; names behind symlinks (python3 -> python3.14, sh -> dash) are approved too - network: connect and unconnected sendto outside the approved addresses are refused; v4-mapped IPv6 judged as IPv4; other IPv6 refused; loopback, DNS and model endpoints always allowed - approved host names are looked up every minute; addresses from the agent tree's own DNS answers are added for the TTL, which is what makes *.domain work. DNS capture now covers the whole agent tree, not only the agent process. Sub-domains seen once are remembered across restarts. - network is not enforced until names were looked up once after start Policy: each limit has Watch or Block. Also fixes a 4-second rescan that reset every agent's profile tag.
The daemon turns what it records into short spoken lines (narrator.rs): the task, the agent's thinking (from its transcript), files read (grouped) and changed, commands run, web and MCP use, and above all what Ring Zero refused. Lines carry a level: alerts (a refusal) cut in, info may be skipped when the agent is busy. Every line passes the secret detector, so a key is never read aloud. GET /api/v1/commentary long-polls for new lines. The app shows them as captions and speaks them on the machine with Piper (one warm process, raw audio to the system player), falling back to espeak-ng or captions only. Piper is installed separately by packaging/voice/install-voice.sh with its licences (GPL-3.0 via espeak-ng; voice dataset CC0) and is never linked into the app. Switch at the bottom of the sidebar.
rz-kokoro keeps Kokoro loaded through the sherpa-onnx C API and turns each stdin line into raw PCM, so the app drives it exactly like Piper. Measured on the ARM64 demo VM: model loads in 0.6 s, each line is ready in about 1 s. Full precision on purpose: the int8 build was about 5x slower on ARM64.
An agent's worker threads (Bun, Node) have their own names, and an agent that was running before the daemon (re)started was never in the kernel's agent map, so its worker threads could read protected files. Reproduced on the VM: after a restart, a thread named 'Bun Pool 1' read ~/projects/flag.txt. The kernel now checks the process's main thread name when the current thread's is not an agent's, and tags the process on the spot. The daemon also re-tags running agents and everything they started, with their profile slot, at startup. Both cases are refused again; a non-agent is unaffected.
- The daemon dropped opencode's kernel events: its agent classifier had no
opencode entry (so no session), and events were labelled with the thread
name ("HTTP Client"). opencode is classified now, and an event whose
thread name is not an agent's takes the process's name.
- The narrator speaks from kernel events for agents without hooks: "is at
work", the programs it runs (shell plumbing stays quiet), files it saves.
Claude Code keeps its richer hook narration and is not repeated.
- Refusals say "Ring Zero Security" and name the agent, not the helper.
- The app starts over when the daemon restarts and its numbering resets,
instead of ignoring every new line.
The modal showed a hard-coded confidence (94/91/97%), template text styled as AI analysis, buttons that did nothing (Allow, Block Once, Report False Positive) and the helper's name (cat) as the source, and it covered the screen on every refusal. Now a corner notice that says only what the record says: one sentence (the same one the commentary speaks), which control refused it, the target, the time and the classifier's category. Refusals from one agent within a few seconds are one notice. Buttons: View in Threats, Change rule. Compact while live commentary is on. The daemon also attributes a helper's event to its agent session, so it reads "opencode tried to read .env", not "head".
The table listed only agents that already had a profile (opencode and four others Discovery found were missing) and put two controls in every cell (a limit switch and Watch/Block). Now a list of every discovered agent, each with one status line, and a detail view with Network and Programs cards. Each card is one choice: No limit, Watch or Block. Things the agent reached outside its list are offered under 'Seen outside the list' to approve with one click. Saving a discovered agent creates its profile; the password is asked once per save. Kernel name map: opencode also runs as opencode.exe.
- Commentary tab in each session: the session told in sentences, rebuilt from what was recorded (GET /api/v1/sessions/:id/commentary replays its events through the narrator with each event's real time, plus the agent's prompts and tool calls in the session's span and its thinking lines). - Session events that were refused now show red and say Blocked. Every file event was drawn green before, so a refused read looked successful. - Terminate goes through the administrator password (rz sessions terminate). The direct call used the app's read-only token, which the daemon refuses, so the button silently did nothing. - Refused reads of protected files say read, not touch.
Captions while agents work and each session's Commentary tab stay. The spoken voice (Piper, Kokoro via rz-kokoro, espeak fallback), its Tauri commands, the voice switch and packaging/voice are removed; git history keeps them.
Both were already enforced as agents (agent_detect) but missing from the inventory, so Discovery showed only coding agents. Package description now says AI agents, not AI coding agents.
Agents can't install packages (new control, on by default):
- Kernel: when a process in an agent's tree becomes a package manager
(npm, npx, pnpm, yarn, bun, pip, uv, uvx, poetry, cargo, gem), the
sched_process_exec hook stops it before it runs an instruction.
- Daemon: reads the full command line on the reader thread. Installs and
fetches (npm install/ci/add/update/exec, npx, pnpm/yarn/bun add, dlx,
pip install, uv add/sync/pip install/tool install, poetry add,
cargo install/add, gem install) are killed; anything else (npm test,
npm run, pip list) is resumed.
- `python -m pip install` runs as python, so it is caught just after it
starts instead.
- The refused process is told why on its own stderr (via pidfd_getfd, so
no DAC override is needed), and commentary names the agent and command.
- `rz settings set package_installs on|off`, password-gated like the
other controls.
Package managers are never an agent by their own name or arguments. npm
puts its command line in its process name ("npm i openclaw@"), so
installing OpenClaw made npm look like OpenClaw and the kernel refused the
install. A package manager an agent starts is still in that agent's tree.
In the kernel, the claw-family match now only looks at the first word of
the name.
A directory rule no longer becomes a file-name block everywhere. A rule
for ~/rz-test/secrets refused every file or folder named "secrets" on the
machine. Known credential stores (~/.ssh/*, ~/.aws/*) still expand to their
key names.
A worker thread exiting no longer untags its agent: only the thread-group
leader's exit removes the process from agent_descendants.
A refused file open now records the file's full path (bpf_d_path, only on
refusals), so the record says which file.
GET /api/v1/events?blocked=true returns refusals across the whole 24-hour
window, so busy activity cannot crowd one out.
- Threats is now Security history. Everything on it was refused before it
happened, so it is no longer described as "active threats".
- It lists every refusal from the daemon's blocked-only query. It no longer
takes the newest 100 events of every kind, which lost refusals within
seconds, and it no longer hides "low severity" ones behind a toggle. The
notice that says "View in Security history" now always finds its item.
- Notices, the page and the Overview "Refused (24h)" tile share one list.
The sidebar count is gone.
- Row titles say what happened (File access refused, Package install
refused, Program refused, Connection refused).
- Actions:
- Removed "Trust Process", which changed only what the page showed, and
"Whitelist Path", which unblocked a file name everywhere.
- Added "Change rule", which opens Policy (password-gated), and
"Mark reviewed", which is remembered in this browser.
- Policy gains the "Agents can't install packages" control. Overview shows
"Package installs" among the controls that are blocking.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this branch adds
npm install,npx,pip install,uv add,cargo install, …) and resumes everything else (npm test,npm run).npm i openclawis npm, not OpenClaw.Fixes
Testing
npm install,npxandpython -m pip installfrom an agent are refused.npm testfrom an agent runs.npm installworks.