RUSTFORGE — INFORME DE AUDITORIA

Ecosistema Rust de 10 Repos — Hallazgos Completos
Alcance: 10 repos Rust, 365 archivos fuente Foco: Seguridad unwrap/panic, auditoria unsafe, integridad hash-chain Herramienta: Scanner estatico propio (15 tests, 4 bugs encontrados en herramienta propia) Fecha: Febrero 2026
Version resumida. Informe completo en ingles →
Muestra Metodologica — Este informe documenta una auditoria interna de nuestro propio ecosistema Rust, publicado para demostrar nuestra metodologia y rigor analitico. Las auditorias de clientes se realizan bajo NDA.
10
Repos Auditados
365
Archivos Fuente
1,025+
Tests Verificados
140
Unwraps Prod Clasificados
8
Fixes Entregados

Resumen Ejecutivo

Auditamos 10 repositorios Rust que abarcan inferencia AI, agent runtimes, autenticacion, busqueda, servicios de gobierno, aprendizaje etico y emulacion — 365 archivos fuente con 1,025+ tests. Cada .unwrap() y .expect() en produccion fue clasificado manualmente: 140 en total, todos invariantes algoritmicos o patron CLI-startup. Se encontraron y corrigieron 8 problemas accionables: 5 riesgos de panic por NaN via partial_cmp().unwrap(), 1 crash en verificacion de hash-chain, 1 propagacion de error no controlada, y 1 unwrap ambiguo mejorado a expect explicito. Se construyo un scanner de analisis estatico propio que fue mejorado durante la auditoria, encontrando 4 bugs en nuestra propia herramienta. Resultado final: 0 riesgos P0, 0 unwraps accionables restantes.

Hallazgos de Riesgo

Cada hallazgo fue detectado, clasificado, corregido y verificado con tests durante la auditoria.

RF-2026-001 Alto
Panic por NaN en Ordenamiento f32 — 5 Sitios, 2 Repos
Que
partial_cmp().unwrap() en valores f32 genera panic cuando un operando es NaN. Encontrado en sampling de tokens LLM (argmax, top-k sort, top-p sort) y scoring de confianza en deteccion de anomalias.
Donde
llm-sampler/src/lib.rs — lineas 192, 204, 225
llm-models/src/llama.rs — linea 880
b3-core/detectors.rs — linea 330
Impacto
Valores NaN son comunes en inferencia de redes neuronales. Un solo NaN crashearia todo el pipeline de inferencia LLM.
Evidencia
// Antes (panic con NaN):
.max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())

// Despues (NaN-safe, orden total):
.max_by(|(_, a), (_, b)| a.total_cmp(b))
CORREGIDO 5 sitios: partial_cmp().unwrap()total_cmp(). 88 + 88 tests pasan.
RF-2026-002 Alto
Crash en Verificacion de Hash-Chain por Input Malformado
Que
La funcion verify() de un log append-only de hash-chain usaba serde_json::from_str(&line).unwrap(). Una linea malformada (corrupcion de disco, escritura parcial) causaria panic en lugar de retornar fallo de verificacion.
Donde
logstore/src/lib.rs — linea 158, funcion verify()
Impacto
El logstore provee evidencia de integridad para un agent runtime. Un crash durante verificacion significa que un log corrupto no puede ser detectado.
Evidencia
// Antes (panic con JSON malformado):
let v: serde_json::Value = serde_json::from_str(&line).unwrap();

// Despues (retorna chain-invalid sin crash):
let v: serde_json::Value = match serde_json::from_str(&line) {
    Ok(v) => v,
    Err(_) => return Ok(false),
};
CORREGIDO Match explicito retorna Ok(false) en fallo de parseo. 41 tests pasan.
RF-2026-003 Medio
Propagacion de Error No Controlada en Agent Runtime
Que
submit(request).unwrap() en una ruta de ejecucion tragaba el tipo de error. Si el canal de intervencion estaba cerrado, el runtime crasheaba en lugar de propagar el error.
Donde
runtime.rs — linea 243
Evidencia
// Antes:
submit(request).unwrap();

