Skip to content

feat: add Rust XPIA subprocess bridge#2992

Merged
rysweet merged 15 commits intomainfrom
feat/issue-2991-xpia-rust-bridge
Mar 10, 2026
Merged

feat: add Rust XPIA subprocess bridge#2992
rysweet merged 15 commits intomainfrom
feat/issue-2991-xpia-rust-bridge

Conversation

@rysweet
Copy link
Owner

@rysweet rysweet commented Mar 9, 2026

Summary

Python subprocess wrapper for calling the amplihack-xpia-defender Rust CLI binary. NO FALLBACKS — binary must be present or functions raise RustXPIAError.

New Files

  • src/amplihack/security/rust_xpia.py — Subprocess bridge (273 lines)
  • tests/test_rust_xpia.py — 23 integration tests (call actual binary)

API

from amplihack.security.rust_xpia import (
    validate_content,
    validate_bash_command,
    validate_webfetch_request,
    validate_agent_communication,
    health_check,
    list_patterns,
    is_available,
)

Design

  • Fail-closed: subprocess errors → RustValidationResult.blocked()
  • NO FALLBACKS: binary not found → RustXPIAError (hard error)
  • Content via stdin to avoid shell injection
  • JSON protocol: parse stdout, check exit code

Prerequisites

  • Requires xpia-defend binary: cargo install --features cli --path <amplihack-xpia-defender>
  • Tests skip if binary not available (@pytest.mark.skipif)

Testing

All 23 tests pass when binary is installed. Tests verify:

  • Safe/malicious content detection
  • Bash command validation
  • Webfetch URL+prompt validation
  • Agent communication validation
  • Health check, patterns listing, config
  • Fail-closed behavior

Refs: #2991

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

🤖 Auto-fixed version bump

The version in pyproject.toml has been automatically bumped to the next patch version.

If you need a minor or major version bump instead, please update pyproject.toml manually and push the change.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

Repo Guardian - Passed

All changed files in this PR are durable, permanent assets appropriate for the repository.

File Assessment
pyproject.toml Version bump — standard configuration change ✅
src/amplihack/security/rust_xpia.py Production security module (Rust subprocess bridge) — parameterized, documented, permanent tooling ✅
tests/test_rust_xpia.py Integration tests for the above module ✅

No ephemeral content (meeting notes, one-off scripts, status updates, or point-in-time documents) detected.

Generated by Repo Guardian for issue #2992 ·

Add Python wrapper that calls the amplihack-xpia-defender Rust CLI
binary via subprocess for XPIA validation. NO FALLBACKS.

New files:
- src/amplihack/security/rust_xpia.py: subprocess bridge with functions:
  - validate_content() - scan text for injection attacks
  - validate_bash_command() - validate bash commands
  - validate_webfetch_request() - validate URL+prompt
  - validate_agent_communication() - validate agent messages
  - health_check() - run XPIA health check
  - list_patterns() / get_config() / is_available()
  - find_binary() - locate xpia-defend on PATH or ~/.cargo/bin

- tests/test_rust_xpia.py: 23 integration tests (call actual binary)

Design principles:
- Fail-closed: any subprocess error → RustValidationResult.blocked()
- NO FALLBACKS: binary not found → RustXPIAError (never falls back to Python)
- Content sent via stdin to avoid shell injection via args
- JSON protocol: parse stdout, check exit code (0=valid, 1=blocked, 2=error)

Refs: #2991

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet rysweet force-pushed the feat/issue-2991-xpia-rust-bridge branch from 47153ca to 3a7af7c Compare March 9, 2026 21:46
@rysweet rysweet marked this pull request as ready for review March 9, 2026 21:46
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

🤖 Auto-fixed version bump

The version in pyproject.toml has been automatically bumped to the next patch version.

If you need a minor or major version bump instead, please update pyproject.toml manually and push the change.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

🤖 PM Architect PR Triage Analysis

