# x402 Remote Inference Integration — Security Audit & Comprehensive Plan

## Part 1: Security Audit of x402 Payment Rails

### Summary: 4 CRITICAL, 6 HIGH findings

#### CRITICAL

**C1: Private key not truly zeroed (nexus.ts L1455, L1901)**
`privKeyHex = "0".repeat(64)` only rebinds the JS variable — the original string lives on the heap until GC. JavaScript strings are immutable.
- **Remediation**: Use `Buffer` throughout (not strings). `buffer.fill(0)` overwrites bytes in place. Pass Buffer directly to crypto APIs.

**C2: x402-wallet.key is a permanent plaintext key file (nexus.ts L1449-1452)**
Lives in `.omnius/nexus/` for daemon lifetime. Any backup, snapshot, or directory listing tool exfiltrates the key. `wallet.enc` is meaningless as protection while this file exists.
- **Remediation**: Pass key to daemon via environment variable or anonymous pipe at spawn time. Delete file after daemon reads it (or never write it to disk).

**C3: Budget denylist bypass in doSpend (nexus.ts L1795)**
`checkBudget(amountSmallest, "transfer:direct", "")` passes empty string for peerId, so `deniedPeers` list is never checked. A blocked peer address can still receive a signed transfer.
- **Remediation**: Pass `targetAddress` as peerId to `checkBudget()`.

**C4: TOCTOU on file permissions (nexus.ts L1451-1452, L1464-1465)**
`writeFile()` then `chmod()` creates a window where the file is world-readable (default umask).
- **Remediation**: Use `fs.open(path, 'wx', 0o600)` + `fs.write()` to atomically create with correct permissions.

#### HIGH

**H1: Scrypt passphrase is predictable (nexus.ts L1440-1443)**
`hostname():username():nexus-wallet` — anyone with shell access to the machine can derive the key.
- **Remediation**: Add a user-provided PIN or use OS keyring (libsecret/keychain) when available.

**H2: npm version injection in daemon auto-install (nexus.ts ~L1107)**
`npm view open-agents-nexus version` output interpolated into `execSync`. DNS-hijacked registry response could inject shell commands.
- **Remediation**: Validate version string against `/^\d+\.\d+\.\d+$/` before interpolation.

**H3: No signature verification on spend proof (nexus.ts doSpend)**
The signed proof in `pending-transfer.json` is not verified before saving. If the signing fails silently, an invalid proof is written to disk and ledger.
- **Remediation**: Verify signature with `verifyTypedData` before writing proof or ledger entry.

**H4: Daemon x402 config accepts arbitrary ALCHEMY_API_KEY from env**
The daemon script reads `process.env.ALCHEMY_API_KEY` and passes it to the NexusClient x402 config. If the daemon runs in a shared environment, this could be exfiltrated.
- **Remediation**: Validate API key format before passing; consider injecting only via the spawn environment, not inherited env.

**H5: EIP-3009 nonce is random but not stored for replay detection**
`doSpend` generates a random nonce for each transfer but doesn't track used nonces. If a malicious peer resubmits a proof before the original submission, the user could see unexpected behavior.
- **Remediation**: USDC contract itself prevents nonce replay on-chain. Low risk in practice but should be documented.

**H6: No rate limiting on spend action**
An LLM can be prompt-injected to call `spend` in a loop. Budget policy catches per-day limits but the circuit breaker requires an RPC call that could timeout.
- **Remediation**: Add a local cooldown (e.g., minimum 5s between spend calls).

#### MEDIUM / LOW

- **M1**: `containsKeyMaterial` regex doesn't catch Base58 private keys or mnemonic phrases
- **M2**: Ledger entries written without signing — anyone with file access can forge entries
- **M3**: Budget policy file (`budget.json`) is not integrity-protected
- **L1**: No audit log of budget policy changes
- **L2**: Daemon log may contain sensitive peer IDs (useful for correlation attacks)

### Recommended Priority

1. ~~**Fix C3 immediately**~~ DONE — `doSpend` now passes `targetAddress` to `checkBudget()`
2. ~~**Fix C4**~~ DONE — all 3 key/wallet file writes use `fsOpen(path, "w", 0o600)` for atomic creation
3. **Plan C2 remediation** (daemon key delivery — architectural change, defer to next sprint)
4. **Document C1** (JS GC limitation — no perfect fix, but can improve with Buffer)

---

## Part 2: Current State Assessment

### What Exists Today

