[PATCH] suricatta/wfx: job ID sanitation

12 views
Skip to first unread message

Konrad Schwarz

unread,
May 20, 2026, 1:00:21 PMMay 20
to swup...@googlegroups.com, christi...@siemens.com, Konrad Schwarz, Felix Moessbauer
wfx job IDs are used to create temporary files during the download and
installation process. To prevent path traversal or truncation, restrict
wfx job IDs to the POSIX portable filename character set.

Signed-off-by: Konrad Schwarz <konrad....@siemens.com>
Reported-by: Felix Moessbauer <felix.mo...@siemens.com>
---
suricatta/server_wfx.lua | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/suricatta/server_wfx.lua b/suricatta/server_wfx.lua
index 2b9a3a58..332349a0 100644
--- a/suricatta/server_wfx.lua
+++ b/suricatta/server_wfx.lua
@@ -405,6 +405,16 @@ function M.utils.validate_json_schema(data, schema, path)
return true
end

+--- Test string for POSIX Portable Filename Character Set compliance.
+--
+-- Test whether `str` contains non-portable characters.
+--
+--- @param str string string to check
+--- @return boolean # Whether `str` contains non-portable characters
+local function has_posix_nonportable_chars(str)
+ return string.match(str, "[^A-Za-z0-9%._-]") ~= nil
+end
+
-- ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
-- ▏
-- ▏ wfx Job Definitions & Types
@@ -1303,6 +1313,12 @@ M.job.workflow.dispatch:set(
return M.transition.result.FAIL_YIELD
end

+ if has_posix_nonportable_chars(job.id) then
+ local msg = "Invalid wfx job ID, only POSIX portable filename characters allowed"
+ suricatta.notify.error(msg)
+ return job.workflow:fail(job, msg)
+ end
+
if not sync_job_status { self, job, message = ("Start %s."):format(self.from.name), progress = 0 } then
return M.transition.result.FAIL_YIELD
end
@@ -1458,6 +1474,12 @@ M.job.workflow.dispatch:set(
return M.transition.result.FAIL_YIELD
end

+ if has_posix_nonportable_chars(job.id) then
+ local msg = "Invalid wfx job ID, only POSIX portable filename characters allowed"
+ suricatta.notify.error(msg)
+ return job.workflow:fail(job, msg)
+ end
+
if job.workflow.transitions[M.state.dau.DOWNLOAD] then
local function file_exists(name)
local f = io.open(name, "r")
--
2.47.3

Stefano Babic

unread,
May 26, 2026, 6:41:41 AM (10 days ago) May 26
to Konrad Schwarz, swup...@googlegroups.com, christi...@siemens.com, Felix Moessbauer
Applied to -master, thanks !

Best regards,
Stefano Babic


--
_______________________________________________________________________
Nabla Software Engineering GmbH
Hirschstr. 111A | 86156 Augsburg | Tel: +49 821 45592596
Geschäftsführer : Stefano Babic | HRB 40522 Augsburg
E-Mail: sba...@nabladev.com

Reply all
Reply to author
Forward
0 new messages