// Despues:
submit(request)?;
// + Intervention(#[from] InterventionError) en RuntimeError
CORREGIDO .unwrap()? con nueva variante InterventionError. 179 tests pasan.
RF-2026-004 Medio
10 Casts Unsafe de Punteros Sin Validacion de Limites
Que
Operaciones de cuantizacion LLM y tensores usaban casts de punteros crudos sin validacion de alineamiento ni limites. Acceso desalineado es comportamiento indefinido.
Donde
llm-quant/src/*.rs (5), llm-core/src/tensor.rs (3), carga GGUF (2)
Evidencia
// Antes (cast crudo, sin validacion):
let ptr = bytes.as_ptr() as *const f16;
let slice = unsafe { std::slice::from_raw_parts(ptr, count) };

// Despues (seguro, validado por bytemuck):
let slice: &[f16] = bytemuck::try_cast_slice(bytes)
    .map_err(|e| TensorError::AlignmentError(e))?;
CORREGIDO 10 casts → bytemuck. 9 unsafe restantes son Metal FFI, Send/Sync, mmap — documentados con comentarios SAFETY. 7 tests de limites agregados.

Metodologia del Scanner

Construimos un scanner de analisis estatico propio durante la auditoria. Encontro 4 bugs en si mismo.

SCANNER Herramienta
4 Bugs del Scanner Encontrados y Corregidos
BUG-1: Indirection de Tests
#[cfg(test)] mod tests;src/tests.rs no era seguido. +27 falsos positivos. Fix: collect_test_module_paths().
BUG-2: Match de Unsafe en Strings
\bunsafe\b matcheaba dentro de string literals y comentarios. Fix: count_real_unsafe() con stripping previo.
BUG-3: Colision de Nombres de Metodo
Parser::expect(TokenKind, msg)? matcheaba el regex .expect(. +16 falsos positivos. Fix: requerir argumento string literal.
BUG-4: Falsos Positivos en Doc Comments
/// y //! con .unwrap() contaban como codigo prod. +18 falsos positivos. Fix: strip_doc_comments().
15 TESTS Scanner v3 con suite de regresion completa.

Observaciones del Analisis

  1. El ecosistema tiene fundamentos de seguridad solidos. Cero panic!, todo! o unimplemented! en codigo de produccion en los 10 repos.
  2. partial_cmp en floats es un punto ciego sistemico. Encontrado en 3 de 10 repos independientemente. total_cmp deberia ser el default para todo ordenamiento f32 en Rust.
  3. Codigo de libreria necesita disciplina de unwrap diferente al de CLI. 34 de 40 unwraps en agent-runtime son .expect("msg") en fn main — patron CLI correcto. Pero 1 unwrap en verify() de libreria era un riesgo real.
  4. El tooling de analisis estatico debe auditarse a si mismo. 4 bugs en nuestro propio scanner durante 10 repos.

Metodologia: Clasificacion de Unwraps

Escaneados: 365 archivos Clasificados: 140 unwraps prod Resultado: 0 accionables restantes

Scoreboard por Proyecto

Cada repo evaluado por: conteo de unwraps prod, cobertura de tests, uso de unsafe, calidad de documentacion de invariantes.

apex-learning

10
0 unwraps prod. 0 unsafe. 106 tests. Arquitectura DDD con 7 crates.

gameboy

9.5
0 unwraps prod. 5 unreachable! (bitmask, documentados). 28 tests.

rcr

9.0
4 unwraps prod (invariantes). 330 tests. Mejor densidad de tests del ecosistema.

nccr

9.0
4 unwraps prod (UTF-8 desde ASCII). 5 unreachable! documentados. 68 tests.

estado-transparente

8.5
4 unwraps prod (chrono hardcoded, siempre valido). 45 tests. Portal de gobierno.

llm-runtime

8.0
10 unwraps post-fix. 9 unsafe (Metal FFI, documentados). 88 tests.
4 CORREGIDOS

agent-core

8.0
14 unwraps post-fix (JSON read-back, serde, RFC3339). 41 tests.
1 CORREGIDO

auth-rust

7.5
16 unwraps prod (7 chrono + 9 startup expect). 29 tests.

agent-runtime

7.5
40 unwraps post-fix (34 CLI expect). 179 tests.
2 CORREGIDOS

b3-core

7.0
48 unwraps prod (30 RwLock + 18 Regex Lazy). 88 tests.
1 CORREGIDO

Patrones Cross-Proyecto

Patrones recurrentes en el ecosistema de 10 repos.

PatronReposCantidadEstado
partial_cmp().unwrap() en f323 / 105CORREGIDO
CLI .expect("msg") en fn main3 / 1044SEGURO
RwLock poison .unwrap()1 / 1030INVARIANTE
Regex::new(literal).unwrap() en Lazy2 / 1021INVARIANTE
unreachable!() con guarda invariante3 / 1011DOCUMENTADO
unsafe con comentario SAFETY1 / 109DOCUMENTADO
panic! / todo! en produccion0 / 100PASS

Quieres la misma profundidad
en tu codebase Rust?

Cada unwrap clasificado. Cada unsafe documentado. Cada fix verificado con tests.
Pago anticipado via Stripe. Sin hallazgos accionables? Reembolso completo.

Iniciar Auditoria — desde $1,800 audit@newcool.io

Pago anticipado. Sin hallazgos accionables, reembolso completo.