From 0a2ac0c409cc1cfbf8877ee801f998a7c9492d95 Mon Sep 17 00:00:00 2001 From: Brian O'Reilly Date: Fri, 13 Mar 2026 17:21:22 -0400 Subject: [PATCH 1/2] docker port maps leak to external interface... Unless they are explicitly bound to loopback, which I thought was the default, but it is not. likely related to the interface between bridges and ip tables in the Linux kernel, but anyhow, get literal about the portmap interface address to prevent exposing the database to the entire internet. With thanks to the friendly heads up email from the German Federal Republic via Hetzner. --- docker/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index b4b80f5..6c62995 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -43,7 +43,7 @@ services: - POSTGRES_USER=${ASTEROID_DB_USER:-asteroid} - POSTGRES_PASSWORD=${ASTEROID_DB_PASSWORD:-asteroid_db_2025} ports: - - "5432:5432" + - "127.0.0.1:5432:5432" volumes: - postgres-data:/var/lib/postgresql/data - ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro From b3790bcb254bd1bce8a413edcbe84e3049679b76 Mon Sep 17 00:00:00 2001 From: Brian O'Reilly Date: Mon, 6 Apr 2026 10:19:06 -0400 Subject: [PATCH 2/2] fix: prevent debugger accumulation from vulnerability scanner probes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bogus requests (e.g. /wp-login.php, /.env) from external scanners were signalling FILE-TO-SERVE-DOES-NOT-EXIST and REQUEST-NOT-FOUND conditions that dropped into the debugger when Swank/Slynk was connected. Enough accumulated sessions would lock up the runtime. Three defence-in-depth changes: - Static file handler now probe-files before calling serve-file - start-server reads ASTEROID_DEBUG env var to set radiance:*debugger* - Override radiance:render-error-page for proper 404/403/500 responses 🅯 Brian O'Reilly , 2026 --- asteroid.lisp | 35 +++++++++++++++++++++++++++-------- conditions.lisp | 24 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/asteroid.lisp b/asteroid.lisp index cbddc52..f125733 100644 --- a/asteroid.lisp +++ b/asteroid.lisp @@ -977,8 +977,11 @@ ;; Serve regular static file (t - (serve-file (merge-pathnames (format nil "static/~a" path) - (asdf:system-source-directory :asteroid)))))) + (let ((file-path (merge-pathnames (format nil "static/~a" path) + (asdf:system-source-directory :asteroid)))) + (if (probe-file file-path) + (serve-file file-path) + (error 'radiance:request-not-found)))))) ;; Status check functions (defun check-icecast-status () @@ -1435,14 +1438,30 @@ ;; RADIANCE server management functions (defun start-server (&key (port *server-port*)) - "Start the Asteroid Radio RADIANCE server" + "Start the Asteroid Radio RADIANCE server. + Reads ASTEROID_DEBUG from the environment to control Radiance's debugger policy: + nil (or unset) - never invoke debugger (production default) + if-swank-connected - invoke only when Swank/Slynk is connected + t - always invoke debugger" (format t "Starting Asteroid Radio RADIANCE server on port ~a~%" port) (compile-styles) ; Generate CSS file using LASS - - ;; Ensure RADIANCE environment is properly set before startup - ;; (unless (radiance:environment) - ;; (setf (radiance:environment) "asteroid")) - + + ;; Set debugger policy from environment to prevent stray conditions from + ;; accumulating debugger sessions (e.g. vulnerability scanners hitting bogus paths) + (let ((debug-env (uiop:getenv "ASTEROID_DEBUG"))) + (setf radiance:*debugger* + (cond + ((or (null debug-env) + (string-equal debug-env "nil") + (string-equal debug-env "")) + nil) + ((string-equal debug-env "t") + t) + ((string-equal debug-env "if-swank-connected") + :if-swank-connected) + (t nil))) + (format t "Debugger policy: ~a~%" radiance:*debugger*)) + (radiance:startup) ;; Start listener statistics polling diff --git a/conditions.lisp b/conditions.lisp index 7c1f38e..71e6d71 100644 --- a/conditions.lisp +++ b/conditions.lisp @@ -202,3 +202,27 @@ (error 'authorization-error :message message :required-role required-role)) + +;;; Override Radiance's default render-error-page to return proper HTTP +;;; status codes instead of a blanket 500 for conditions like +;;; request-not-found and file-to-serve-does-not-exist. This prevents +;;; vulnerability scanners from generating misleading 500 responses and +;;; gives us control over error presentation. +(defun radiance:render-error-page (condition) + (cond + ((typep condition 'radiance:request-not-found) + (setf (radiance:return-code radiance:*response*) 404) + (setf (radiance:content-type radiance:*response*) "text/plain") + "Not Found") + ((typep condition 'radiance:file-to-serve-does-not-exist) + (setf (radiance:return-code radiance:*response*) 404) + (setf (radiance:content-type radiance:*response*) "text/plain") + "Not Found") + ((typep condition 'radiance:request-denied) + (setf (radiance:return-code radiance:*response*) 403) + (setf (radiance:content-type radiance:*response*) "text/plain") + "Forbidden") + (t + (setf (radiance:return-code radiance:*response*) 500) + (setf (radiance:content-type radiance:*response*) "text/plain") + "Internal Server Error")))