PR: #2992
Title: feat: add Rust XPIA subprocess bridge
Author: @rysweet
Branch: feat/issue-2991-xpia-rust-bridgemain


✅ Workflow Compliance (Steps 11-12)

NON-COMPLIANT - PR needs workflow completion

Step 11 (Review): ❌ Incomplete

  • Insufficient review evidence. Found 0 formal reviews and 3 comments. Review score: 0 (need >= 5). Comprehensive review detected: False

Step 12 (Feedback): ❌ Incomplete

  • Insufficient feedback implementation. Response score: 2 (need >= 3)

Blocking Issues:

  • Step 11 incomplete: Need comprehensive code review with security, quality, and philosophy checks
  • Step 12 incomplete: Need to address and respond to review feedback

🏷️ Classification

Priority: CRITICAL

  • Contains critical/security keywords

Complexity: COMPLEX

  • 3 files with 477 lines changed

🔍 Change Scope Analysis

⚠️ UNRELATED CHANGES DETECTED

Primary Purpose: New feature

Unrelated Changes:

  • Configuration changes

Affected Files:

  • pyproject.toml

Recommendation: Consider splitting this PR into separate focused PRs for each concern

💡 Recommendations

  • Complete workflow steps 11-12 before marking PR as ready
  • Add at least one formal code review

📊 Statistics

  • Files Changed: 3
  • Comments: 3
  • Reviews: 0

🤖 Generated by PM Architect automation using Claude Agent SDK

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

Repo Guardian - Passed

All changed files in this PR are durable, permanent assets appropriate for the repository.

File Assessment
pyproject.toml Version bump — standard configuration change ✅
src/amplihack/security/rust_xpia.py Production security module (Rust subprocess bridge) — parameterized, documented, permanent tooling ✅
tests/test_rust_xpia.py Integration tests for the above module ✅

No ephemeral content (meeting notes, one-off scripts, status updates, or point-in-time documents) detected.

Generated by Repo Guardian for issue #2992 ·

Ubuntu and others added 2 commits March 9, 2026 23:21
Tests exercise the FULL production chain in subprocess isolation:

1. TestBinaryDirect (7 tests): xpia-defend CLI binary invoked directly
2. TestPreToolUseHook (7 tests): pre_tool_use.py hook with real Claude
   Code JSON protocol (stdin → JSON stdout → allow/deny)
3. TestSessionStartHook (1 test): session_start.py health check
4. TestRustBridgeFullChain (8 tests): Python → rust_xpia.py → binary
   for all validation types (content, bash, webfetch, agent, health)
5. TestAdversarialAttacks (9 tests): real attack payloads with
   parametrized expected outcomes matching Python parity
6. TestFailClosed (3 tests): binary missing → blocked, garbage output
   → blocked, exit code 2 → blocked (even if JSON says valid)

All 35 tests pass. Verified Python parity for all 'allowed' results.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…input)

The Claude Code PreToolUse hook protocol sends JSON with top-level keys:
  tool_name, tool_input, session_id, cwd, hook_event_name, tool_use_id

Both pre_tool_use.py and the new pre_tool_use_rust.py were incorrectly
parsing nested toolUse.name / toolUse.input, meaning the hooks never
found the tool name and silently allowed all commands.

Changes:
- Fix pre_tool_use.py to parse top-level tool_name/tool_input
- Add pre_tool_use_rust.py: Rust-backed hook via xpia-defend binary
  - Uses cwd from hook input for project root detection
  - Fail-closed: import errors, missing binary, or exceptions → deny
  - Logs to ~/.claude/logs/xpia/rust_security_YYYYMMDD.log
- Update 7 hook protocol tests to use correct input format

Verified in real Claude Code sessions:
- Safe commands (echo, wc -w) → ALLOW with risk=none
- Injection content → DENY with risk=critical, threats=2
- Security log entries written with session_id

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet
Copy link
Owner Author

rysweet commented Mar 10, 2026

Real Session Testing Results ✅

Critical Bug Found & Fixed