| Layer | Component | Status | Remote-Ready? |
|-------|-----------|--------|---------------|
| **Agent Loop** | `AgenticRunner` | Production | No — hardcoded local backend |
| **Backend Interface** | `AgenticBackend` | Production | Yes — clean interface, pluggable |
| **Backend Impl** | `OllamaAgenticBackend` | Production | Local only |
| **P2P Transport** | `NexusTool` (daemon-based) | Production | Yes — invoke_capability works |
| **P2P Mesh** | `PeerMesh` (WebSocket) | Built, not wired | Yes — gossip, heartbeat, capabilities |
| **Inference Router** | `InferenceRouter` | Built, not wired | Yes — trust scoring, secret redaction |
| **Secret Vault** | `SecretVault` | Built, not wired | Yes — OMNIUS_VAR placeholder system |
| **x402 Payments** | Wallet + spend + ledger | Production | Yes — EIP-3009, budget policy |
| **Sub-Agent** | `OpenCodeTool` | Production | No — spawns local subprocess |
| **Call Sub-Agent** | `CallSubAgent` | Production | No — uses parent's backend |

### Key Architectural Facts

1. **`AgenticBackend` is the integration point** — any implementation that satisfies `chatCompletion()` can drive the agent loop
2. **The InferenceRouter already handles tool-calling** — `P2PInferRequest` includes `tools` array, `P2PInferResponse` includes `toolCalls`
3. **Secret redaction is automatic** — vault scans all text for known values, replaces with `{{OMNIUS_VAR_*}}`, injects back on response
4. **Trust tiers control redaction depth** — LOCAL (no redaction), TEE (minimal), VERIFIED (standard), PUBLIC (full)
5. **The gap is "last mile" wiring** — InferenceRouter exists but is never called from AgenticRunner

---

## Part 3: The Four Scenarios Evaluated

### Scenario 1: Entire Stack Defers to Remote Inference
*"The whole agent runs on someone else's GPU"*

**How it would work**: Replace `OllamaAgenticBackend` with `NexusAgenticBackend` at CLI startup. Every `chatCompletion()` call routes through InferenceRouter to a remote peer.

**Already addressed?** Partially. The `AgenticBackend` interface supports this. InferenceRouter handles tool-calling. SecretVault protects secrets. What's missing is:
- `NexusAgenticBackend` class that adapts InferenceRouter → AgenticBackend interface
- CLI flag: `--backend nexus` or `--remote-peer 12D3KooW...`
- x402 budget integration (each chatCompletion costs money)

**Attractiveness**: Medium. Useful for headless agents on Raspberry Pi / VPS with no GPU. But latency and trust concerns make it less appealing for primary development.

**Security**: SecretVault handles credential safety. Trust tiers control exposure. x402 budget prevents runaway spend. This is actually the **safest** remote scenario.

### Scenario 2: Specific Tasks Routed to Remote Models Transiently
*"I need a 70B model for this one hard coding problem, then back to local 27B"*

**How it would work**: AgenticRunner's tool loop detects a "hard" task (or user explicitly requests), temporarily routes to a remote peer with the needed model, gets the response, returns to local inference.

**Already addressed?** No. The backend is currently immutable during a task. But the infrastructure is ready:
- InferenceRouter.`infer(model, messages)` is a one-shot call
- Could be wrapped as a tool: `nexus(action='remote_infer', model='llama3.3:70b', prompt='...')`
- Or implemented as backend fallback: local → timeout/quality check → remote

**Attractiveness**: HIGH. This is the "superpower" use case. A $200 laptop running 8B can seamlessly tap into a 122B model on the mesh for complex tasks, paying $0.001 per request.

**Security**: Medium risk. The "hard task" might contain the most sensitive context. SecretVault mitigates this. Budget policy caps per-invoke spend.

### Scenario 3: Sub-Agents Delegated to Remote Inference
*"Spawn a sub-agent that runs entirely on a remote peer's GPU"*

**How it would work**: When spawning a sub-agent, specify a remote backend:
```
sub_agent(task='Review this PR', backend='nexus', model='qwen3.5:122b', peer='12D3KooW...')
```
The sub-agent's entire AgenticRunner loop runs against the remote peer.

**Already addressed?** Partially. CallSubAgent already creates independent AgenticRunner instances. The pattern exists. What's missing:
- Sub-agent tool that accepts `backend` parameter
- NexusAgenticBackend (same as Scenario 1)
- Result return across the network boundary
- x402 payment for multi-turn conversations (not just single invoke)

