Private
Public Access
1
0

fix: CIDR suffix in agent URLs, agent client CIDR strip, and IP SAN fixes
Some checks failed
CI Pipeline / Rust Format Check (push) Failing after 5s
CI Pipeline / Clippy Lints (push) Successful in 45s
CI Pipeline / Rust Unit Tests (push) Successful in 1m1s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 12s
CI Pipeline / Build .deb & Release (push) Has been skipped

BUG-10: PostgreSQL inet type includes CIDR suffix (/32) when cast to text,
causing malformed agent URLs like https://127.0.0.1/32:12443.
Fixed by using host(ip_address)::text in all SQL queries across
pm-worker and pm-web modules, and adding a Rust-side safety
strip of CIDR notation in pm-agent-client.

Files changed:
- crates/pm-agent-client/src/client.rs: strip CIDR suffix from IP
- crates/pm-worker/src/health_poller.rs: host(ip_address)::text
- crates/pm-worker/src/patch_poller.rs: host(ip_address)::text
- crates/pm-worker/src/refresh_listener.rs: host(ip_address)::text
- crates/pm-worker/src/job_executor.rs: host(ip_address)::text (2 places)
- crates/pm-worker/src/ws_relay.rs: host(h.ip_address)::text
- crates/pm-web/src/routes/discovery.rs: host(ip_address)::text (2 places)
- crates/pm-web/src/routes/hosts.rs: host(ip_address)::text (3 places)
- docs/linux_patch_api_research.md: added research notes
This commit is contained in:
2026-04-29 00:58:43 +00:00
parent 9a8e9bfa38
commit b552a13619
9 changed files with 533 additions and 13 deletions

View File

@ -194,7 +194,7 @@ async fn get_scan_results(
Path(scan_id): Path<Uuid>,
) -> Result<Json<Vec<DiscoveryResult>>, (StatusCode, Json<Value>)> {
sqlx::query_as::<_, DiscoveryResult>(
r#"SELECT id, scan_id, ip_address::text AS ip_address, fqdn,
r#"SELECT id, scan_id, host(ip_address)::text AS ip_address, fqdn,
agent_version, os_name, agent_port, discovered_at, registered
FROM discovery_results
WHERE scan_id = $1
@ -230,7 +230,7 @@ async fn register_discovered_host(
// Fetch discovery result
let result: Option<DiscoveryResult> = sqlx::query_as(
r#"SELECT id, scan_id, ip_address::text AS ip_address, fqdn,
r#"SELECT id, scan_id, host(ip_address)::text AS ip_address, fqdn,
agent_version, os_name, agent_port, discovered_at, registered
FROM discovery_results WHERE id = $1"#,
)

View File

@ -109,7 +109,7 @@ async fn list_hosts(
let hosts: Vec<HostSummary> = if auth.role.is_admin() {
sqlx::query_as(
r#"
SELECT id, fqdn, ip_address::text AS ip_address, display_name,
SELECT id, fqdn, host(ip_address)::text AS ip_address, display_name,
os_family, os_name, health_status, agent_version, registered_at
FROM hosts
ORDER BY fqdn
@ -123,7 +123,7 @@ async fn list_hosts(
} else {
sqlx::query_as(
r#"
SELECT DISTINCT h.id, h.fqdn, h.ip_address::text AS ip_address,
SELECT DISTINCT h.id, h.fqdn, host(h.ip_address)::text AS ip_address,
h.display_name, h.os_family, h.os_name,
h.health_status, h.agent_version, h.registered_at
FROM hosts h
@ -275,7 +275,7 @@ async fn get_host(
let host: Option<Value> = sqlx::query_scalar(
r#"
SELECT row_to_json(h) FROM (
SELECT id, fqdn, ip_address::text AS ip_address, display_name,
SELECT id, fqdn, host(ip_address)::text AS ip_address, display_name,
os_family, os_name, arch, agent_version, health_status,
last_health_at, last_patch_at, agent_port, notes,
registered_at, updated_at