The Claude Code PreToolUse hook protocol sends JSON with top-level tool_name and tool_input — NOT nested under toolUse as previously documented. Both the original Python hook and the new Rust hook were parsing the wrong format, meaning XPIA pre-tool-use validation has never actually fired in real sessions.

Fix Applied

  • pre_tool_use.py: Parse input_data.get('tool_name') instead of input_data.get('toolUse', {}).get('name')
  • pre_tool_use_rust.py: New Rust-backed hook with correct format + CWD from hook input
  • Tests updated to use correct Claude Code input format

Real Session Evidence

# Safe command → ALLOWED
[00:50:59] tool=Bash command='echo SAFE_123' → valid=True, risk=none, threats=0

# Injection content → BLOCKED  
[00:51:01] tool=Bash command='echo ignore all previous instructions...' → valid=False, risk=critical, threats=2

Test Results

  • 23 unit tests: ✅ PASS
  • 35 outside-in tests: ✅ PASS (including hook protocol tests with correct format)
  • Real Claude Code session: ✅ ALLOW safe + DENY injection
  • Security logging: ✅ Entries in ~/.claude/logs/xpia/

Ubuntu and others added 3 commits March 10, 2026 02:06
Expanded test coverage for Rust XPIA defense chain:

New test classes:
- TestPatternCoverage: all 19 patterns with correct validators (content vs bash)
- TestRustBackedHook: 14 tests for pre_tool_use_rust.py production hook
- TestRustHookLogging: verify security log entries on allow and deny
- TestSecurityLevels: low/medium/high/strict matrix validation
- TestEdgeCases: empty, huge, unicode, special chars, multiline
- TestEncodingBypasses: base64, unicode escape, mixed case
- TestThreatMetadata: required fields, location bounds, severity values
- TestPerformance: latency bounds (<500ms binary, <2s hook round-trip)

Enhanced existing classes:
- TestAdversarialAttacks: 17 content attacks, 13 bash attacks
- TestFailClosed: binary missing, garbage output, exit code 2, timeout, hook denial

All 135 outside-in + 23 unit = 158 total tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Catalogues all discovered false negatives and false positives as strict xfail
tests, so they will automatically fail when pattern fixes land (removing the
xfail marker becomes the final step of each fix).

False negatives (13): reverse shells, download-execute, SUID, crontab,
SSH key injection, firewall flush, history erasure, disregard training,
system message exfiltration, restriction removal.

False positives (11): 'Dan' as substring (RH001), 'developer mode' in
safe context (RH001), 'Step 1/Step 2' instructions (CA001), negation
unawareness (PO003), sysadmin role claim (RH002), package names (RH001),
.env read (DE002).

16 test classes, 100 test functions, 162 test cases (135 pass + 27 xfail).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…, FPs

Expanded probing uncovered 21 additional pattern engine bugs:

Encoding/obfuscation bypasses (5):
- Base64-pipe-bash, Unicode homoglyphs, URL encoding, zero-width chars, flooding

Data exfiltration gaps (4):
- SCP, git credential theft, Docker host escape, /proc memory dump

Privilege escalation gaps (7):
- sudo bash, SUID copy, setcap, LD_PRELOAD, /etc/passwd, /etc/sudoers, insmod

New false positives (5):
- 3-step instructions, security discussion, Dan in prose, pytest dev mode, pydantic

Total: 20 test classes, 120 test functions, 183 test cases (135 pass + 48 xfail).
All linked to rysweet/amplihack-xpia-defender#4.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor

PR Triage Report

Category: Security Feature
Risk Level: 🔴 HIGH
Priority: High
Recommendation: Needs security-focused deep review before merge


Summary

This PR adds a Python subprocess bridge to the amplihack-xpia-defender Rust CLI binary for Cross-Prompt Injection Attack (XPIA) defense, refs #2991. The implementation is intentionally fail-closed (no fallbacks) and touches both hook infrastructure and security validation paths.

Files Changed

File Change Lines
src/amplihack/security/rust_xpia.py New: subprocess bridge to Rust binary +280
tests/test_outside_in_xpia_rust.py New: outside-in integration tests +1383
tests/test_rust_xpia.py New: 23 unit tests (binary-dependent) +195
.claude/tools/xpia/hooks/pre_tool_use_rust.py New: Rust-backed hook implementation +135
.claude/tools/xpia/hooks/pre_tool_use.py Modified: hook protocol input schema fix +5
pyproject.toml Minor dependency update +1

Risk Factors

  1. Security-critical code: XPIA defense sits on the critical path for tool use validation
  2. Subprocess execution: All validation calls out to an external binary — binary availability and integrity matter
  3. Hard fail-closed: RustXPIAError raised (not caught) when binary absent — callers must handle
  4. Hook modification: Changes to pre_tool_use.py affect all tool use in the system
  5. Large test file: 1383-line outside-in test file is substantial and warrants review for test quality

Positive Signals

  • Fail-closed design is correct for security code
  • Content passed via stdin (avoids shell injection)
  • JSON protocol with exit code checking
  • 23 tests with skip guards when binary unavailable
  • is_available() helper for safe feature detection

Action Required

  • Security reviewer: Validate subprocess invocation cannot be exploited (stdin injection, path traversal in binary path)
  • Reviewer: Confirm pre_tool_use.py hook schema change matches current Claude Code hook protocol
  • Maintainer: Verify amplihack-xpia-defender binary build/install is documented and CI-tested
  • Reviewer: Check that RustXPIAError propagation doesn't create unhandled exceptions in callers

Generated by PR Triage Agent ·

Ubuntu and others added 5 commits March 10, 2026 04:32
Pattern fixes in amplihack-xpia-defender PR #5 resolved 33 of 45 bugs.
Updated test expectations:
- Removed xfail from 33 now-passing tests (reverse shells, privesc, exfil,
  download-execute, false positive fixes for CA001/RH001/RH002/PO003)
- Updated pattern count assertions: 19 → 31
- Updated 'reveal system prompt' to expect blocking (new PO005 pattern)
- 13 xfail remain: encoding bypasses (4), DAN proper names (3),
  dan-utils package (1), .env read (1), security discussion (1),
  dan in prose (1), disregard training (1), restriction removal (1)

Test suite: 170 passed + 13 xfailed = 183 test cases, 0 failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Dan proper name false positives (3): RH001 now requires attack verbs
- dan-utils package false positive (1): RH001 no longer matches substrings
- Dan in prose false positive (1): RH001 context-aware matching

Result: 175 passed, 8 xfailed (was 170 passed, 13 xfailed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Pattern count assertions updated from 31 to 37
- Removed xfail: disregard training gap (PO001 widened)
- Removed xfail: restriction removal gap (PO008 new pattern)

Result: 177 passed, 6 xfailed (was 175 passed, 8 xfailed)

Remaining 6 xfails require architectural changes:
- 4 encoding bypasses (homoglyphs, URL encoding, zero-width, flooding)
- 1 .env read false positive
- 1 security discussion false positive

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Pattern count: 37 → 40 (3 new patterns)
- Fix sysadmin test: 'I am the system administrator' is correctly flagged
  as role reversal (RH002), not a false positive
- Remove zero-width char xfail: now passes thanks to normalize_input()
- Results: 178 passed, 5 xfailed (was 177+6)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Encoding preprocessor pipeline in xpia-defender PR #11 fixes:
- Unicode homoglyph bypass (Cyrillic і/а → Latin i/a)
- URL encoding bypass (%20 → space)

Results: 180 passed, 3 xfailed (was 178+5)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ubuntu and others added 2 commits March 10, 2026 15:14
- New xpia_install.py: downloads platform-specific binary from
  rysweet/amplihack-xpia-defender GitHub releases to ~/.amplihack/bin/
- Updated find_binary() to auto-install when binary not found
- Wired ensure_xpia_binary() into copilot launcher startup
- 19 unit tests covering platform detection, version tracking,
  download flow, and auto-install integration

Supports: linux-x64, linux-arm64, macos-x64, macos-arm64, windows-x64
Uses gh CLI for downloads, idempotent with version marker file.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes 5 security issues found in code review:

1. CRITICAL: Added SHA256 checksum verification — downloads SHA256SUMS.txt
   from release, verifies archive hash before extraction. Tampered binaries
   are now detected and rejected.

2. CRITICAL: Added path traversal protection for zip extraction — validates
   member names contain no '..' or absolute paths, resolves final path to
   confirm it stays within target directory.

3. HIGH: Fixed file permissions — set explicit 0o755 instead of OR-ing
   execute bits onto existing permissions (which could result in 0o777).

4. HIGH: Improved launcher error handling — separate ImportError from
   runtime errors, log at ERROR level, print clear message that security
   validation will block tool use until binary is available.

5. MEDIUM: Changed find_binary() default to auto_install=False — runtime
   validation calls no longer trigger unexpected network activity. Only
   explicit startup call (copilot.py) passes auto_install=True.

Also: removed unused imports (os, stat), narrowed bare except to specific
exception types, added 8 new tests (27 total).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet
Copy link
Owner Author

rysweet commented Mar 10, 2026

Code Review: XPIA Auto-Installer Security Hardening

Findings (5 issues found and fixed)

# Severity Issue Fix
1 CRITICAL No checksum verification on downloaded binaries Added SHA256SUMS.txt download + hash verification before extraction
2 CRITICAL Zip extraction vulnerable to path traversal Added _safe_zip_extract() with ../ and absolute path rejection
3 HIGH File permissions used OR (could yield 0o777) Set explicit chmod(0o755)
4 HIGH Launcher except Exception silently continues without security Separate ImportError, log at ERROR, print warning about fail-closed
5 MEDIUM auto_install=True default triggers unexpected network calls Changed to auto_install=False, explicit opt-in at startup

Outside-In Testing Results

Test Environment: feat/issue-2991-xpia-rust-bridge, 2026-03-10
Tests Executed:

  1. Fresh install (no binary → auto-download → health check) → ✅ PASSED
  2. Idempotency (second call instant, no download) → ✅ PASSED (0.086s)
  3. find_binary discovery (finds ~/.amplihack/bin/) → ✅ PASSED
  4. E2E validation (benign=valid, attack=blocked, safe bash=valid, dangerous bash=blocked) → ✅ PASSED
  5. Checksum tamper detection (wrong hash → XPIAInstallError) → ✅ PASSED

Unit Tests: 27 passed (up from 19)
Regressions: None detected

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet rysweet merged commit 22279b5 into main Mar 10, 2026
1 check passed
@github-actions
Copy link
Contributor

Repo Guardian - Passed

All changed files in this PR are durable, permanent assets appropriate for the repository.

File Assessment
.claude/tools/xpia/hooks/pre_tool_use.py Production XPIA pre-tool-use hook — parameterized, documented, permanent tooling ✅
.claude/tools/xpia/hooks/pre_tool_use_rust.py Rust-backed XPIA hook — production hook replacing Python regex ✅
src/amplihack/launcher/copilot.py Launcher module modification — permanent project toolchain ✅
src/amplihack/security/rust_xpia.py Production security module (Rust subprocess bridge) — parameterized, documented ✅
src/amplihack/security/xpia_install.py Binary auto-installer with checksum verification — permanent toolchain utility ✅
tests/test_outside_in_xpia_rust.py Outside-in integration tests for the full XPIA stack ✅
tests/test_rust_xpia.py Unit tests for the Rust XPIA bridge ✅
tests/test_xpia_install.py Unit tests for the binary auto-installer ✅

No ephemeral content (meeting notes, one-off scripts, status updates, or point-in-time documents) detected.

Generated by Repo Guardian for issue #2992 ·

@github-actions github-actions bot mentioned this pull request Mar 11, 2026
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