Skip to content

fix: harden reviewed trust boundaries - #116

Merged
w0wl0lxd merged 3 commits into
fix/ci-checksfrom
review/whole-repo-20260725
Jul 26, 2026
Merged

w0wl0lxd merged 3 commits into
fix/ci-checksfrom
review/whole-repo-20260725

Conversation

@w0wl0lxd

Copy link
Copy Markdown
Owner

Why

A whole-repository correctness and security review found several contained defects: failed session snapshots could be dropped, project plugin manifests defaulted omitted capabilities to allowed, compaction could retry an unchanged overflow request forever, and OAuth endpoint validation accepted attacker-controlled hostname prefixes.

What changed

  • retain failed periodic session snapshots for the existing retry loop
  • default omitted project plugin capabilities to denied
  • stop compaction overflow retries when truncation makes no progress
  • parse OAuth endpoints and permit plaintext HTTP only for exact loopback hosts
  • add regression coverage and a changelog fragment

Verification

  • cargo fmt --all -- --check
  • cargo check --all
  • cargo clippy --all --tests -- -D warnings
  • cargo nextest run --workspace (3849 passed, 1 skipped)
  • targeted OAuth, plugin-permission, and storage-writer tests
  • git diff --check

Risk and rollback

The main compatibility change is default-deny behavior for omitted project plugin capabilities. Plugins must explicitly request required capabilities in plugin.toml. Roll back commit e0012eb if this causes unexpected compatibility problems.

Review follow-ups

The broader review also identified workspace trust, MCP environment isolation, authenticated updates, MCP cancellation/body limits, persistence health reporting, and provider conformance testing as follow-up work. Those require separate product or architecture decisions and are intentionally excluded from this contained patch.

Changelog

changelog.d/review-hardening.fixed.md

@coderabbitai

coderabbitai Bot commented Jul 25, 2026 •

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 97b4009c-8f12-4cee-ba45-e7e01776c10e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR hardens plugin permission defaults, OAuth endpoint validation, compaction overflow handling, and session snapshot persistence retries, with expanded tests and changelog documentation.

Changes

Review hardening

Layer / File(s) Summary
Permission and endpoint validation
n00n-lua/src/plugin_permissions.rs, n00n-agent/src/mcp/oauth/discovery.rs, changelog.d/review-hardening.fixed.md
Unspecified plugin permissions now deny by default, while OAuth endpoints require HTTPS or exact loopback HTTP hosts. Tests cover both policies and rejection cases.
Bounded compaction overflow retry
n00n-agent/src/agent/compaction.rs
Compaction returns the provider overflow error when truncation makes no progress, with mock-provider error support and regression coverage.
Per-session snapshot retry state
n00n-ui/src/storage_writer.rs
Failed session revisions retain pending snapshots, track retry attempts independently, preserve newer revisions, and reset attempts when revisions advance.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant StorageWriter
  participant flush
  participant retry_states
  participant pending_snapshots
  StorageWriter->>flush: flush pending snapshots
  flush-->>StorageWriter: failed session revisions
  StorageWriter->>retry_states: update retry attempts
  retry_states->>pending_snapshots: retain or remove revision
  StorageWriter->>flush: retry retained snapshot
Loading

Possibly related PRs

  • w0wl0lxd/n00n#41: Also changes StorageWriter flush and retry behavior.
  • w0wl0lxd/n00n#66: Also changes StorageWriter persistence and per-session retry handling.

Poem

I’m a rabbit guarding each retry,
Keeping failed snapshots safely nigh.
Overflow? I stop the chase.
Loopback hosts must show their face.
Permissions sleep unless marked true—
Hardening hops from me to you!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main security-hardening focus of the changeset.
Description check ✅ Passed The description is directly related to the patch and matches the listed hardening fixes and verification work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch review/whole-repo-20260725

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@w0wl0lxd
w0wl0lxd marked this pull request as ready for review July 26, 2026 00:10
@w0wl0lxd

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 26, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c37ac0ae1a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread n00n-ui/src/storage_writer.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
n00n-ui/src/storage_writer.rs (1)

