diff --git a/.Jules/sentinel.md b/.Jules/sentinel.md index 1c1ddfe..1d906ce 100644 --- a/.Jules/sentinel.md +++ b/.Jules/sentinel.md @@ -2,3 +2,8 @@ **Vulnerability:** I discovered a discrepancy between my internal memory of the codebase and the actual source code. My memory stated that `VulkanRTPipeline::readFile` had security checks (file size limit, error checking), but the actual code had none of these protections, leaving it vulnerable to crashes (DoS) from malformed files or memory exhaustion. **Learning:** Never assume security controls exist based on documentation or memory. Always verify the implementation in the actual source code ("Source of Truth"). **Prevention:** Explicitly verify security controls by reading the code before assuming they are present. When documentation claims a security feature exists, treat it as a claim to be verified, not a fact. + +## 2024-05-24 - DoS by Logging +**Vulnerability:** The `AsyncLogger` class used an unbounded `std::queue`, creating a Denial of Service (DoS) risk via memory exhaustion if log messages were generated faster than they could be processed. +**Learning:** Even internal utility classes like loggers can be attack vectors if they lack resource limits. "Infinite" buffers are never truly infinite. +**Prevention:** Implement a `MAX_QUEUE_SIZE` or similar bound for producer-consumer queues. Drop messages or block (with timeout) when full. Added a thread-safe warning mechanism using `std::atomic` to alert when dropping occurs. diff --git a/src/AsyncLogger.h b/src/AsyncLogger.h index 5c2ccdc..110ca9d 100644 --- a/src/AsyncLogger.h +++ b/src/AsyncLogger.h @@ -32,6 +32,12 @@ class AsyncLogger { void log(const std::string& message) { { std::lock_guard lock(queueMutex); + if (msgQueue.size() >= MAX_QUEUE_SIZE) { + if (!queueFullWarning.exchange(true)) { + std::cerr << "[Security] AsyncLogger queue full! Dropping messages to prevent DoS." << std::endl; + } + return; + } msgQueue.push(message); } cv.notify_one(); @@ -44,6 +50,10 @@ class AsyncLogger { std::condition_variable cv; bool exitFlag; + // Security: Bound queue size to prevent memory exhaustion DoS + static const size_t MAX_QUEUE_SIZE = 10000; + std::atomic queueFullWarning{false}; + void processQueue() { while (true) { std::unique_lock lock(queueMutex); @@ -63,6 +73,7 @@ class AsyncLogger { std::cout << msg << std::flush; lock.lock(); } + queueFullWarning = false; } } }; diff --git a/src/main.cpp b/src/main.cpp index 3503741..37260d6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -188,8 +188,6 @@ class RacingEngine { AsyncLogger logger; // UX State Tracking - float currentFPS = 0.0f; - float frameTimeMs = 0.0f; void updateWindowTitle() { glm::vec3 pos = camera.getPosition();