**Attractiveness**: VERY HIGH. This is the marketplace killer feature. An agent can "hire" specialized remote agents for specific skills. A coding agent sends a security review sub-task to a peer running a security-specialized model.

**Security**: Lower risk than Scenario 2 — sub-agent context is scoped to just the delegated task. SecretVault can enforce stricter redaction for sub-agent contexts.

### Scenario 4: Interlaced Remote Inference (Any Point in Chain)
*"Mid-conversation, seamlessly route any individual LLM call to any peer"*

**How it would work**: Backend becomes a router, not a fixed endpoint. Each `chatCompletion()` call evaluates:
1. Is a local model available and capable? → Use local
2. Is a remote peer better (larger model, lower latency, specific capability)? → Route via InferenceRouter
3. Apply budget check before routing
4. Redact secrets, send, inject on response

**Already addressed?** The InferenceRouter's scoring formula already supports this:
```
score = trustWeight * (1 / (1 + latency/100)) * (1 - load) * modelMatch
```
What's missing: the "hybrid backend" that dynamically chooses local vs remote per-call.

**Attractiveness**: HIGHEST. This is the most flexible and the end-state vision. But also the most complex to implement correctly.

**Security**: Highest risk — any message in the conversation might be sent remotely. Requires robust SecretVault with comprehensive secret detection. Trust tier enforcement is critical.

---

## Part 4: Recommended Architecture — "The Mix" (Progressive Implementation)

### Phase 1: NexusAgenticBackend (enables Scenarios 1 & 3)
**Effort**: Medium | **Impact**: High | **Timeline**: This sprint

Create `NexusAgenticBackend` that implements `AgenticBackend`:

```typescript
export class NexusAgenticBackend implements AgenticBackend {
  constructor(
    private router: InferenceRouter,
    private model: string,
    private budgetChecker?: (cost: number) => Promise<boolean>,
  ) {}

  async chatCompletion(request: ChatCompletionRequest): Promise<ChatCompletionResponse> {
    // 1. Estimate cost from token count
    // 2. Check budget
    // 3. Route via InferenceRouter (handles redaction + peer selection)
    // 4. Map P2PInferResponse → ChatCompletionResponse
    // 5. Write ledger entry
  }
}
```

**What this unlocks**:
- `omnius run --backend nexus --model qwen3.5:122b` → full remote agent
- Sub-agents with `backend: "nexus"` → delegated remote execution
- `/p2p start` + `/p2p connect` → mesh is live, inference is routed

### Phase 2: Remote Inference Tool (enables Scenario 2)
**Effort**: Low | **Impact**: Very High | **Timeline**: This sprint

Add a `remote_infer` action to the nexus tool:

```typescript
case "remote_infer":
  // 1. Find best peer for requested model
  // 2. Budget check
  // 3. Route single inference call via InferenceRouter
  // 4. Return result to agent
  // Agent stays on local model but can "reach out" for specific questions
```

This is the easiest win — a single nexus action that any agent can call. No backend swapping needed. The agent decides when to use remote inference, just like calling any other tool.

**What this unlocks**:
- Agent running on 8B can call `nexus(action='remote_infer', model='qwen3.5:70b', prompt='Complex analysis...')`
- Budget-checked per-call
- Secret-safe via vault
- Agent retains autonomy — it chooses when to use remote help

### Phase 3: Hybrid Backend (enables Scenario 4)
**Effort**: High | **Impact**: Highest | **Timeline**: Next sprint

Create `HybridAgenticBackend` that dynamically routes:

```typescript
export class HybridAgenticBackend implements AgenticBackend {
  constructor(
    private localBackend: OllamaAgenticBackend,
    private remoteRouter: InferenceRouter,
    private policy: RoutingPolicy,
  ) {}

  async chatCompletion(request): Promise<Response> {
    const route = this.policy.decide(request, this.localBackend, this.remoteRouter);
    if (route === 'local') return this.localBackend.chatCompletion(request);
    return this.nexusBackend.chatCompletion(request); // via InferenceRouter
  }
}
```