231-276: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Dead replace check in flush()'s failure paths.

In both the ensure_subdir error branch (lines 246-257) and the main write-failure branch (lines 266-272), pending_guard.get(&id) is checked before reinserting a failed snapshot. Since mem::take empties pending_guard at the top of the function while the same lock guard is held for the entire call, and batch's keys are unique, pending_guard.get(&id) can never be Some for an id being reinserted here — the check is always vacuously true. It's harmless today but reads as if concurrent mutation of pending_guard is possible mid-loop, which it isn't under the current locking.

♻️ Suggested simplification
-            for (id, snapshot) in batch {
-                let replace = pending_guard
-                    .get(&id)
-                    .is_none_or(|current| current.revision < snapshot.revision);
-                if replace {
-                    pending_guard.insert(id, snapshot);
-                }
-            }
+            for (id, snapshot) in batch {
+                pending_guard.insert(id, snapshot);
+            }

Same simplification applies to the main loop's reinsert at lines 266-272.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@n00n-ui/src/storage_writer.rs` around lines 231 - 276, Remove the redundant
replace checks in both failure paths of flush. After mem::take empties
pending_guard and while the lock is held, directly reinsert each failed snapshot
into pending_guard in the ensure_subdir error branch and the write_session
failure branch, preserving the existing failed revision reporting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@n00n-lua/src/plugin_permissions.rs`:
- Around line 71-74: Import toml::Value at file scope in
n00n-lua/src/plugin_permissions.rs (lines 71-74) and use Value::as_bool; import
isahc::http::Uri at file scope in n00n-agent/src/mcp/oauth/discovery.rs (lines
100-102) and use Uri for parsing. Replace the inline fully qualified type paths
at both sites without changing behavior.

In `@n00n-ui/src/storage_writer.rs`:
- Around line 27-31: Update the RetryState declaration to remove the unnecessary
Copy and Clone derives, leaving it as a non-derived struct while preserving its
existing revision and attempts fields and &mut RetryState usage.

---

Outside diff comments:
In `@n00n-ui/src/storage_writer.rs`:
- Around line 231-276: Remove the redundant replace checks in both failure paths
of flush. After mem::take empties pending_guard and while the lock is held,
directly reinsert each failed snapshot into pending_guard in the ensure_subdir
error branch and the write_session failure branch, preserving the existing
failed revision reporting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8ebde30c-9c7a-41aa-adcf-8545589b41ca

📥 Commits

Reviewing files that changed from the base of the PR and between e9a2b89 and c37ac0a.

📒 Files selected for processing (5)
  • changelog.d/review-hardening.fixed.md
  • n00n-agent/src/agent/compaction.rs
  • n00n-agent/src/mcp/oauth/discovery.rs
  • n00n-lua/src/plugin_permissions.rs
  • n00n-ui/src/storage_writer.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Make non-trivial or multi-file changes in a dedicated git worktree on a new branch, preserve unrelated user changes, and do not force-push or push to main.
Ship finished work by committing with a clear Conventional Commit message, pushing the branch, and opening a draft PR; never add AI-agent attribution to authored content.
For repository exploration, prefer structural tools (codegraph, arbor, index), then targeted reads; use grep only as fallback, parallelize independent calls, and filter large outputs.
Research documented behavior before fixing unfamiliar failures or third-party, CLI, API, infrastructure, or deployment issues, and distinguish baseline failures from regressions.

Files:

  • changelog.d/review-hardening.fixed.md
  • n00n-agent/src/mcp/oauth/discovery.rs
  • n00n-lua/src/plugin_permissions.rs
  • n00n-agent/src/agent/compaction.rs
  • n00n-ui/src/storage_writer.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Follow the workspace Rust lint configuration in the root Cargo.toml and clippy.toml; every crate must opt in with [lints] workspace = true.
Do not add unsafe code, FFI, global mutable state, static mut, or unchecked transmute-like behavior without written review and an explicit crate-level lint exception. Existing unsafe calls require #[allow(unsafe_code)] and a SAFETY comment.
Do not use unwrap, expect, panic!, todo!, unimplemented!, or dbg! in production code; use explicit error handling instead. Tests are exempt from unwrap, expect, and panic restrictions.
Do not silently discard failures with unwrap_or, unwrap_or_default, .ok() on Result, or similar defaults. Convert missing data, parse failures, dependency errors, closed channels, and invalid state into typed errors, explicit rejection, or a named fallback with sanitized structured logging.
Use typed error propagation with ?, ok_or_else, and map_err; use thiserror for library domain errors and color-eyre at binary boundaries.
Do not use wildcard imports. Import types at the top of the file and use short names rather than fully qualified inline paths.
Keep constants at the top of the file immediately after imports, avoid inline magic numbers and strings, and use descriptive variable and function names.
Use #[derive(Copy)] only for structs with one primitive field.
Prefer structured logging with broad useful fields and provide helpful, sanitized error messages.
Keep Rust code minimal and idiomatic: avoid trivial comments, unnecessary state, and bloat; follow KISS, DRY, and SRP.
Do not commit or log credentials, API keys, tokens, cookies, authorization headers, raw provider payloads, prompts, or user session data.
Validate and authorize HTTP, file, queue, config/environment, LLM output, and provider callbacks before mutation or persistence; apply prompt-injection defenses when untrusted content enters prompts or tool calls.
Tool execution must use allowlisted to...

Files:

  • n00n-agent/src/mcp/oauth/discovery.rs
  • n00n-lua/src/plugin_permissions.rs
  • n00n-agent/src/agent/compaction.rs
  • n00n-ui/src/storage_writer.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,toml}: Run and keep passing cargo fmt --all, cargo check --all, cargo clippy --all --tests -- -D warnings, and workspace tests; use cargo test --workspace when cargo-nextest is unavailable.
Add new dependencies to the workspace Cargo.toml first, then reference them with workspace = true in the consuming crate.

Files:

  • n00n-agent/src/mcp/oauth/discovery.rs
  • n00n-lua/src/plugin_permissions.rs
  • n00n-agent/src/agent/compaction.rs
  • n00n-ui/src/storage_writer.rs
**/*.{rs,rs.in}

📄 CodeRabbit inference engine (AGENTS.md)

Treat LLM and provider output as untrusted input; validate it against schemas, domain constraints, and source evidence before persistence or action.

Files:

  • n00n-agent/src/mcp/oauth/discovery.rs
  • n00n-lua/src/plugin_permissions.rs
  • n00n-agent/src/agent/compaction.rs
  • n00n-ui/src/storage_writer.rs
🪛 markdownlint-cli2 (0.23.0)
changelog.d/review-hardening.fixed.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🔇 Additional comments (11)
n00n-agent/src/agent/compaction.rs (4)

125-130: LGTM!


331-339: LGTM!


360-360: LGTM!


465-494: LGTM!

n00n-lua/src/plugin_permissions.rs (1)

184-202: LGTM!

n00n-agent/src/mcp/oauth/discovery.rs (2)

2-2: LGTM!


292-300: LGTM!

changelog.d/review-hardening.fixed.md (1)

1-1: LGTM!

n00n-ui/src/storage_writer.rs (3)

184-229: LGTM!


72-113: LGTM!

Also applies to: 278-303


477-609: LGTM!

Comment thread n00n-lua/src/plugin_permissions.rs
Comment thread n00n-ui/src/storage_writer.rs Outdated
@w0wl0lxd

Copy link
Copy Markdown
Owner Author

Addressed all final review feedback in e9078a6, including the outside-diff simplification: failed snapshots are reinserted directly, retry attempts live on each snapshot, and equal-revision replacements reset their retry budget. Full workspace formatting, check, clippy, and 3,853-test nextest suite pass.

@w0wl0lxd
w0wl0lxd merged commit fbf17c6 into fix/ci-checks Jul 26, 2026
2 checks passed
@w0wl0lxd
w0wl0lxd deleted the review/whole-repo-20260725 branch July 26, 2026 00:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant