Skip to content

Harden tool execution: secure subprocess runner, improved tool checks, and safer installs#36

Merged
Neuro-Rift merged 2 commits into
mainfrom
codex/improve-code-robustness-and-error-handling
Mar 14, 2026
Merged

Harden tool execution: secure subprocess runner, improved tool checks, and safer installs#36
Neuro-Rift merged 2 commits into
mainfrom
codex/improve-code-robustness-and-error-handling

Conversation

@Neuro-Rift
Copy link
Copy Markdown
Owner

@Neuro-Rift Neuro-Rift commented Mar 14, 2026

User description

Motivation

  • Reduce risk from executing external discovery/exploitation tools by centralizing and hardening subprocess invocation and environment setup.
  • Provide reliable detection of tool availability and capability while giving clearer diagnostics to users and logs.
  • Make automated tool installation safer and more robust against missing dependencies and failing installs.

Description

  • Added a secure, fault-tolerant subprocess runner _run_command_secure with restricted environment, retries, resource limits, output sanitization, and optional Linux sandboxing (firejail).
  • Introduced helper functions for safety checks and validation: _get_restricted_env, _is_safe_argument, _is_safe_workdir, _build_preexec_limits, _sanitize_output, _validate_tool_output, _should_retry, and _verify_tool_capability.
  • Reworked tool detection and verification by changing is_tool_installed to accept verify_execution and by using shutil.which and executable checks; updated check_tools to use this verification and improved logging/console messages.
  • Hardened install_missing_tools to validate package manager dependencies (sudo, apt, go), perform apt update via the secure runner, install Go-based tools with _run_command_secure, surface failures without aborting when possible, and return consolidated success state.
  • Minor imports and typing updates (shutil, List) and added an interactive dev_mode_shell helper for development-time commands.

Testing

  • No automated tests were executed as part of this change.

Codex Task


CodeAnt-AI Description

Secure and validated tool execution, safer installs, and clearer tool checks

What Changed

  • Tool checks now verify a tool is present, executable, and optionally runnable; missing/unusable tools are reported with a clear console message and structured logs.
  • All external tool invocations and installs use a centralized secure runner with timeouts, retries, resource limits, sanitized output, and optional Linux sandboxing; this prevents execution of unsafe arguments and reduces crash/hangs during runs.
  • Automatic installation of missing tools performs an apt update via the secure runner, skips Go-based installs if Go is absent, and reports individual install failures without aborting the whole process; returns a consolidated success state.
  • Generated custom tools are saved only after sanitizing filenames and paths, with secure directory/file permissions, and invalid inputs are rejected with clear errors.
  • CLI/parsing and interactive prompts improved for clearer messages (e.g., AI pipeline/agent prompts, web UI launch warnings) and minor UX consistency fixes.

Impact

✅ Fewer unsafe tool executions
✅ Clearer install failure messages
✅ Safer automatic tool installation

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features

    • Added tool capability verification and enhanced dependency validation during installation.
  • Improvements

    • Strengthened tool execution with timeouts, resource limits, and structured retry logic for transient failures.
    • Enhanced error handling and user-facing warnings for tool management and execution issues.
    • Improved logging across execution paths for better visibility into tool operations.

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Mar 14, 2026

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 14, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 260d4006-d81e-4bf3-bd0b-4ff57e2e3941

📥 Commits

Reviewing files that changed from the base of the PR and between f2c87d8 and fc75b32.

📒 Files selected for processing (1)
  • neurorift_main.py

📝 Walkthrough

Walkthrough

This change implements a comprehensive security-hardening overhaul for external tool execution in NeuroRift, introducing restricted environments, subprocess limits, output sanitization, retry logic, and enhanced error handling across tool installation, verification, and generation workflows.

Changes

