Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .Jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-23 - Denial of Service: Unbounded Queues
**Vulnerability:** The `AsyncLogger` class used an unbounded `std::queue` to buffer log messages. If the producer (main thread) generated logs faster than the consumer (worker thread) could write to stdout, the queue would grow indefinitely, leading to memory exhaustion and application crash (DoS).
**Learning:** Asynchronous operations must always have resource limits. "Infinite" buffering is a security anti-pattern.
**Prevention:** Implement bounded queues (e.g., ring buffers or size checks) for all producer-consumer patterns. Drop data or block the producer when limits are reached, depending on the criticality of the data.
16 changes: 15 additions & 1 deletion src/AsyncLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class AsyncLogger {
public:
AsyncLogger() : exitFlag(false) {
AsyncLogger() : exitFlag(false), queueFullWarning(false) {
worker = std::thread([this] {
processQueue();
});
Expand All @@ -32,6 +32,13 @@ class AsyncLogger {
void log(const std::string& message) {
{
std::lock_guard<std::mutex> lock(queueMutex);
if (msgQueue.size() >= MAX_QUEUE_SIZE) {
if (!queueFullWarning) {
std::cerr << "[Security] AsyncLogger queue full (" << MAX_QUEUE_SIZE << "), dropping messages!\n";
queueFullWarning = true;
}
return;
}
msgQueue.push(message);
}
cv.notify_one();
Expand All @@ -43,6 +50,8 @@ class AsyncLogger {
std::mutex queueMutex;
std::condition_variable cv;
bool exitFlag;
bool queueFullWarning;
static constexpr size_t MAX_QUEUE_SIZE = 10000;

void processQueue() {
while (true) {
Expand All @@ -63,6 +72,11 @@ class AsyncLogger {
std::cout << msg << std::flush;
lock.lock();
}

// Queue is empty here. Reset warning flag if it was set.
if (queueFullWarning) {
queueFullWarning = false;
}
}
}
};
3 changes: 1 addition & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,7 @@ class RacingEngine {
AsyncLogger logger;

// UX State Tracking
float currentFPS = 0.0f;
float frameTimeMs = 0.0f;
// Note: currentFPS and frameTimeMs are already defined above

void updateWindowTitle() {
glm::vec3 pos = camera.getPosition();
Expand Down