Skip to content

fix: bug-hunt Phase 2 fixes (ACP, TUI, MCP, bash, write/edit) - #230

Closed
w0wl0lxd wants to merge 27 commits into
mainfrom
fix/bughunt-phase2-20260802
Closed

w0wl0lxd wants to merge 27 commits into
mainfrom
fix/bughunt-phase2-20260802

Conversation

@w0wl0lxd

@w0wl0lxd w0wl0lxd commented Aug 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR collects the fixes from bug-hunt Phase 2.

Phase 1 confirmed fixes

  1. ACP server died on invalid UTF-8 (n00n-acp/src/server.rs)

    • n00n acp no longer exits with a panic when binary/invalid UTF-8 is written to stdin.
    • It now returns a JSON-RPC parse error (-32700) and keeps running.
  2. ACP request id coercion to RequestId::Null (n00n-acp/src/server.rs)

    • Overflowing or otherwise unparseable request ids no longer silently coerce to Null.
    • They are rejected with an invalid_request error (-32600) and id: null, per JSON-RPC.
  3. TUI panic in non-TTY environments (src/cmd/tui.rs)

    • Running n00n without a prompt in a pipe/non-TTY now exits with code 1 and a clear message instead of a ratatui panic.
    • Added tests/non_tty.rs to guard this path.

Phase 2 confirmed fixes

  1. MCP manager shutdown task leak (n00n-agent/src/mcp/mod.rs)

    • McpHandle now stores the command-loop task and cancels it if graceful shutdown times out, preventing a leaked background task.
  2. bash tool exfiltration checks (plugins/bash/init.lua)

    • Commands that may exfiltrate data to remote hosts (curl, wget, nc, ncat, dig, nslookup, and encoded data piped to network tools) now require a justification.
  3. Write/edit secret and PII validation (plugins/write/init.lua, plugins/edit/init.lua, plugins/lib/n00n/secret_check.lua)

    • New plugins/lib/n00n/secret_check.lua heuristically detects secret/PII patterns in tool content.
    • write, edit, multiedit, edit_lines, and insert_lines now return an error when the new content may contain a secret/PII pattern and no justification is provided.

Test plan

  • cargo fmt --all ✅
  • cargo check --all ✅
  • cargo clippy --all --tests -- -D warnings ✅
  • cargo nextest run --workspace ✅ (4585 passed, 1 flake in cmd::tui_bridge::tests::spawn_serves_tui_list_over_uds; passes individually)
  • cargo nextest run -p n00n-lua ✅ (978 passed)
  • Regenerated n00n-token-profile/baselines/cold_start.json to account for expanded tool schemas.

Note

This work was done in an isolated worktree: fix/bughunt-phase2-20260802 off origin/main.


Note

Medium Risk
Changes touch agent I/O, process lifecycle, and permission guardrails; false positives on bash or secret heuristics could block legitimate workflows until justified.

Overview
Hardens ACP and TUI I/O, fixes MCP shutdown leaks, and adds guardrails on bash and file-editing tools.

ACP races stdin reads against stdout write failures, surfaces write errors instead of ignoring them, treats invalid UTF-8 on stdin as JSON-RPC parse errors (keeps serving), and rejects malformed id values with invalid_request instead of coercing to null. TUI refuses to start when stdin/stdout are not a TTY, pointing users to --print.

MCP keeps the command-loop task on McpHandle, runs force_shutdown (clear index/snapshot, kill process groups, reap stdio children) when graceful shutdown times out, and tightens stdio teardown via explicit force_shutdown on transports.

bash adds exfiltration heuristics (network/DNS tools, encoded data piped to network commands, etc.) that require justification, with tests so benign commands like sync are not flagged by substring false positives.

write, edit, multiedit, edit_lines, and insert_lines use new n00n.secret_check to block likely secrets/credentials without justification. Docs, token-profile baselines, and code_execution preamble trim (os/sys removed from injected imports) reflect the expanded schemas and sandbox posture; interpreter tests assert open() is sandbox-blocked.

Reviewed by Cursor Bugbot for commit c5ebcc6. Bugbot is set up for automated code reviews on this repo. Configure here.

- Invalid UTF-8 on stdin no longer kills the ACP server; it returns a
  JSON-RPC parse error and keeps running.
- Malformed/overflowing request ids no longer coerce to RequestId::Null;
  they are rejected with an invalid-request error (-32600).
- Extracted read_request() to make line/id validation testable.

Fixes: n00n-acp/src/server.rs
Running `n00n` with no prompt in a pipe/non-TTY previously panicked with
a ratatui init error. Now it exits with code 1 and a clear message
pointing users at --print.

Fixes: src/cmd/tui.rs
@coderabbitai

