Skip to content

M1 base: workspace cleanup + CLI + allowlist hardening#27

Closed
jean-neiverth wants to merge 5 commits into
nullislabs:mainfrom
bleu:dev/m1-base
Closed

M1 base: workspace cleanup + CLI + allowlist hardening#27
jean-neiverth wants to merge 5 commits into
nullislabs:mainfrom
bleu:dev/m1-base

Conversation

@jean-neiverth

Copy link
Copy Markdown
Collaborator

Summary

  • Hoist [workspace.dependencies] + [workspace.lints] to root Cargo.toml to prevent version drift across crates
  • Migrate CLI from hand-rolled parser to clap
  • Mark RPC namespace allowlist enforcement as future direction in docs
  • Harden extract_host against fragment/query URL bypass (COW-1096)

Context

This branch is the base for the M2 epic (PR #22). Opening as draft so it can serve as an explicit review target for M1-scope work that isn't covered by PRs #8, #9, #12, or #15.

🤖 Generated with Claude Code

brunota20 and others added 5 commits June 25, 2026 20:10
Adds a `[workspace.dependencies]` table to the root manifest
consolidating every dep used by 2+ crates across the full nullis-
shepherd stack (anyhow, thiserror, tokio, futures, serde, serde_json,
tracing, tracing-subscriber, strum, alloy-*, cowprotocol, reqwest,
wit-bindgen, clap). Per-crate manifests inherit with `dep.workspace
= true`, and may add features per call site via `dep = { workspace
= true, features = ["extra"] }`. Single-consumer deps (wasmtime,
toml, redb, getrandom, url, hex, axum, rand, ...) stay per-crate.

Adds `[workspace.lints]` with light-touch defaults: `dbg_macro` and
`todo` denied via clippy, `unsafe_op_in_unsafe_fn` warned via rust.
`unsafe_code = deny` cannot be applied workspace-wide because every
wit-bindgen guest module emits an `unsafe extern "C"` shim.

Also pre-declares `auto_impl` and `derive_more` in the workspace deps
table so future `Arc<dyn Trait>` boundaries and newtype-heavy crates
can opt in without touching the root manifest.

The version-drift failure mode (cowprotocol pinned to `1.0.0-alpha`
in nexum-engine but `1.0.0-alpha.3` in shepherd-sdk, flagged in the
2026-06-25 audit) is now impossible by construction: every consumer
inherits the single workspace pin.

Audit reference: milestone-rubric-grant-audit-2026-06-25.md, judgment
calls 1 + 3.
Replaces the `std::env::args().skip(1)` walker with a `#[derive(clap::
Parser)]` struct so the engine binary picks up `--help`, `--version`,
proper argument validation, and structured error reporting for free.

The positional surface is preserved one-for-one (`<wasm-path>
[manifest-path]`); behaviour for callers that already pass two paths
is identical. Help output now documents each argument inline rather
than hiding the usage in an anyhow message that only fires on misuse.

`clap.workspace = true` consumes the workspace dep added in the
prior commit; no new direct version pin in this crate.

Audit reference: milestone-rubric-grant-audit-2026-06-25.md, judgment
call 2.
…irection

A casual reader of `07-rpc-namespace-design.md` hitting the file
top or the "Method Allowlisting" subsection could plausibly walk
away believing the 0.2 runtime gates RPC methods on a read-only
allowlist and intercepts signing methods to delegate them to the
identity backend. The shipped host implementation does neither:
`chain::request` forwards any method string through to the
configured alloy provider.

Adds an explicit `Status: Future direction (0.3+ target)` callout
both at the file top and right above the "Method Allowlisting"
subsection so the gap between design intent and shipped behaviour
is visible without having to scroll the design narrative end-to-end.

Audit reference: milestone-rubric-grant-audit-2026-06-25.md, judgment
call 4.
…(COW-1096)

extract_host used find('/').or_else(find('?')) to locate the host
boundary, so a fragment containing '/' (e.g. evil.com#/good.com) or
a query string with an embedded URL could trick the parser into
extracting the wrong host. Fix by taking the minimum position of
'/', '?', and '#' per RFC 3986.

Add 13 new tests covering adversarial URL shapes (fragments, query
strings with slashes, port stripping, loopback/localhost, IPv6,
percent-encoding, empty hosts) and host_allowed bypass attempts
(suffix injection, case sensitivity, empty allowlist, wildcard
semantics).
fix(nexum-engine): harden extract_host against fragment/query bypass (COW-1096)
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.

2 participants