# DDOSDefenderPE — Patch Notes
**Iudex Industries | Internal Build**
## Security Vulnerabilities Patched
### 🔴 [CRITICAL] Rate-limit bypass via LoginStart packet buffering
Minecraft's TCP stack buffers packets. When a handshake is cancelled by `HandshakeListener`, a `LoginStart` packet already in the buffer would still fire in `LoginStartListener` — completely bypassing the per-subnet and global rate limiters. This meant an attacker could send a burst of handshakes, have them all cancelled, but still flood `LoginStart` checks with no cooldown applied.
**Fix:** `LoginStartListener` now maintains its own fully independent rate limiter (identical values to `HandshakeListener`: per-subnet 1-second cooldown, global soft limit 25/s, hard limit 50/s). The rate-limit gate runs before any other logic. Re-injected packets (players passing verification) are exempt via the verified/pending connection check, which runs first.
---
### 🟠 [HIGH] TrustedIPs allowed single device to push unlimited accounts
The TrustedIPs system stored exact IPs (not subnets) and allowed those IPs to bypass the global login rate limit entirely. One device that had already been verified could send an unlimited number of accounts through the queue, defeating the global hard cap of 50 logins/second.
**Fix:** `TrustedIPs` class removed entirely. FastPass was reverted to subnet-based verification (`/24` for IPv4, `/48` for IPv6), and `HandshakeListener` was reverted to blocking all connections above the rate limit with no trusted bypass. Fast-path verification is now handled purely by AccountGuard + FastPass tier logic.
---
### 🟠 [HIGH] FastPass bypassed AccountGuard completely for CAUTION/SUSPICIOUS accounts
FastPass-verified players were allowed through unconditionally regardless of their AccountGuard tier, including SUSPICIOUS accounts. This meant a player who had been flagged as suspicious (score ≥ 60) could exploit their FastPass entry to skip Mojang API verification.
**Fix:** FastPass now only provides a fast-path for CLEAN and CAUTION tiers. SUSPICIOUS still forces Mojang API verification (if not FastPass subnet-matched). HIGH_RISK blocks FastPass players outright.
---
### 🟠 [HIGH] FastPass stored exact IP, allowing subnet change to bypass re-verification
FastPass stored the player's exact IP at the time of verification. Changing IP (DHCP renewal, VPN, mobile network) would cause a FastPass miss and fall through to full re-verification — but the old exact-IP entry remained, which could have been exploited if subnet assumptions were relaxed in future changes.
**Fix:** FastPass now stores the subnet (`/24` for IPv4, `/48` for IPv6) instead of the exact IP. A player on the same subnet passes instantly. A subnet change triggers re-verification.
---
### 🟡 [MEDIUM] AccountGuard penalised every rapid reconnect individually, causing false-positive death spirals
The reconnect scoring system added score on every individual fast reconnect (gap < 5s → +30, 5–30s → +15, 30s–3min → +5). A player falsely flagged and blocked would reconnect to check remaining time, each reconnect adding more score. When the block expired, their score was still above the HIGH_RISK threshold and they were immediately re-blocked — indefinitely.
**Fix:** Reconnect scoring is now pattern-based. A single rapid reconnect scores zero (impatience). Only sustained patterns of 2+ rapid gaps (< 20s) or 3+ moderate gaps (< 90s) accumulate score. Additionally, reconnect scoring is skipped entirely while the player is blocked — reconnecting to check remaining time produces zero score change.
---
### 🟡 [MEDIUM] No disconnect packet sent on connection cancellation
When a connection was cancelled with `event.setCancelled(true)`, no Minecraft Login Disconnect packet was sent to the client. Minecraft clients that receive no response auto-retry the connection immediately, creating a reconnect loop that amplifies attack traffic and causes bots to hammer the server faster.
**Fix:** All cancellation paths now call `DisconnectHelper.sendAndClose()`, which sends a `WrapperLoginServerDisconnect` packet before closing the connection. Clients receive a proper disconnect reason and do not auto-retry.
---
### 🟢 [LOW] `getConnectionId()` NPE on unresolved socket addresses
`LoginStartListener.getConnectionId()` called `address.getAddress().getHostAddress()` without null-checking `address.getAddress()`. Unresolved `InetSocketAddress` instances (possible with certain proxy/VPN forwarding configurations) would throw a `NullPointerException` on the executor thread, silently dropping the connection without cleanup.
**Fix:** Added `|| address.getAddress() == null` guard — returns null (treated as unknown connection) instead of throwing.
Developer information
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle.
maven { name = "Modrinth"; url = "https://api.modrinth.com/maven" }