coderabbitai Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@w0wl0lxd, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 92b8a850-8908-4d2a-a1e5-5803a3fcd215

📥 Commits

Reviewing files that changed from the base of the PR and between 95987ac and 8cc1eea.

📒 Files selected for processing (17)
  • n00n-acp/src/server.rs
  • n00n-agent/src/mcp/mod.rs
  • n00n-agent/src/mcp/stdio.rs
  • n00n-agent/src/mcp/transport.rs
  • n00n-interpreter/src/runner.rs
  • n00n-lua/tests/code_execution_policy.rs
  • n00n-lua/tests/plugin_host.rs
  • n00n-token-profile/baselines/cold_start.json
  • plugins/code_execution/init.lua
  • plugins/edit/init.lua
  • plugins/lib/n00n/secret_check.lua
  • plugins/write/init.lua
  • site/docs/content/lua-api/_index.md
  • site/docs/content/tools/_index.md
  • src/cmd/tui.rs
  • tests/non_tty.rs
  • typos.toml
📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added protection against potential data exfiltration in shell commands, including network and encoded-data transfers.
    • Added secret and PII detection for file-writing and editing tools, with optional justification support.
    • Added clearer validation for malformed requests and invalid identifiers.
  • Bug Fixes

    • Improved MCP shutdown handling to prevent task leaks.
    • Interactive mode now provides a clear error when launched without a terminal and directs users to print mode.
  • Tests

    • Expanded coverage for security checks, sandboxed file access, request parsing, shutdown behavior, and non-interactive startup.

Walkthrough

The change adds secret/PII validation to editing tools, exfiltration checks to Bash, and Python sandbox tests. It also improves ACP parsing, MCP shutdown task ownership, and non-terminal TUI startup handling.

Changes

Content and execution safety controls

Layer / File(s) Summary
Secret and PII detection
plugins/lib/n00n/secret_check.lua, site/docs/content/lua-api/_index.md
Adds heuristic detection for credential-like values and authorization headers. Documents check and reason.
Editing and Bash guardrails
plugins/edit/init.lua, plugins/write/init.lua, plugins/bash/init.lua, n00n-lua/tests/plugin_host.rs, site/docs/content/tools/_index.md, n00n-token-profile/baselines/cold_start.json, changelog.d/230.fixed.md, typos.toml
Edit and write tools require justification for detected sensitive content. Bash requires justification for detected exfiltration patterns. Tests and documentation cover the new behavior.
Python sandbox validation
plugins/code_execution/init.lua, n00n-interpreter/src/runner.rs
Removes sys and os from the Python preamble. Tests verify that Python file reads and writes are blocked.

Runtime reliability and lifecycle handling

Layer / File(s) Summary
ACP request parsing and error responses
n00n-acp/src/server.rs
Handles EOF, invalid UTF-8, I/O failures, malformed JSON, and invalid request IDs with distinct outcomes.
MCP command-task shutdown
n00n-agent/src/mcp/mod.rs
Retains the command-loop task and cancels it when shutdown acknowledgment times out.
Non-terminal startup handling
src/cmd/tui.rs, tests/non_tty.rs
Rejects interactive TUI startup without terminal input or output. The integration test verifies clean failure.

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

Suggested reviewers: tontinton

Poem

A rabbit checks each secret string,
And guards the paths where data may spring.
Bash asks why the network calls,
MCP cleans up when shutdown falls.
No terminal? The TUI says “not today!”
Then hops safely on its way.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly summarizes the PR's main bug-fix areas across ACP, TUI, MCP, bash, and file-editing tools.
Description check ✅ Passed The description directly explains the changes, objectives, affected components, tests, and known test flake.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/bughunt-phase2-20260802

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.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions github-actions 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.

Criterion

Details
Benchmark suite Current: 8cc1eea Previous: 8d5809e Ratio
fib/jit_mlua_hook 6626107 ns/iter (± 61148) 6678342 ns/iter (± 253554) 0.99
fib/jit_watchdog 2221705 ns/iter (± 7096) 2220199 ns/iter (± 12990) 1.00
fib/jit_none 2225958 ns/iter (± 43499) 2218881 ns/iter (± 33232) 1.00
fib/interp_mlua_hook 8187601 ns/iter (± 36001) 8091425 ns/iter (± 114645) 1.01
fib/interp_watchdog 4367937 ns/iter (± 21549) 4326050 ns/iter (± 14651) 1.01
fib/interp_none 4330719 ns/iter (± 25587) 4302519 ns/iter (± 21751) 1.01
buffer_rw/jit_mlua_hook 585172 ns/iter (± 12121) 585064 ns/iter (± 2008) 1.00
buffer_rw/jit_watchdog 192189 ns/iter (± 371) 191572 ns/iter (± 450) 1.00
buffer_rw/jit_none 192050 ns/iter (± 317) 191410 ns/iter (± 393) 1.00
buffer_rw/interp_mlua_hook 1047156 ns/iter (± 11097) 1047263 ns/iter (± 5989) 1.00
buffer_rw/interp_watchdog 583686 ns/iter (± 15516) 586663 ns/iter (± 8150) 0.99
buffer_rw/interp_none 583318 ns/iter (± 3085) 582762 ns/iter (± 1557) 1.00
splash_render_120x40 50331 ns/iter (± 8524) 48447 ns/iter (± 2593) 1.04
splash_render_200x60 196697 ns/iter (± 1769) 159346 ns/iter (± 17058) 1.23