**RoutingPolicy** decides based on:
- Model requirements (request asks for capability local model can't provide)
- Token count (large context → route to peer with bigger context window)
- Load (local GPU saturated → overflow to mesh)
- Cost (local is free, remote costs money → prefer local unless quality difference is high)
- User preference (explicit `/remote on` toggle)

### Phase 4: Marketplace Dynamics
**Effort**: Medium | **Impact**: Network effect | **Timeline**: Post-MVP

1. **Provider Dashboard**: `nexus(action='provider_stats')` — earnings, requests served, uptime
2. **Reputation System**: Track successful invocations, response quality, latency consistency
3. **Discovery Registry**: Public capability index so agents can find providers without prior connection
4. **Tiered Pricing**: Providers set per-model rates; consumers see a unified pricing menu
5. **SLA Guarantees**: Timeout → automatic failover to next-best peer; refund on failure

---

## Part 5: What Makes This Marketplace Attractive

### For Providers (GPU Owners)
- **Passive income**: Expose idle GPU capacity, earn USDC while sleeping
- **Zero config**: `omnius run` → `nexus connect` → `nexus expose --margin 0.3` → earning
- **x402 automatic payments**: No invoicing, no manual settlement. Payment flows with each request
- **Trust control**: Choose who can access your models (TEE, verified, public)
- **Usage metering**: Full audit trail in metering.jsonl + ledger.jsonl

### For Consumers (Agent Operators)
- **Access any model**: Your 8B laptop can tap into 122B models on the mesh
- **Budget safety**: Daily limits, per-invoke caps, circuit breaker — impossible to overspend
- **Secret safety**: SecretVault auto-redacts credentials before any request leaves your machine
- **Seamless**: Agent doesn't know it's using remote inference — same tool-calling loop
- **Transient or persistent**: Single question or entire sub-agent workflow — your choice

### For the Network
- **Self-reinforcing**: More providers → better model selection → more consumers → more revenue → more providers
- **Anti-centralization**: No single point of failure or control. Any node can be provider AND consumer
- **Trust graduated**: Start with `public` trust (full redaction), build to `verified`, eventually `tee`
- **Economic alignment**: x402 ensures providers are compensated, consumers get value, network grows

---

## Part 6: Implementation Order

| Step | Description | Files | Depends On |
|------|-------------|-------|------------|
| ~~**0**~~ | ~~Fix C3 budget bypass~~ DONE + C4 TOCTOU fix | nexus.ts | — |
| **1a** | Wire InferenceRouter into interactive.ts | interactive.ts | Already built |
| **1b** | Create NexusAgenticBackend | orchestrator/src/nexusBackend.ts | 1a |
| **1c** | Add `--backend nexus` to CLI | cli/src/config.ts, run.ts | 1b |
| ~~**2**~~ | ~~Add `remote_infer` action to nexus tool~~ DONE | nexus.ts | 1a |
| **3a** | Create HybridAgenticBackend | orchestrator/src/hybridBackend.ts | 1b |
| **3b** | RoutingPolicy with load/cost/capability logic | orchestrator/src/routingPolicy.ts | 3a |
| **4** | Sub-agent with backend selection | execution/src/tools/ (new or modified) | 1b |
| **5** | Provider dashboard + reputation | nexus.ts (new actions) | 2 |

### Immediate Next Steps (This Sprint)

1. ~~**Fix C3**~~ DONE — `targetAddress` now passed to `checkBudget()` in doSpend
2. ~~**Fix C4**~~ DONE — atomic file creation with `fsOpen(path, "w", 0o600)` for all key/wallet files
3. ~~**Step 2**~~ DONE — `remote_infer` action with auto-discovery + explicit peer + budget + ledger + error handling (23/23 eval tests pass)
4. **Step 1b** — NexusAgenticBackend (unlocks Scenarios 1 & 3)
5. **Step 1c** — CLI flag for nexus backend

### What's Already Built vs What's Needed

```
BUILT (just needs wiring):
  ├── InferenceRouter (trust-scored peer selection)
  ├── SecretVault (automatic credential protection)
  ├── PeerMesh (WebSocket gossip mesh)
  ├── x402 payment rails (wallet + spend + ledger + budget)
  ├── AgenticBackend interface (clean abstraction)
  └── P2P types (InferRequest/Response with tool-calling)

DONE:
  ├── remote_infer nexus action (auto-discover + invoke + budget + ledger) ✓

NEEDS BUILDING:
  ├── NexusAgenticBackend (adapter: InferenceRouter → AgenticBackend)
  ├── HybridAgenticBackend (local + remote routing)
  ├── RoutingPolicy (cost/capability/load decision engine)
  └── CLI integration (--backend nexus, /p2p infer command)
```

The remarkable thing is that **70% of the infrastructure is already built**. The remaining work is primarily wiring and integration — connecting InferenceRouter to AgenticRunner, and adding the CLI/tool surface for agents to use it.