Cohort / File(s) Summary
Security Infrastructure
neurorift_main.py
Introduces 7 new private helpers: _get_restricted_env, _is_safe_argument, _is_safe_workdir, _build_preexec_limits, _sanitize_output, _validate_tool_output, _should_retry. Implements _run_command_secure for robust subprocess execution with timeouts, memory limits, file descriptor limits, retries, and JSON validation.
Tool Verification & Installation
neurorift_main.py
Adds _verify_tool_capability flow with capability verification and optional execution testing. Enhances tool installation with dependency validation for sudo/apt, guards installation steps behind dependency checks, replaces direct system calls with secure runner, introduces boolean aggregation for multi-tool success tracking, and expands error handling with structured metrics logging.
Tool Generation & Discovery
neurorift_main.py
Updates generate_tool signature to use consistent string default for identifier parameter. Adds metadata handling, secure permissions (600), and secure directory creation for generated tools. Extends path sanitization via SecurityValidator for custom tool paths.
Input Validation & Logging
neurorift_main.py
Refactors banner/session setup, target sanitization, and session directory creation with secure paths and restricted permissions. Adds verbose logging across execution paths including tool execution steps, retry attempts, and structured metric logging (tool_check_succeeded, tool_check_failed). Expands error classification for encoding, argument, timeout, permission, missing binary, and OS errors.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰✨ Through tunnels of code, we hop with care,
With limits and checks floating through the air,
Pre-exec guards and outputs so clean,
The safest of tool runs you've ever seen,
Security hardened, from whisker to toe! 🛡️

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/improve-code-robustness-and-error-handling
📝 Coding Plan
  • Generate coding plan for human review comments

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 and usage tips.

This commit fixes the style issues introduced in ca327f7 according to the output
from Black.

Details: #36
@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Mar 14, 2026
@Neuro-Rift Neuro-Rift merged commit ddb27a9 into main Mar 14, 2026
3 of 5 checks passed
@Neuro-Rift Neuro-Rift deleted the codex/improve-code-robustness-and-error-handling branch March 14, 2026 11:40
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Mar 14, 2026

Sequence Diagram

This PR centralizes external command execution into a secure runner and routes both tool capability checks and installation through it. The flow improves safety by using restricted execution settings, validated output, and consolidated status reporting for missing or failed tools.

sequenceDiagram
    participant User
    participant NeuroRift
    participant SecureRunner
    participant OS

    User->>NeuroRift: Start tool check or install
    NeuroRift->>NeuroRift: Resolve executable path and permissions
    NeuroRift->>SecureRunner: Verify tool capability with help command
    SecureRunner->>OS: Run command with restricted environment and limits
    OS-->>SecureRunner: Return exit code and output
    SecureRunner-->>NeuroRift: Return sanitized validated result
    NeuroRift->>SecureRunner: Run package update and missing tool installs
    SecureRunner-->>NeuroRift: Return per tool outcomes with retries
    NeuroRift-->>User: Show consolidated success and warnings
Loading

Generated by CodeAnt AI

@deepsource-io
Copy link
Copy Markdown
Contributor

deepsource-io Bot commented Mar 14, 2026

DeepSource Code Review

We reviewed changes in f2c87d8...fc75b32 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade  

Focus Area: Hygiene
Security  

Reliability  

Complexity  

Hygiene  

Feedback

  • Stale, copy-pasted fragments
    • Multiple unused imports, redefinitions, and dead variables indicate bits were copied or left over as the file evolved; extracting small, focused functions and removing unused symbols will stop churn from accumulating.
  • Weak encapsulation and boundary-crossing
    • Direct calls into a client's protected internals and instance methods that don't use self show blurred module/class boundaries; define clear public APIs, convert stray instance methods to module functions, and avoid touching _-prefixed internals.
  • Brittle path/temp handling
    • The ad-hoc startswith path checks and insecure temp-dir usage reveal inconsistent filesystem assumptions; use pathlib comparisons (isrelativeto/resolve) and secure tempfile APIs (mkstemp/TemporaryDirectory) to validate and create safe paths.

Code Review Summary