This comment was automatically generated by workflow using github-action-benchmark.

…O errors

- `read_request` now only emits `parse_error` for `InvalidData` (invalid
  UTF-8). Other `read_line` I/O errors are propagated as `color-eyre`
  reports, causing `serve` to exit instead of mis-reporting a parse error
  and looping.
- Unit tests downcast the returned `Report` to `AcpError` before checking
  the error code.
- `tests/non_tty.rs` now uses a per-process temp directory to avoid races.
@w0wl0lxd

w0wl0lxd commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@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: e229b71e2a

ℹ️ 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 tests/non_tty.rs Outdated
…e/edit secret validation

- Cancel the MCP manager command-loop task if shutdown times out.
- Require `justification` for bash commands that may exfiltrate data
  (curl, wget, nc, ncat, dig, nslookup, encoded data piped to network tools).
- Add `plugins/lib/n00n/secret_check.lua` with heuristic secret/PII detection.
- Require `justification` for write/edit/multiedit/edit_lines/insert_lines
  when new content may contain secrets/PII.
- Regenerate token-profile baseline for the expanded tool schemas.
@w0wl0lxd w0wl0lxd changed the title fix: ACP stdio robustness and non-TTY guard fix: bug-hunt Phase 2 fixes (ACP, TUI, MCP, bash, write/edit) Aug 3, 2026
@w0wl0lxd

w0wl0lxd commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@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: b3b0d16efe

ℹ️ 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 plugins/bash/init.lua Outdated
Comment thread plugins/lib/n00n/secret_check.lua Outdated
@w0wl0lxd
w0wl0lxd marked this pull request as ready for review August 3, 2026 04:56

@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: 11

