From 114721c24abc9e1be7d1e0050ccf1d10b797bc33 Mon Sep 17 00:00:00 2001 From: DavidHerran Date: Sun, 5 Jul 2026 20:05:12 -0500 Subject: [PATCH] fix(ink/credential): cota anti-griefing del Vec del holder (audit C, HIGH DoS) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit ultra 2026-07-04 (dimensión ink-contracts, decisión C de David): un issuer malicioso podía emitir credenciales ilimitadas a una VÍCTIMA, bloateando su holder_credentials: Vec hasta que cualquier op que lo cargara (issue/read) excedía el gas → griefing DoS. Fix: MAX_CREDENTIALS_PER_HOLDER=512 + error HolderCredentialLimitReached antes del push. (Nota: el índice issuer_credentials de un emisor de alto volumen debe migrar a Mapping<(issuer,i),id> paginado — trabajo futuro; no es griefing de terceros.) Contrato 4 tests verde. Co-Authored-By: Claude Fable 5 --- contracts/origin-credential-mint/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/contracts/origin-credential-mint/lib.rs b/contracts/origin-credential-mint/lib.rs index ede489d..5e42ad9 100644 --- a/contracts/origin-credential-mint/lib.rs +++ b/contracts/origin-credential-mint/lib.rs @@ -147,8 +147,21 @@ mod origin_credential_mint { AlreadyExpired, InvalidConfiguration, TransferFailed, + /// Audit 2026-07-04: el holder alcanzó el máximo de credenciales + /// (`MAX_CREDENTIALS_PER_HOLDER`) — cota anti-griefing/DoS. Sin esto, un + /// issuer malicioso bloateaba el `Vec` del holder hasta que cualquier + /// operación que lo cargue (issue/read) excedía el gas. + HolderCredentialLimitReached, } + /// Máximo de credenciales por holder (cota anti-griefing del `Vec` en storage). + /// Una persona/entidad tiene un número acotado de credenciales legítimas; el + /// límite evita que un issuer malicioso infle el `Vec` de una víctima hasta + /// hacerlo ilegible por gas. (El índice `issuer_credentials` de un emisor de + /// alto volumen debe migrar a un índice paginado `Mapping<(issuer,i),id>` — + /// trabajo futuro; no es un vector de griefing de terceros.) + pub const MAX_CREDENTIALS_PER_HOLDER: u32 = 512; + pub type Result = core::result::Result; /// Convierte un valor `U256` del entorno pallet-revive a `Balance` (u128) @@ -289,6 +302,11 @@ mod origin_credential_mint { // Update indices canonical let mut holder_list = self.holder_credentials.get(holder).unwrap_or_default(); + // Audit 2026-07-04: cota anti-griefing — sin esto un issuer malicioso + // bloatea el Vec del holder hasta hacerlo ilegible por gas. + if holder_list.len() as u32 >= MAX_CREDENTIALS_PER_HOLDER { + return Err(Error::HolderCredentialLimitReached); + } holder_list.push(id); self.holder_credentials.insert(holder, &holder_list);