⚠️ Prototype / Experimental This project is purely a prototype to experiment with the concepts of GVM + Rust and agentic engineering. It is not production-ready, not endorsed by Greenbone, and not intended as a replacement for python-gvm. APIs, architecture, and scope may change without notice.
Rust client library for the Greenbone Management Protocol (GMP) — a reimplementation of python-gvm with type safety, async-first design, and a programmable mock server for testing.
Release and nightly builds publish CycloneDX 1.5 SBOMs generated by cargo-cyclonedx; the JSON artifacts are post-processed in CI to add CC0 document licensing, build lifecycle metadata, and supplier hints before sbomqs scoring and packaging. CPEs are intentionally left untouched unless a reliable package mapping is available.
Note
Releases are managed via the release-orchestrator. To create a nightly/alpha build, create an alpha release in the orchestrator. See RELEASING.md for details.
rust-gvm provides everything needed to talk to Greenbone Vulnerability Manager (gvmd) — from low-level XML framing to high-level typed commands — plus a standalone mock server that speaks the GMP protocol over Unix sockets or TCP, enabling integration testing without a real Greenbone instance.
| Crate | Purpose | Status |
|---|---|---|
gvm-protocol |
Sans-I/O XML framing, command builder, response parser | ✅ Implemented |
gvm-mock-server |
Programmable mock GMP server (4 modes, fault injection) | ✅ Implemented |
gvm-connection |
Transport layer (Unix socket, SSH) | ✅ Unix + SSH done |
gvm-gmp |
Typed GMP command builders per version (22.4–22.8+) | ✅ Implemented |
gvm-client |
High-level async client with version negotiation | ✅ Implemented |
┌─────────────────────────────────┐
│ gvm-client │ High-level API, version negotiation
├─────────────────────────────────┤
│ gvm-gmp │ Typed commands per GMP version
├─────────────────────────────────┤
│ gvm-protocol │ Sans-I/O XML framing + response parsing
├─────────────────────────────────┤
│ gvm-connection │ Unix socket / TLS / SSH transports
└─────────────────────────────────┘
gvm-mock-server ← Standalone mock for testing any GMP client
The high-level client handles version negotiation automatically and exposes typed convenience methods for every GMP domain:
use gvm_client::{GmpClient, GvmError};
use gvm_connection::{UnixSocketConfig, UnixSocketConnection};
use gvm_gmp::commands::targets::CreateTargetOpts;
use gvm_gmp::commands::tasks::CreateTaskOpts;
#[tokio::main]
async fn main() -> Result<(), GvmError> {
// 1. Create a transport and connect — auto-negotiates GMP version (22.4–22.7+)
let conn = UnixSocketConnection::new(UnixSocketConfig::new("/run/gvmd/gvmd.sock"));
let mut client = GmpClient::connect(conn).await?;
println!("Connected, GMP version: {}", client.version());
// 2. Authenticate
client.authenticate("admin", "admin").await?;
// 3. Create a target — typed response, no manual XML parsing
let target = client.create_target("My Target", CreateTargetOpts {
hosts: vec!["192.168.1.0/24".to_string()],
..Default::default()
}).await?;
println!("Created target: {}", target.id);
// 4. List all targets
let targets = client.get_targets(Default::default()).await?;
for t in &targets.items {
println!(" {} — {}", t.meta.id, t.meta.name);
}
// 5. Create and start a scan task
let config_id = "daba56c8-73ec-11df-a475-002264764cea".parse().unwrap();
let scanner_id = "08b69003-5fc2-4037-a479-93b440211c73".parse().unwrap();
let task = client.create_task(
"My Scan", &config_id, &target.id, &scanner_id,
CreateTaskOpts::default(),
).await?;
client.start_task(&task.id).await?;
println!("Started task: {}", task.id);
client.disconnect().await?;
Ok(())
}For full control you can use the underlying send() / call() methods directly with command builders from gvm-gmp:
use gvm_gmp::commands::{authentication, targets};
// call() raises GvmError::Server on non-2xx; send() returns the raw Response
client.call(authentication::authenticate("admin", "admin")).await?;
let response = client.call(targets::get_targets(Default::default())).await?;
println!("Raw XML: {} bytes", response.data().len());Use GmpVersioned when you need to branch on the server's GMP version:
use gvm_client::GmpVersioned;
use gvm_connection::{UnixSocketConfig, UnixSocketConnection};
let conn = UnixSocketConnection::new(UnixSocketConfig::new("/run/gvmd/gvmd.sock"));
let mut client = GmpVersioned::connect(conn).await?;
match &client {
GmpVersioned::V225(_) => println!("GMP 22.5"),
GmpVersioned::V226(_) => println!("GMP 22.6"),
_ => println!("Other version: {}", client.version()),
}
// All versions share the same send/call API
client.call(authentication::authenticate("admin", "admin")).await?;Connect to a remote gvmd over SSH tunnel:
use gvm_client::GmpClient;
use gvm_connection::{SshConfig, SshAuth, SshConnection};
let config = SshConfig::new("scanner.example.com", "gvm", SshAuth::Agent)
.with_port(22)
.with_remote_socket("/run/gvmd/gvmd.sock");
let conn = SshConnection::new(config);
let mut client = GmpClient::connect(conn).await?;
// Same API as Unix socket — connect/call/disconnectuse gvm_mock_server::{MockGmpServer, ServerMode, GmpVersion};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let server = MockGmpServer::builder()
.mode(ServerMode::Stateful)
.version(GmpVersion::V22_5)
.credentials("admin", "admin")
.unix_socket_auto()
.build()
.await?;
println!("Mock GMP server listening at: {:?}", server.socket_path());
// Connect with any GMP client (rust-gvm, python-gvm, etc.)
server.shutdown().await;
Ok(())
}# Start a stateful mock server on a Unix socket
gvm-mock-server --mode stateful --version 22.5 --socket /tmp/gvmd.sock
# Or on TCP
gvm-mock-server --mode stateful --version 22.5 --tcp 127.0.0.1:9390Then connect with python-gvm:
from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import GMP
from gvm.transforms import EtreeCheckCommandTransform
conn = UnixSocketConnection(path="/tmp/gvmd.sock")
with GMP(connection=conn, transform=EtreeCheckCommandTransform()) as gmp:
gmp.authenticate("admin", "admin")
targets = gmp.get_targets()
print(targets)The mock server is the most developed component. It's designed to be a drop-in test server for any GMP client library — Rust, Python, Go, or shell scripts.
| Mode | Description |
|---|---|
| Echo | Returns well-formed <command_response status="200"/> for any recognized command |
| Fixture | Returns pre-built realistic GMP XML from a fixture library (90+ commands) |
| Stateful | Full in-memory CRUD with authentication, task lifecycle, and resource relationships |
| Scenario | Plays back scripted command→response sequences (strict or lenient matching) |
- 4 server modes — from simple echo to full stateful CRUD
- Unix socket + TCP listeners — compatible with python-gvm's
UnixSocketConnectionandTLSConnection - Per-session authentication — supports python-gvm's two-connection flow (version probe + auth session)
- Task lifecycle — New → Running → Stopped → Done state machine
- Fault injection — disconnect, delay, malformed XML, error codes, truncated responses
- Scenario playback — deterministic scripted sequences for regression tests
- Command history — inspect what the server received after tests
- Pre-seeding — populate the store before tests via builder API
- Template substitution —
{{uuid}},{{now}},{{version}}in fixture responses - Resource filtering — basic GMP filter string support (
name=foo status=Running)
The mock server is validated against python-gvm in CI, exercising the full protocol flow: version negotiation, authentication, target/task CRUD, notes lifecycle, and cleanup.
gvm-connection provides async transport implementations behind the GvmConnection trait:
use gvm_connection::{GvmConnection, UnixSocketConfig, UnixSocketConnection};
let config = UnixSocketConfig::new("/run/gvmd/gvmd.sock");
let mut conn = UnixSocketConnection::new(config);
conn.connect().await?;
conn.send(b"<get_version/>").await?;
let response_bytes = conn.read().await?; // Uses XmlReader for frame detection
conn.disconnect().await?;| Transport | Status | Feature Flag |
|---|---|---|
| Unix socket | ✅ Implemented | unix (default) |
| SSH tunnel | ✅ Implemented | ssh |
| TLS over TCP | 📋 Planned | tls |
Both transports support the full python-gvm reconnect pattern (connect → get_version → disconnect → reconnect → authenticate → commands) and implement the GvmConnection trait, so they're interchangeable with GmpClient.
gvm-protocol provides the transport-agnostic building blocks:
XmlCommand— Builder for GMP XML commands with attributes, child elements, and text contentResponse— Parser for GMP XML responses (status codes, child text extraction, id extraction)XmlReader— Streaming XML completeness detector for framing GMP messages over byte streams
See docs/STATUS.md for detailed implementation status of each crate and GMP command coverage.
# Build everything
cargo build --workspace
# Run all tests (630+ tests)
cargo test --workspace
# Run python-gvm integration tests
make test-integration
# Build the mock server binary
cargo build --release -p gvm-mock-server- Rust 1.75+ (MSRV)
- Python 3.10+ with
python-gvm(for integration tests only)
| Workflow | Trigger | What it does |
|---|---|---|
| CI | Push/PR to main | Format, clippy, test, doc, deny, coverage, MSRV, python-gvm integration |
| Nightly | Daily 04:00 UTC + manual | Full CI + cross-platform binary builds (5 targets) |
| Release | v* tag push |
Full test → cross-platform builds → GHCR mock-server image → GitHub Release with checksums |
Download from GitHub Releases or the rolling nightly pre-release.
| Platform | Binary |
|---|---|
| Linux x86_64 (glibc) | gvm-mock-server-linux-amd64.tar.gz |
| Linux x86_64 (musl, static) | gvm-mock-server-linux-amd64-musl.tar.gz |
| Linux ARM64 | gvm-mock-server-linux-arm64.tar.gz |
| macOS x86_64 | gvm-mock-server-macos-amd64.tar.gz |
| macOS ARM64 | gvm-mock-server-macos-arm64.tar.gz |
Tagged releases also publish a container image at ghcr.io/clawosiris/gvm-mock-server:<tag>.
See docs/mock-server-consumption.md for downstream CI usage guidance.
Design specifications live in spec/:
openspec.md— Full library architecture and crate specsmock-server-openspec.md— Mock server design and APImock-server-tests-openspec.md— Test planlibrary-tests-openspec.md— Library test planmcp-server-integration-spec.md— MCP server integration testing
AGPL-3.0-or-later — matching the Greenbone ecosystem.
Copyright 2026 Greenbone AG
- python-gvm — Official Python GMP library
- gvmd — Greenbone Vulnerability Manager daemon
- openvas-mcp-server — MCP Server for OpenVAS/Greenbone