🤖 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-acp/src/server.rs`:
- Around line 67-69: Update the writer task and serve flow so serialization,
write, and flush failures are returned as a typed error instead of discarded.
Have serve observe the writer task result, stop processing requests when the
writer reports failure, and propagate that error rather than returning success
on EOF; preserve the existing JSON-RPC responses for individual line, JSON, and
request-id errors.
- Around line 610-677: Import the repository’s test-case attribute in server.rs
and replace #[test] with #[test_case] on the six unit tests shown:
request_id_accepts_valid_ids, request_id_rejects_invalid_types_and_overflow,
read_request_returns_none_on_eof,
read_request_returns_parse_error_on_invalid_utf8,
read_request_returns_invalid_request_on_overflow_id, and
read_request_parses_null_id. Keep their existing snake_case names and test
bodies unchanged.

In `@n00n-agent/src/mcp/mod.rs`:
- Around line 626-633: Update the task mutex access in the shutdown flow around
task.cancel to explicitly match the lock result instead of silently calling
PoisonError::into_inner. On poisoned recovery, use an explicitly named fallback
guard and emit a sanitized structured warn! event; otherwise preserve the
existing task extraction and cancellation behavior.
- Around line 626-633: Update the shutdown path around McpHandle’s stored task
and shutdown_all so transport teardown does not depend on the cancelled command
loop completing. Ensure the cancellation owner retains access to the inner entry
and ToolIndex, clears or publishes an empty index before terminating child
process groups, and then kills/reaps the associated processes even when
task.cancel().await is used.
- Around line 301-303: Import smol::Task at module scope in the module
containing the task field, then update the task field’s type from smol::Task<()>
to Task<()> while preserving its existing Arc, Mutex, and Option structure.

In `@plugins/bash/init.lua`:
- Around line 245-273: Replace the raw "nc" and "od " substring checks in the
encoded-data and command-substitution conditions with command-boundary-aware
patterns, reusing the anchoring approach already used by the earlier netcat
detection in this function. Preserve detection for actual nc/ncat and od
commands while preventing matches inside ordinary words such as “sync” or
“good”.
- Around line 211-277: The command-boundary detection in
exfiltration_command_reason only recognizes network tools at script start, after
pipes, and after &&. Update every network-command prefix check in
exfiltration_command_reason, including encoded-data and command-substitution
paths, to recognize commands after ;, ||, and newlines as well, or reuse the
existing collect_guard_commands segmentation logic used by broad_command_reason
while preserving current reasons.

In `@plugins/edit/init.lua`:
- Around line 273-277: Extract the duplicated secret/justification validation
into a shared require_justification helper in secret_check.lua, accepting text,
justification, and tool name and returning the existing error table or nil.
Replace the inline checks at plugins/edit/init.lua lines 273-277, 348-357,
425-429, and 480-484, plus plugins/write/init.lua lines 75-79, passing each
site’s tool name and preserving the existing per-edit loop behavior.

In `@plugins/lib/n00n/secret_check.lua`:
- Around line 79-136: Update SECRET_ASSIGNMENT_PATTERN and the M.check detection
flow so credential-style assignments are actually evaluated. Remove the
unsupported "|" alternation and check each secret-key suffix with valid Lua
pattern matching, including assignments such as userCredential=..., while
preserving the existing token and authorization-header checks.

In `@tests/non_tty.rs`:
- Around line 6-7: Update the state-directory cleanup before create_dir_all to
handle remove_dir_all’s Result explicitly: treat only the NotFound error as
expected, and fail the test for every other cleanup error before recreating the
directory. Preserve the existing create_dir_all behavior.
- Around line 30-33: Update the non-TTY assertion in the test to require a
non-success exit code and the exact expected terminal error text in stderr,
removing the permissive `code == 1` alternative. Preserve the existing
diagnostic output while ensuring the test verifies the terminal guard was
reached.
🪄 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: 499bfece-ec19-43fb-908c-7558f7b9aadb

📥 Commits

Reviewing files that changed from the base of the PR and between fda180a and 9456e34.

📒 Files selected for processing (13)
  • changelog.d/230.fixed.md
  • n00n-acp/src/server.rs
  • n00n-agent/src/mcp/mod.rs
  • n00n-interpreter/src/runner.rs
  • n00n-lua/tests/plugin_host.rs
  • n00n-token-profile/baselines/cold_start.json
  • plugins/bash/init.lua
  • plugins/code_execution/init.lua
  • plugins/edit/init.lua
  • plugins/lib/n00n/secret_check.lua
  • plugins/write/init.lua
  • src/cmd/tui.rs
  • tests/non_tty.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Do not add unsafe code, FFI, global mutable state, static mut, or unchecked transmute-like behavior without written review, an explicit lint exception, and a SAFETY comment where applicable.
Do not use unwrap, expect, panic!, todo!, unimplemented!, or dbg! in production Rust code; tests are exempt from the unwrap/expect/panic restriction.
Do not silently discard failures with unwrap_or, unwrap_or_default, .ok() on Result, or equivalent defaults; return typed errors, reject the operation, or use an explicitly named fallback with sanitized structured logging.
Use idiomatic Rust, descriptive names, minimal state, and avoid unnecessary comments, bloat, and magic numbers or strings.
Import types at the top of the file and use short imported names; keep constants immediately after imports.
Use Result<T, E> and explicit error handling instead of panics; use thiserror for library/domain errors and color-eyre at binary edges.
Use #[derive(Copy)] only for structs containing one primitive field.
Prefer structured logging with useful fields and provide helpful, sanitized error messages.
Place unit tests in the same file inside #[cfg(test)] modules; use #[test_case] and snake_case test names.
Propagate typed errors with ?, ok_or_else, and map_err; library crates use thiserror and binaries use color-eyre.
Treat LLM and provider output as untrusted input; validate schemas, domain constraints, and source evidence before persistence or action.
Do not log raw provider payloads, prompts, credentials, or user session data, and never commit credentials, API keys, tokens, cookies, or auth headers.
Validate and authorize HTTP, file, queue, configuration/environment, LLM, and provider-callback inputs before mutation or persistence.
Tool execution requires allowlisted tools, scoped credentials, explicit user context, audit events, and refusal or denial tests.

Files:

  • n00n-interpreter/src/runner.rs
  • src/cmd/tui.rs
  • tests/non_tty.rs
  • n00n-agent/src/mcp/mod.rs
  • n00n-lua/tests/plugin_host.rs
  • n00n-acp/src/server.rs
🧠 Learnings (2)
📚 Learning: 2026-07-31T05:40:20.137Z
Learnt from: w0wl0lxd
Repo: w0wl0lxd/n00n PR: 203
File: changelog.d/203.fixed.md:1-2
Timestamp: 2026-07-31T05:40:20.137Z
Learning: Files in changelog.d/ whose names begin with a numeric fragment identifier are headingless changelog fragments. Treat their contents as entry bodies because generated release sections provide the headings; do not report Markdown MD041 or add an H1 heading to these fragments. This does not apply to changelog.d/README.md.

Applied to files:

  • changelog.d/230.fixed.md
📚 Learning: 2026-07-31T19:15:04.814Z
Learnt from: w0wl0lxd
Repo: w0wl0lxd/n00n PR: 206
File: changelog.d/orchestration-hardening.fixed.md:1-1
Timestamp: 2026-07-31T19:15:04.814Z
Learning: Files in changelog.d are changelog fragments intended for user-facing release notes and may begin directly with summary prose. Do not flag a missing Markdown H1 or require an H1 solely because Markdownlint MD041 reports it in these fragment files.

Applied to files:

  • changelog.d/230.fixed.md
🪛 Luacheck (1.2.0)
plugins/lib/n00n/secret_check.lua

[warning] 79-79: unused variable 'SECRET_ASSIGNMENT_PATTERN'

(W211)

🪛 markdownlint-cli2 (0.23.1)
changelog.d/230.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 (10)
plugins/code_execution/init.lua (1)

15-15: LGTM!

n00n-interpreter/src/runner.rs (1)

508-531: LGTM!

n00n-acp/src/server.rs (2)

94-105: LGTM!


124-164: LGTM!

n00n-agent/src/mcp/mod.rs (1)

1164-1164: LGTM!

Also applies to: 1351-1351, 1521-1521

changelog.d/230.fixed.md (1)

1-1: MD041 heading warning does not apply to this fragment.

Based on learnings from this repository, files in changelog.d/ whose names begin with a numeric fragment identifier are headingless by design, since generated release sections provide the heading. This applies here, so the markdownlint MD041 hint on Line 1 should not be actioned.

Source: Learnings

plugins/bash/init.lua (1)

22-22: LGTM!

Also applies to: 688-688, 716-716, 740-740, 792-796

n00n-lua/tests/plugin_host.rs (1)

3172-3210: LGTM!

Also applies to: 5938-5987

n00n-token-profile/baselines/cold_start.json (1)

7-20: LGTM!

src/cmd/tui.rs (1)

263-268: LGTM!

Comment thread n00n-acp/src/server.rs Outdated
Comment thread n00n-acp/src/server.rs Outdated
Comment thread n00n-agent/src/mcp/mod.rs Outdated
Comment thread n00n-agent/src/mcp/mod.rs Outdated
Comment thread plugins/bash/init.lua Outdated
Comment thread plugins/bash/init.lua Outdated
Comment thread plugins/edit/init.lua Outdated
Comment thread plugins/lib/n00n/secret_check.lua Outdated
Comment thread tests/non_tty.rs Outdated
Comment thread tests/non_tty.rs
@codecov

codecov Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 40.84507% with 126 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
n00n-acp/src/server.rs 33.67% 65 Missing ⚠️
n00n-agent/src/mcp/mod.rs 37.14% 44 Missing ⚠️
n00n-agent/src/mcp/stdio.rs 0.00% 16 Missing ⚠️
src/cmd/tui.rs 80.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@w0wl0lxd
w0wl0lxd enabled auto-merge August 3, 2026 06:25

@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: 4

Caution

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

⚠️ Outside diff range comments (1)
n00n-acp/src/server.rs (1)

133-142: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Return Invalid Request for non-request payloads.

A missing id does not by itself make a payload a notification. {}, null, and {"method": 1} reach the end of this branch without a response. Return AcpError::invalid_request() with RequestId::Null when the value is neither a response nor a request with a string method. JSON-RPC requires an invalid-request response for JSON that is not a valid Request object. (jsonrpc.org)

Proposed fix
             } else if let Some(id) = id {
                 server.respond(id, Err(AcpError::invalid_request()));
+            } else {
+                server.respond(RequestId::Null, Err(AcpError::invalid_request()));
             }
🤖 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-acp/src/server.rs` around lines 133 - 142, Update the incoming payload
dispatch around handle_incoming_response, handle_request, and
handle_notification so any value that is neither a response nor an object with a
string method produces an invalid-request response using RequestId::Null.
Preserve notification handling only for valid method payloads without an id, and
retain id-specific responses for valid request-shaped payloads.
🤖 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-acp/src/server.rs`:
- Around line 124-130: Update the invalid request-ID branch in the surrounding
JSON stream processing loop to reject the current value and continue processing
subsequent values instead of terminating the loop with break. Add a test
covering an invalid-ID request followed by a valid request on the same input
line, verifying both the error response and later valid request are handled.

In `@site/docs/content/lua-api/_index.md`:
- Around line 5924-5928: Align the published documentation with the actual
coverage of the secret_check.lua detector by removing or qualifying general
PII-detection claims and describing only secret-keyword/token patterns and
Basic/Bearer authorization headers. Update site/docs/content/lua-api/_index.md
lines 5924-5928 and the write, edit, multiedit, edit_lines, and insert_lines
justification descriptions in site/docs/content/tools/_index.md lines 45, 56,
66, 78, and 87 respectively; do not add detector rules unless explicitly
implementing and testing them.
- Around line 5930-5935: Update the n00n.secret_check example so
require("n00n.secret_check") is assigned to the local module variable used by
M.check and M.reason, making the block executable; alternatively label the block
explicitly as a pseudocode/signature excerpt if it is not intended to run.

In `@typos.toml`:
- Line 26: Update the secret ignore pattern in typos.toml to use the
case-insensitive pattern `(?i)secret`, replacing the current `[Ss]ecret` entry
so all capitalization variants are ignored.

---

Outside diff comments:
In `@n00n-acp/src/server.rs`:
- Around line 133-142: Update the incoming payload dispatch around
handle_incoming_response, handle_request, and handle_notification so any value
that is neither a response nor an object with a string method produces an
invalid-request response using RequestId::Null. Preserve notification handling
only for valid method payloads without an id, and retain id-specific responses
for valid request-shaped payloads.
🪄 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: 851319eb-41d2-4a5d-a3d4-eda075c156e0

📥 Commits

Reviewing files that changed from the base of the PR and between 9456e34 and 95987ac.

📒 Files selected for processing (5)
  • n00n-acp/src/server.rs
  • plugins/lib/n00n/secret_check.lua
  • site/docs/content/lua-api/_index.md
  • site/docs/content/tools/_index.md
  • typos.toml
💤 Files with no reviewable changes (1)
  • plugins/lib/n00n/secret_check.lua
📜 Review details
⏰ Context from checks skipped due to timeout. (15)
  • GitHub Check: Coverage
  • GitHub Check: MSRV (1.97)
  • GitHub Check: Test (Windows)
  • GitHub Check: Build (Windows)
  • GitHub Check: Build
  • GitHub Check: Rustdoc
  • GitHub Check: Lint (Windows)
  • GitHub Check: Format (Rust)
  • GitHub Check: Docs
  • GitHub Check: Lint
  • GitHub Check: Test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (rust)
  • GitHub Check: Criterion
🧰 Additional context used
📓 Path-based instructions (2)
site/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

User documentation should be warm, simple, concise, easy for non-native English speakers, story-oriented, without em-dashes, emojis, or an AI tone.

Files:

  • site/docs/content/tools/_index.md
  • site/docs/content/lua-api/_index.md
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Do not add unsafe code, FFI, global mutable state, static mut, or unchecked transmute-like behavior without written review, an explicit lint exception, and a SAFETY comment where applicable.
Do not use unwrap, expect, panic!, todo!, unimplemented!, or dbg! in production Rust code; tests are exempt from the unwrap/expect/panic restriction.
Do not silently discard failures with unwrap_or, unwrap_or_default, .ok() on Result, or equivalent defaults; return typed errors, reject the operation, or use an explicitly named fallback with sanitized structured logging.
Use idiomatic Rust, descriptive names, minimal state, and avoid unnecessary comments, bloat, and magic numbers or strings.
Import types at the top of the file and use short imported names; keep constants immediately after imports.
Use Result<T, E> and explicit error handling instead of panics; use thiserror for library/domain errors and color-eyre at binary edges.
Use #[derive(Copy)] only for structs containing one primitive field.
Prefer structured logging with useful fields and provide helpful, sanitized error messages.
Place unit tests in the same file inside #[cfg(test)] modules; use #[test_case] and snake_case test names.
Propagate typed errors with ?, ok_or_else, and map_err; library crates use thiserror and binaries use color-eyre.
Treat LLM and provider output as untrusted input; validate schemas, domain constraints, and source evidence before persistence or action.
Do not log raw provider payloads, prompts, credentials, or user session data, and never commit credentials, API keys, tokens, cookies, or auth headers.
Validate and authorize HTTP, file, queue, configuration/environment, LLM, and provider-callback inputs before mutation or persistence.
Tool execution requires allowlisted tools, scoped credentials, explicit user context, audit events, and refusal or denial tests.

Files:

  • n00n-acp/src/server.rs
🔇 Additional comments (2)
n00n-acp/src/server.rs (1)

94-105: LGTM!

site/docs/content/tools/_index.md (1)

24-24: LGTM!

Also applies to: 44-44, 47-47, 59-59, 69-69, 81-81

Comment thread n00n-acp/src/server.rs
Comment thread site/docs/content/lua-api/_index.md Outdated
Comment thread site/docs/content/lua-api/_index.md
Comment thread typos.toml Outdated
@w0wl0lxd

w0wl0lxd commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

Addressed the remaining review findings in commit 33346f145:

  • Propagate ACP stdout serialization/write/flush failures instead of returning success.
  • Continue after invalid request IDs and return Invalid Request for malformed non-request JSON values.
  • Make MCP timeout shutdown clear published state before killing/reaping child process groups, and log poisoned mutex recovery.
  • Tighten shell command-boundary detection for ;, ||, &, and newlines.
  • Share secret justification validation, detect credential-style assignments such as userCredential=..., and keep multiedit errors readable.
  • Align generated docs and non-TTY cleanup/assertions.

Validation: cargo check -p n00n-acp -p n00n-agent, targeted ACP/MCP/Lua/non-TTY tests, full n00n-lua plugin-host tests (239 passed), and clippy for touched Rust crates all pass.

@greptile-apps

greptile-apps Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR delivers Phase 2 of a bug-hunt sprint across five subsystems: ACP server robustness (invalid UTF-8 and overflowing request IDs), MCP shutdown task leak, TUI non-TTY crash, bash exfiltration gating, and write/edit secret-pattern detection. The changes are well-scoped, tested, and generally correct.

  • ACP (n00n-acp/src/server.rs): invalid UTF-8 on stdin now returns a JSON-RPC parse error and continues; unparseable or overflowing request IDs are rejected with invalid_request instead of silently coercing to RequestId::Null; stdout write failures are now surfaced rather than swallowed.
  • MCP (n00n-agent/src/mcp/mod.rs, stdio.rs, transport.rs): McpHandle now holds the command-loop Task so it can be cancelled when graceful shutdown times out; StdioTransport gains a force_shutdown that calls kill_and_reap after setting the alive flag, and pre-captures the child pid so child_pids() is lock-free.
  • Bash / write / edit (plugins/): exfiltration-prone commands and secret-bearing content now require an explicit justification; a new secret_check.lua module provides the heuristic detection used by write, edit, multiedit, edit_lines, and insert_lines.

Confidence Score: 5/5

Safe to merge; all changes are well-scoped bug fixes with corresponding tests and no regressions identified.

The Rust fixes (ACP, MCP, TUI) follow straightforward error-propagation patterns with clear test coverage. The Lua security gates are conservative by design and the single finding — eight unreachable keywords in SECRET_KEYWORDS — has no runtime impact because the non-suffixed versions of those same keywords already cover every real assignment the gmatch can produce.

Files Needing Attention: plugins/lib/n00n/secret_check.lua — the = / : suffixed keyword entries are dead code and can be trimmed.

Important Files Changed

Filename Overview
n00n-acp/src/server.rs Fixes invalid UTF-8 panic by catching InvalidData and responding with parse_error; changes request_id to return Result so malformed/overflowing IDs are rejected with invalid_request instead of silently coercing to Null; adds writer failure detection to surface stdout errors.
n00n-agent/src/mcp/mod.rs Stores the command-loop task in McpHandle so it can be explicitly cancelled when graceful shutdown times out, preventing the previously leaked background task.
n00n-agent/src/mcp/stdio.rs Separates pid capture from ChildGuard (stored separately so child_pids() is lock-free), wraps ChildGuard in async Mutex, and adds force_shutdown that calls kill_and_reap after setting the alive flag.
n00n-agent/src/mcp/transport.rs Adds force_shutdown as a default no-op to McpTransport trait, so non-stdio transports don't need to implement it.
plugins/lib/n00n/secret_check.lua New heuristic secret/PII detection module; the 8 keywords ending with = or : in SECRET_KEYWORDS are unreachable via contains_keyword(key) since the gmatch key-capture pattern cannot produce strings containing = or :.
plugins/bash/init.lua Adds exfiltration_command_reason to gate curl, wget, nc, ncat, dig, nslookup, and encoded-data patterns behind a justification; the network variable and its two dependent branches are dead code (previously flagged).
plugins/write/init.lua Integrates secret_check.require_justification before the actual file write; correctly placed before path resolution so the error is returned without side effects.
plugins/edit/init.lua Adds secret_check gates to edit, multiedit, edit_lines, and insert_lines; multiedit uses the shared top-level justification field and prefixes error messages with 0-based edit index.
src/cmd/tui.rs Adds pre-flight TTY check (stdin and stdout) that returns a clear error instead of panicking inside ratatui when running in a pipe/non-TTY environment.
plugins/code_execution/init.lua Removes sys and os from the Python preamble; removing sys may silently break generated scripts that use sys.exit() or sys.stderr (previously flagged).

Sequence Diagram

sequenceDiagram
    participant LLM as LLM / Tool caller
    participant Tool as write / edit / multiedit
    participant SC as secret_check.lua
    participant FS as Filesystem

    LLM->>Tool: call(content, justification?)
    Tool->>SC: require_justification(content, justification, tool_name)
    SC->>SC: secret_assignment_keyword(content)
    alt "keyword match AND value >= 16 chars"
        SC-->>Tool: "{ llm_output: error, is_error: true }"
        Tool-->>LLM: error — provide justification
    else authorization header literal
        SC-->>Tool: "{ llm_output: error, is_error: true }"
        Tool-->>LLM: error — provide justification
    else no match OR justification provided
        SC-->>Tool: nil (ok)
        Tool->>FS: write / apply edit
        Tool-->>LLM: success
    end
Loading

Reviews (2): Last reviewed commit: "docs: regenerate lua API reference" | Re-trigger Greptile

Comment thread plugins/bash/init.lua Outdated
Comment thread plugins/lib/n00n/secret_check.lua Outdated
Comment thread plugins/code_execution/init.lua Outdated
@w0wl0lxd

w0wl0lxd commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

@cursor review verbose=true

@cursor

cursor Bot commented Aug 3, 2026

Copy link
Copy Markdown

Bugbot request id: serverGenReqId_f4d8795e-1d90-46b3-aa6b-1bdddb5af855

@cursor

cursor Bot commented Aug 3, 2026

Copy link
Copy Markdown

Bugbot rules debug

No rules were used for this review.

https://cursor.com/docs/bugbot#team-rules

Bugbot request id: serverGenReqId_f4d8795e-1d90-46b3-aa6b-1bdddb5af855

@cursor

cursor Bot commented Aug 3, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_f4d8795e-1d90-46b3-aa6b-1bdddb5af855)

@greptile-apps greptile-apps 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.

w0wl0lxd has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

- Fix writer task error propagation in serve flow
- Add test_case attribute to unit tests in n00n-acp/src/server.rs
- Add invalid_id_continues_to_next_value test
- Fix poisoned mutex handling in MCP shutdown with structured warn
- Update secret_check.lua docs with actual coverage
- Add child_pids method to McpTransport trait
Resolved conflict in n00n-acp/src/server.rs:
- Added .await to handle_request call (from main)
- Preserved error handling logic for invalid requests (from PR branch)
- Fixed missing closing brace
@w0wl0lxd

Copy link
Copy Markdown
Owner Author

@codex review

@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: 8cc1eea67b

ℹ️ 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".


local function secret_assignment_keyword(s)
local l = lower(s)
for key, value in l:gmatch("([%w_%-%.]+)%s*[:=]%s*[\"']?([A-Za-z0-9+/_%-]+)") do

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Accept quoted keys when scanning credentials

For JSON-style credentials such as {"api_key": "abcdefghijklmnop"}, this pattern cannot match because it requires : or = immediately after the captured key and does not allow the closing quote. The write handler therefore persists a common credential-file representation without requiring justification; support quoted keys or parse the relevant serialization formats before mutation.

AGENTS.md reference: AGENTS.md:L78-L78

Useful? React with 👍 / 👎.

Comment thread plugins/edit/init.lua
end),

handler = function(input, ctx)
local secret_error = secret_check.require_justification(input.new_string, input.justification, "edit")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Validate the completed edit instead of only the replacement

When an existing file contains API_KEY=PLACEHOLDER and an edit replaces only PLACEHOLDER with a long credential, input.new_string has no secret-bearing key, so this check passes and the resulting assignment is persisted without justification. The same fragment-only check is used by the other edit variants; validate the reconstructed file content inside the edit callback before writing it.

AGENTS.md reference: AGENTS.md:L78-L78

Useful? React with 👍 / 👎.

Comment thread n00n-acp/src/server.rs
Comment on lines +714 to +718
#[test]
fn read_request_returns_parse_error_on_invalid_utf8() {
// Invalid UTF-8 is handled in the serve loop with InvalidData error kind
// It responds with parse_error and continues
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exercise invalid UTF-8 handling in the regression test

This test contains no invocation or assertion, so it passes even if the serve loop again terminates on invalid UTF-8 instead of returning a parse error and continuing; the adjacent EOF test has the same problem. Drive the server with invalid bytes and assert the emitted JSON-RPC response and continued request processing.

AGENTS.md reference: AGENTS.md:L54-L56

Useful? React with 👍 / 👎.

@w0wl0lxd

Copy link
Copy Markdown
Owner Author

Closing this conflicting multi-area bug-hunt bundle. Several ideas remain useful, but unresolved ACP and secret-validation defects require separate focused PRs from current main.

@w0wl0lxd w0wl0lxd closed this Aug 12, 2026
auto-merge was automatically disabled August 12, 2026 07:58

Pull request was closed

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