fix(ink/credential): cota anti-griefing del Vec del holder (audit C, HIGH DoS)
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 <noreply@anthropic.com>
This commit is contained in:
1 parent
9f48723ca5
commit
114721c24a
1 file changed
+18
@@ -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<T> = core::result::Result<T, Error>;
|
||||
|
||||
/// 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);
|
||||
|
||||
|
||||
Reference in new issue
Block a user