From 94962f796af7e4897659b749035fa192372f6450 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 24 Aug 2026 10:45:10 +0100 Subject: [PATCH 1/2] chore(security): triage and resolve panic-attack findings (fixes #12) --- audits/assail-classifications.a2ml | 97 ++++++++---------------------- 1 file changed, 25 insertions(+), 72 deletions(-) diff --git a/audits/assail-classifications.a2ml b/audits/assail-classifications.a2ml index c07a6fbd..d1f4a77c 100644 --- a/audits/assail-classifications.a2ml +++ b/audits/assail-classifications.a2ml @@ -1,72 +1,25 @@ -;; SPDX-License-Identifier: MPL-2.0 -;; Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) - -(assail-classifications - (metadata - (version "1.0.0") - (project "proven-servers") - (last-updated "2026-05-26") - (entries 10) - (status "active")) - - (classification - (file "bindings/rust/src/ffi_smtp.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/ffi_ftp.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/ffi_grpc.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/ffi_mqtt.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/ffi_firewall.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/ffi_ssh.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/core.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/ffi_graphql.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/ffi_dns.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) - (classification - (file "bindings/rust/src/ffi_macros.rs") - (category "UnsafeCode") - (classification "legitimate-ffi") - (audit "audits/audit-ffi-2026-05-26.md") - (rationale "Rust FFI bindings to libproven-servers (SMTP/FTP/gRPC/etc.) — every unsafe block is an extern "C" call or buffer-ownership transition governed by the C ABI; underlying logic is in formally-verified Idris2.")) -) +%A2ML +- suppression: + file: 'bindings/ruby/lib/proven_servers/grpc.rb' + rule: 'DynamicCodeExecution' + justification: 'Ruby metaprogramming used for GRPC dynamic method dispatch; inputs are constrained to schema.' +- suppression: + file: 'protocols/proven-socks/src/SOCKS/Types.idr' + rule: 'HardcodedSecret' + justification: 'False positive: Idris2 type definitions matching heuristic keywords, no actual secrets.' +- suppression: + file: 'protocols/proven-kms/src/KMS/Types.idr' + rule: 'HardcodedSecret' + justification: 'False positive: Idris2 type definitions matching heuristic keywords, no actual secrets.' +- suppression: + file: 'protocols/proven-radius/src/RADIUS/Types.idr' + rule: 'HardcodedSecret' + justification: 'False positive: Idris2 type definitions matching heuristic keywords, no actual secrets.' +- suppression: + file: 'protocols/proven-authserver/src/Authserver/Types.idr' + rule: 'HardcodedSecret' + justification: 'False positive: Idris2 type definitions matching heuristic keywords, no actual secrets.' +- suppression: + file: 'not-proven/proven-ssh-bastion/src/SSH/Auth.idr' + rule: 'HardcodedSecret' + justification: 'False positive: Idris2 type definitions matching heuristic keywords, no actual secrets.' From 1077885b4ef726e0925fab06cd687935bc64c219 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:29:24 +0100 Subject: [PATCH 2/2] fix(ffi): prevent Zig 0.15 stack overflow in AMQP/Diode reset by using @memcpy --- protocols/proven-amqp/ffi/zig/src/amqp.zig | 14 +++++++------- protocols/proven-diode/ffi/zig/src/diode.zig | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/protocols/proven-amqp/ffi/zig/src/amqp.zig b/protocols/proven-amqp/ffi/zig/src/amqp.zig index 9f6714cc..a8a91068 100644 --- a/protocols/proven-amqp/ffi/zig/src/amqp.zig +++ b/protocols/proven-amqp/ffi/zig/src/amqp.zig @@ -439,7 +439,7 @@ pub export fn amqp_create( for (&sessions, 0..) |*s, i| { if (!s.active) { - s.* = empty_session; + @memcpy(std.mem.asBytes(s), std.mem.asBytes(&empty_session)); @memcpy(s.vhost[0..vhost_len], vhost_ptr[0..vhost_len]); s.vhost_len = vhost_len; s.frame_max = if (frame_max == 0) 131072 else frame_max; @@ -458,7 +458,7 @@ pub export fn amqp_destroy(slot: c_int) callconv(.c) void { mutex.lock(); defer mutex.unlock(); if (slot < 0 or slot >= MAX_SESSIONS) return; - sessions[@intCast(slot)] = empty_session; + @memcpy(std.mem.asBytes(&sessions[@intCast(slot)]), std.mem.asBytes(&empty_session)); } // -- State queries ------------------------------------------------------------ @@ -951,12 +951,12 @@ pub export fn amqp_cleanup(slot: c_int) callconv(.c) u8 { // Clear all session state sessions[idx].state = .idle; - sessions[idx].channels = [_]Channel{empty_channel} ** MAX_CHANNELS; + @memcpy(std.mem.asBytes(&sessions[idx].channels), std.mem.asBytes(&empty_session.channels)); sessions[idx].channel_count = 0; - sessions[idx].exchanges = [_]ExchangeEntry{empty_exchange} ** MAX_EXCHANGES; - sessions[idx].queues = [_]QueueEntry{empty_queue} ** MAX_QUEUES; - sessions[idx].bindings = [_]BindingEntry{empty_binding} ** MAX_BINDINGS; - sessions[idx].consumers = [_]ConsumerEntry{empty_consumer} ** MAX_CONSUMERS; + @memcpy(std.mem.asBytes(&sessions[idx].exchanges), std.mem.asBytes(&empty_session.exchanges)); + @memcpy(std.mem.asBytes(&sessions[idx].queues), std.mem.asBytes(&empty_session.queues)); + @memcpy(std.mem.asBytes(&sessions[idx].bindings), std.mem.asBytes(&empty_session.bindings)); + @memcpy(std.mem.asBytes(&sessions[idx].consumers), std.mem.asBytes(&empty_session.consumers)); sessions[idx].consumer_count = 0; return 0; diff --git a/protocols/proven-diode/ffi/zig/src/diode.zig b/protocols/proven-diode/ffi/zig/src/diode.zig index 5dd701f3..1f49657d 100644 --- a/protocols/proven-diode/ffi/zig/src/diode.zig +++ b/protocols/proven-diode/ffi/zig/src/diode.zig @@ -239,7 +239,7 @@ pub export fn diode_create(direction: u8, protocol: u8) callconv(.c) c_int { for (&gateways, 0..) |*gw, i| { if (!gw.active) { - gw.* = empty_gateway; + @memcpy(std.mem.asBytes(gw), std.mem.asBytes(&empty_gateway)); gw.direction = @enumFromInt(direction); gw.protocol = @enumFromInt(protocol); gw.state = .configured; @@ -255,7 +255,7 @@ pub export fn diode_destroy(slot: c_int) callconv(.c) void { mutex.lock(); defer mutex.unlock(); if (slot < 0 or slot >= MAX_GATEWAYS) return; - gateways[@intCast(slot)] = empty_gateway; + @memcpy(std.mem.asBytes(&gateways[@intCast(slot)]), std.mem.asBytes(&empty_gateway)); } // -- State queries ------------------------------------------------------------