Analyzer Status Updated (UTC) Details
Python Mar 14, 2026 11:39a.m. Review ↗

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Mar 14, 2026

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Output Validation
    _validate_tool_output requires non-empty stdout/stderr and marks outputs as invalid when both are empty or when JSON parsing fails. This can cause false negatives for legitimate tools whose help/version output is only on stderr or produce no output but still exit successfully. Verify downstream callers (e.g. _verify_tool_capability and check_tools) handle such cases and consider more tolerant validation for capability checks.

  • Go install PATH handling
    After running go install, binaries are placed in GOPATH/bin or GOBIN which may not be on PATH. The current install flow does not verify or surface where Go put the binaries, nor instruct the user to update PATH. This can produce silent "installed" state but binaries remain unusable. Add verification and user guidance (or copy binaries into tools dir) after install attempts.

Copy link
Copy Markdown

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

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: fc75b322e7

ℹ️ 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 neurorift_main.py
Comment on lines +261 to +263
if not stdout.strip() and not stderr.strip():
validation_passed = False
error_type = error_type or "empty_output"
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 zero-output subprocesses as successful

This validation rejects any command that exits with code 0 but produces no stdout/stderr, because empty_output flips validation_passed to false and _run_command_secure requires that flag for success. That makes silent-but-successful commands (including common go install runs when nothing is printed) look like failures, so install_missing_tools can report failed installs even when the tool was actually installed.

Useful? React with 👍 / 👎.

