dev → main: v0.1.0 governance hardening, Phase 2 daemon, e2e showcase, dependabot bumps#17
Open
gnanirahulnutakki wants to merge 351 commits into
Open
dev → main: v0.1.0 governance hardening, Phase 2 daemon, e2e showcase, dependabot bumps#17gnanirahulnutakki wants to merge 351 commits into
gnanirahulnutakki wants to merge 351 commits into
Conversation
gnanirahulnutakki
added a commit
that referenced
this pull request
May 26, 2026
…o/sigs.k8s.io/controller-runtime-0.24.0 deps(go)(deps): bump sigs.k8s.io/controller-runtime from 0.23.3 to 0.24.0 in /go
…dation Document the empty, whitespace-only, and traversal-escaping path rejection behavior landed at commit 500bd5a. Update both docs/reference/cli.md and the Hugo source mirror to reflect the current CLI contract: JSON error shape, detail field, human output, and explicit non-claims.
… suggestion ardur profile init --path /dev/null (or any existing non-regular file: device files, FIFOs, sockets) previously returned a misleading profile_exists condition with a destructive --force suggestion. Add a non-regular-file check between the directory check and FileExistsError in write_profile_template() so these paths are rejected with profile_path_invalid instead. Regular-file profile_exists behavior and --force semantics are unchanged. Two regression tests added: library-level InvalidProfilePathError for FIFOs and CLI JSON response contract for non-regular files.
Design deep-dive on the auto-detection plan's §4.1 seam: which mission governs an agent nobody launched under 'ardur run'. Proposes the AG-0..AG-4 governance posture ladder (observe-first, identity-bound, operator-promoted), synthesized shadow baselines structurally barred from enforcing, the operator agent-binding registry with load-time dry-run lowering validation, two-claim verifier semantics (mission vs class-policy compliance), and the composition contract with lower_to_bpf_policy_plan/apply_policy. Web-verified survey of EDR / zero-trust / allowlisting precedent for policy on unmanaged workloads. Research document only; no code changed.
…wdStrike tax) (#117) Net-new Epic B research lane: the cost and reliability budget of always-on host-wide agent detection. Covers (1) eBPF exec-tracing overhead on every host exec with web-verified incumbent numbers (Tetragon 1.68%/2.46% worst case, Falco 2-5% / 431-millicore baseline, CrowdStrike <=1% claim); (2) the FP/FN budget with the McAfee 2010 and CrowdStrike 2024 enforce-on-error outages as the FP-cost anchor and Phantom Attack (CVE-2021-33505) as the FN anchor; (3) fail-safe posture (observe, never enforce, on uncertainty); and (4) eight concrete SLOs the Epic B slices (B1/B2/B5/B8) are held to. Does not duplicate the detection/fingerprinting/policy lanes in the roadmap plan (PR #114) -- it supplies the numeric budget those docs defer to.
…#108/#109/#110) (#115) * fix(enforce): close the enforcement-surface authz + stale-policy findings Closes the three vulns filed against the merged BPF-LSM enforcement surface. #108 (missing authorization / IDOR): - apply_policy and set_kill_switch now receive the peer handshake. - apply_policy resolves the session via the new DaemonSessionRegistry.ActiveSessionForPeer, which requires the caller to OWN the session (same UID/GID/PID/start-time/cred-source recorded at register) — the same gate end_session/session_status already enforced. - set_kill_switch (global, fail-open) is gated to a uid-0 admin peer, not any allowlisted UID, so a sandboxed workload can't disable enforcement host-wide. - register_session now verifies the client-supplied root_pid is a descendant of the registering peer (namespace-robust /proc ancestry), so a peer can only register process trees it spawned — it cannot bind a session to another workload's cgroup. A literal /proc/<peer>/cgroup inode match is intentionally not used: the launcher adopts the agent child into the cgroup (it isn't in it itself) and cgroup namespaces make the inode unresolvable across the daemon boundary — that check would reject the verified `ardur run` flow. #109 (stale policy state): - ApplyPolicyMaps clears the inactive double-buffer op slot before writing, so a rule from two generations ago can't survive the flip. - New DeleteAllowlistEntries; the daemon tracks applied path/net allowlist entries per session and revokes the dropped ones on re-apply and releases all on session end / expiry (the allowlist maps are not double-buffered). #110 (double-buffer race): - daemon-wide applyMu serializes ApplyPolicyMaps / RemovePolicyMaps / SetKillSwitch (applyMu acquired outside mu; no lock-order inversion). Tests: foreign-peer apply_policy rejected; set_kill_switch admin-gated; inactive-slot cleared; allowlist revoked on re-apply + session end; concurrent applies serialized (‑race); Linux /proc ancestry check. Verified on a real BPF-LSM kernel that `ardur run --enforce` still blocks (EPERM) + attests + verifies offline, and that a foreign peer's apply_policy is rejected at the socket. Refs #63. * fix(enforce): inject the register cgroup verifier so daemon-flow tests can stub it The Linux register-time ancestry check rejected existing daemon tests that register synthetic root_pids (which aren't real /proc descendants) — darwin's stub masked it. Make the verifier an injected daemon field: production wires verifyRegisterSessionCgroup, newTestDaemon substitutes a no-op. The real check stays covered directly by daemon_cgroup_verify_linux_test.go. * fix(enforce): skip register ancestry check for root peers A root (uid 0) peer is already fully privileged (it can move processes between cgroups directly), so the register-time root_pid-ancestry check adds nothing against it — its purpose is constraining NON-root allowed peers (the sandboxed- workload spoofing threat). Skipping root also unblocks tiers that register a placeholder root_pid: the seccomp tier enforces per-shim'd-process (not by cgroup) and its smoke registers root_pid=1, which a root daemon+client must be able to register. Per-session ownership on apply_policy still applies to every peer regardless of uid.
developers.redhat.com and medium.com return 403 Forbidden to the lychee link checker. Both URLs are legitimate research citations in the Epic B docs. Excluding the domains rather than removing the references.
developers.redhat.com, medium.com, and answers.uillinois.edu return 403 Forbidden to the lychee link checker. All URLs are legitimate research citations in the Epic B docs. Excluding the domains rather than removing the references. Also regenerates the Hugo source mirror.
developers.redhat.com, medium.com, answers.uillinois.edu, and theregister.com return 403 Forbidden to the lychee link checker from GitHub Actions IPs. All URLs are legitimate research citations in the Epic B docs. Excluding the domains rather than removing the references. Also regenerates the Hugo source mirror.
Update docs/TESTING.md and Hugo source mirror to accurately describe all five link-check exclude patterns: one unauthenticated-404 pattern (security/advisories/new) and four bot-blocking-403 domains added in e351209 (developers.redhat.com, medium.com, answers.uillinois.edu, theregister.com). The previous prose said 'one URL pattern' which was stale after the lychee 403 fix landed.
…efault fallback
The cmd_kill_switch() proxy URL resolution used an 'or' fallback chain
that treated an explicitly-passed empty string ('') as falsy, silently
substituting the default https://127.0.0.1:8443 and reaching the network
layer with a raw urllib error instead of returning structured
proxy_url_invalid recovery guidance.
Replace the fallback chain with an explicit 'args.proxy_url is None'
check so an empty string reaches the validator and returns
proxy_url_invalid, matching every other invalid URL variant.
Adds test_kill_switch_empty_proxy_url_returns_invalid regression guard.
…eneration Empty or whitespace-only --agent-id and --mission values were silently accepted by 'ardur issue', producing a Mission Passport with sub='' or mission='' and creating signing keys. Add fail-closed validation in cmd_issue that rejects these inputs before generate_keypair, returning structured JSON (issue_agent_id_invalid / issue_mission_invalid) with placeholder-only next_steps and exit 1. No keys are created on rejection. Refs: t_266acd61, t_56ba844b
CodeQL alert #236: Import of 'MissionPassport' is not used. The TYPE_CHECKING block imported MissionPassport for a type annotation that is already a string-literal forward reference at line 493. The runtime import at line 591 handles actual usage. Behavior-preserving.
Protect claude-code used type=Path for --scope, and Path("") normalizes
to Path(".") which silently resolved empty/whitespace scope values to
the current working directory. This let --scope "" or --scope " "
succeed with exit 0 and create real signing keys plus an active mission
instead of failing closed.
Change --scope from type=Path to type=str and add an explicit
empty/whitespace guard before home.mkdir/generate_keypair, returning
structured JSON (protect_scope_invalid) with placeholder-only
next_steps. Explicit --scope . continues to work as before.
Python argparse type=Path converts --keys-dir "" to Path("") which
normalizes to Path(".") (cwd), silently writing signing keys and state
to an unexpected directory. Change type=Path to type=str for path flags
on start/issue/verify/attest so empty strings survive argparse, then
reject them with a structured path_arg_invalid error before any key
generation, state creation, or directory resolution.
Valid --keys-dir . (explicit cwd) is preserved. Omitted options (None)
pass through untouched. The existing protect_scope_invalid guard is
unchanged.
Document the path_arg_invalid structured error for start/issue/verify/attest that rejects empty/whitespace-only path arguments before any key generation, state creation, or directory resolution. Regenerate source-backed Hugo mirror.
Split _default_home_dir() into a pure path resolver and a deferred _ensure_default_home_dir() side effect. Importing vibap modules no longer creates .vibap/ on disk; the mkdir(0o700) happens on first actual write (key generation, receipt write, etc). VIBAP_HOME explicit dirs are not re-chmod'd (preserves legacy contract). Adds 13 regression tests for import-side-effect-free module loading.
CodeQL note alert #239 flagged 'import stat' as unused. The test file uses Path.stat() method calls (not the stat module), so the module-level import is dead. Removing it clears the alert without behavior change.
setup_home_invalid (empty/whitespace --home) was implemented in 05ec053 but missing from the public CLI reference docs. Document the fail-closed behavior for ardur setup and all Personal commands, matching the adjacent path_not_directory and setup_port_invalid/setup_host_invalid contracts. Files changed (2): - docs/reference/cli.md: added 1 paragraph between path_not_directory and setup_port_invalid/setup_host_invalid sections - site/content/source/docs/reference/cli.md: regenerated mirror
Empty or whitespace-only --agent-id and explicitly-provided whitespace-only --mission previously flowed into Mission Passport JWT claims while generating real signing keys, active_mission.jwt, and home artifacts. Reject them before any key generation, JWT issuance, or plugin artifact creation with structured JSON (protect_agent_id_invalid / protect_mission_invalid) and placeholder-only next_steps, matching the established protect_scope_invalid shape. --agent-id has an argparse default so only explicitly-passed empty strings reach the guard. --mission defaults to None; an empty string is falsy and falls through to the mode/profile default, which is acceptable. Only whitespace-only strings (truthy but meaningless) are rejected. Adds 8 regression tests covering empty, whitespace, and tab/newline variants for both flags, plus the empty-string-mission fallback and valid-args success path.
…ecovery Align docs/reference/cli.md and the generated Hugo source mirror with the landed protect claude-code --agent-id/--mission validation (commit 2010655). Document the structured JSON error codes, placeholder-only next_steps, the empty-string --mission fallback behavior, and the no-keys/no-JWT/no-home guarantee on rejection.
empty/whitespace-only --mission values (e.g. ' ') were treated as truthy by the run_governed_cli or-fallback and reached key generation, creating a Mission Passport with a blank mission string before launching the governed agent. Add an explicit .strip() validation gate that fails closed with exit 2 and deterministic placeholder-only next_steps before any keys, passports, or artifacts are created.
…mission Empty or whitespace-only --mission on ardur start is a mission JSON file path, not a directory. The generic path_arg_invalid hint suggested --mission . which would fail with IsADirectoryError. Add _start_mission_path_invalid_response() returning mission-file-specific next_steps pointing at <mission.json> and never --mission . . Directory args (--keys-dir, --state-dir, --log-path, --tls-cert, --tls-key) keep the generic path_arg_invalid hint where '.' is valid. Adds 3 parametrized regression tests covering empty, whitespace, and tab/newline mission values, asserting no artifacts, no traceback, no raw paths, and placeholder-only tokens. Documents the new recovery contract in docs/reference/cli.md and regenerates the Hugo source mirror.
…tion
protect claude-code --home used type=Path, so argparse normalized empty
strings to PosixPath('.') (the CWD) at parse time and whitespace values
survived as literal directories. Both silently created signing keys and
active_mission.jwt in unintended locations before validation could run.
Switch --home to type=str so empty/whitespace values reach the handler
intact, then validate the stripped string before any mkdir/keygen/passport
write. Invalid values return the structured protect_home_invalid response
with placeholder-only next_steps and no artifacts. Explicit --home . and
omitted --home are preserved.
Mirrors the established protect_scope_invalid / setup_home_invalid shape.
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.
Summary
Promotes
devtomainwith 81 commits. This is the full v0.1.0 hardening cycle that brings all governance features from development into the release branch.Governance & Policy Engine
Proxy Surface
/metricsendpointPhase 2 Daemon
Claude Code & Gemini Integration
Testing
Dependabot bumps
Test plan
🤖 Generated with Claude Code