Comment thread neurorift_main.py
"""Create a minimal execution environment for subprocesses."""
return {
"PATH": os.environ.get("PATH", "/usr/bin:/bin"),
"HOME": str(self.base_dir),
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 Preserve Go install env when executing go install

The restricted environment forces HOME to the repo directory and drops Go-related env vars, so go install no longer honors the user’s configured GOBIN/GOPATH paths. In installs triggered from install_missing_tools, binaries are written under ${HOME}/go/bin relative to the project (not the user’s normal tool path), which commonly leaves the installed tools undiscoverable by later shutil.which checks.

Useful? React with 👍 / 👎.

Comment thread neurorift_main.py
Comment on lines +247 to +249
validation_passed = True
error_type = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Treating empty stdout and stderr as a validation failure breaks successful commands that intentionally produce no output (for example go install when cached), so installs/checks are marked failed even with exit code 0. Only enforce non-empty output when JSON output is explicitly expected. [logic error]

Severity Level: Major ⚠️
- ⚠️ `--install` reports false failures for Go tools.
- ❌ Setup automation may misclassify successful installs.
- ⚠️ Users retry installs unnecessarily, wasting time.
Suggested change
validation_passed = True
error_type = None
if expect_json and not stdout.strip():
validation_passed = False
error_type = error_type or "empty_output"
Steps of Reproduction ✅
1. Run CLI install flow via `python neurorift_main.py --install`; `_async_main()` calls
`vf.install_missing_tools()` at `neurorift_main.py:1174-1175`.

2. In `install_missing_tools()` (`neurorift_main.py:536-546`), missing Go tools trigger
`_run_command_secure(["go", "install", package], ...)`.

3. If `go install` exits `0` with no output, `_validate_tool_output()`
(`neurorift_main.py:247-249`) marks it invalid (`empty_output`), and
`_run_command_secure()` computes `success=False` at `neurorift_main.py:360-362`.

4. The install path logs failure and sets `all_successful=False`
(`neurorift_main.py:549-558`) even though the command returned success.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** neurorift_main.py
**Line:** 247:249
**Comment:**
	*Logic Error: Treating empty `stdout` and `stderr` as a validation failure breaks successful commands that intentionally produce no output (for example `go install` when cached), so installs/checks are marked failed even with exit code 0. Only enforce non-empty output when JSON output is explicitly expected.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Comment thread neurorift_main.py
Comment on lines +516 to +519
"tool_capability_check_failed",
extra={
"tool": tool,
"error_type": result.get("error_type"),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Requiring sudo unconditionally causes installation to fail on root-only/minimal environments where apt is available but sudo is not installed. Build the apt command dynamically so root runs apt directly and only require sudo for non-root execution. [possible bug]

Severity Level: Major ⚠️
- ❌ Root containers fail automated tool installation path.
- ⚠️ `--check` remediation cannot proceed without sudo binary.
- ⚠️ Extra manual setup needed in minimal environments.
Suggested change
"tool_capability_check_failed",
extra={
"tool": tool,
"error_type": result.get("error_type"),
if not self._validate_dependency("apt"):
return False
apt_cmd = (
["apt", "update"]
if hasattr(os, "geteuid") and os.geteuid() == 0
else ["sudo", "apt", "update"]
)
if apt_cmd[0] == "sudo" and not self._validate_dependency("sudo"):
return False
update_result = self._run_command_secure(apt_cmd, timeout=180, retries=1)
Steps of Reproduction ✅
1. Trigger install path using `python neurorift_main.py --install` (or `--check` then
approve install); call site is `_async_main()` at `neurorift_main.py:1169-1175`.

2. `install_missing_tools()` immediately requires both `sudo` and `apt` at
`neurorift_main.py:516-517`, before checking execution context.

3. In root/minimal images where `apt` exists but `sudo` is absent,
`_validate_dependency("sudo")` fails through `is_tool_installed()`
(`neurorift_main.py:487-490`), returning `False`.

4. Function exits early (`neurorift_main.py:517`); `apt update` at `neurorift_main.py:519`
never runs, though root could execute `apt` directly.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** neurorift_main.py
**Line:** 516:519
**Comment:**
	*Possible Bug: Requiring `sudo` unconditionally causes installation to fail on root-only/minimal environments where `apt` is available but `sudo` is not installed. Build the apt command dynamically so root runs `apt` directly and only require `sudo` for non-root execution.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Comment thread neurorift_main.py
list_tools_parser.add_argument('--verbose', action='store_true', help='Show detailed tool information')
list_tools_parser = subparsers.add_parser(
"list-tools", help="List all custom tools"
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The orchestrated mode defaults to defensive whenever --mode is omitted, which conflicts with the earlier default session mode (offensive) and can block offensive tools unexpectedly. Use the same default mode resolution in both places. [logic error]

Severity Level: Critical 🚨
- ❌ Orchestrated scans block offensive recon tools unexpectedly.
- ❌ ExecutionManager permission checks fail planned offensive steps.
- ⚠️ Session mode and runtime mode become inconsistent.
Suggested change
)
tool_mode = (
ToolMode.OFFENSIVE
if (args.mode or "offensive") == "offensive"
else ToolMode.DEFENSIVE
)
Steps of Reproduction ✅
1. Start orchestrated workflow without explicit mode: `python neurorift_main.py
--orchestrated --target example.com`; control enters `_async_main()` orchestrated branch
at `neurorift_main.py:1011`.

2. Earlier in the same function, session creation defaults mode to offensive
(`mode=args.mode or "offensive"`) at `neurorift_main.py:1005-1008`.

3. Orchestrated context then sets `tool_mode` using `args.mode == "offensive"` at
`neurorift_main.py:1029`; with omitted `--mode`, this resolves to `ToolMode.DEFENSIVE`.

4. During execution, `NROperator.execute_plan()` calls `ExecutionManager.execute_tool()`
(`modules/ai/agents.py:61-69`), and the mode gate rejects offensive tools
(`modules/orchestration/execution_manager.py:42-50`), including wrappers marked offensive
like `modules/tools/wrappers/nmap.py:12`.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** neurorift_main.py
**Line:** 1029:1029
**Comment:**
	*Logic Error: The orchestrated mode defaults to defensive whenever `--mode` is omitted, which conflicts with the earlier default session mode (`offensive`) and can block offensive tools unexpectedly. Use the same default mode resolution in both places.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Mar 14, 2026

CodeAnt AI finished reviewing your PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant