From 4f90ad38dedf883647958b27a4d5ae6de98dbe36 Mon Sep 17 00:00:00 2001 From: sabban Date: Mon, 1 Sep 2025 09:33:49 +0200 Subject: [PATCH 1/4] fix(stream): improve error handling in duration parsing fix https://github.com/crowdsecurity/cs-nginx-bouncer/issues/93 --- lib/plugins/crowdsec/stream.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/plugins/crowdsec/stream.lua b/lib/plugins/crowdsec/stream.lua index cc05d15..a1cb54c 100644 --- a/lib/plugins/crowdsec/stream.lua +++ b/lib/plugins/crowdsec/stream.lua @@ -72,10 +72,11 @@ end local function parse_duration(duration) local match, err = ngx.re.match(duration, "^((?[0-9]+)h)?((?[0-9]+)m)?(?[0-9]+)") local ttl = 0 - if not match then + if not match or err then if err then - return ttl, err + ngx.log(ngx.ERR, "Error while parsing duration: " .. err) end + return ttl, err end if match["hours"] ~= nil and match["hours"] ~= false then local hours = tonumber(match["hours"]) @@ -213,7 +214,8 @@ function stream:stream_query(api_url, timeout, api_key_header, api_key, user_age decision.origin = "lists:" .. decision.scenario end if bouncing_on_type == decision.type or bouncing_on_type == "all" then - local ttl, err = parse_duration(decision.duration) + local ttl + ttl, err = parse_duration(decision.duration) if err ~= nil then ngx.log(ngx.ERR, "[Crowdsec] failed to parse ban duration '" .. decision.duration .. "' : " .. err) end From e1a41f6229d226379435926a1f2c9c4b61e2904d Mon Sep 17 00:00:00 2001 From: sabban Date: Mon, 1 Sep 2025 14:41:41 +0200 Subject: [PATCH 2/4] fix regexp --- lib/plugins/crowdsec/stream.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/plugins/crowdsec/stream.lua b/lib/plugins/crowdsec/stream.lua index a1cb54c..b6c7c6b 100644 --- a/lib/plugins/crowdsec/stream.lua +++ b/lib/plugins/crowdsec/stream.lua @@ -68,9 +68,9 @@ end --- Parse a golang duration string and return the number of seconds --- @param duration string: the duration string to parse --- @return number: the number of seconds ---- @return string: the error message if any +--- @return string: the error message or nil if no error local function parse_duration(duration) - local match, err = ngx.re.match(duration, "^((?[0-9]+)h)?((?[0-9]+)m)?(?[0-9]+)") + local match, err = ngx.re.match(duration, "^((?[0-9]+)h)?((?[0-9]+)m)?((?[0-9]+)s)?((?[0-9]+)ms)?((?[0-9]+)µs)?((?[0-9]+)ns)?)$") local ttl = 0 if not match or err then if err then @@ -90,6 +90,11 @@ local function parse_duration(duration) local seconds = tonumber(match["seconds"]) ttl = ttl + seconds end + if match["milliseconds"] ~= nil and match["milliseconds"] ~= false then + local milliseconds = tonumber(match["milliseconds"]) + ttl = ttl + (milliseconds / 1000) + end + --- microseconds and nanoseconds are ignored as they are too small to be useful in this context return ttl, nil end From 1cb1c16703be185f61c3ffbd5cd0cb9a1e617126 Mon Sep 17 00:00:00 2001 From: sabban Date: Mon, 1 Sep 2025 17:53:02 +0200 Subject: [PATCH 3/4] fix the regexp --- lib/plugins/crowdsec/stream.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plugins/crowdsec/stream.lua b/lib/plugins/crowdsec/stream.lua index b6c7c6b..c2c0522 100644 --- a/lib/plugins/crowdsec/stream.lua +++ b/lib/plugins/crowdsec/stream.lua @@ -70,7 +70,7 @@ end --- @return number: the number of seconds --- @return string: the error message or nil if no error local function parse_duration(duration) - local match, err = ngx.re.match(duration, "^((?[0-9]+)h)?((?[0-9]+)m)?((?[0-9]+)s)?((?[0-9]+)ms)?((?[0-9]+)µs)?((?[0-9]+)ns)?)$") + local match, err = ngx.re.match(duration, "^((?[0-9]+)h)?((?[0-9]+)m)?((?[0-9]+)s)?((?[0-9]+)ms)?((?[0-9]+)µs)?((?[0-9]+)ns)?$") local ttl = 0 if not match or err then if err then From 8ebd4e69248d439a884a0ddf1f1865ea5595b5b2 Mon Sep 17 00:00:00 2001 From: sabban Date: Mon, 1 Sep 2025 18:06:16 +0200 Subject: [PATCH 4/4] fix the regexp --- lib/plugins/crowdsec/stream.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plugins/crowdsec/stream.lua b/lib/plugins/crowdsec/stream.lua index c2c0522..92dd2d7 100644 --- a/lib/plugins/crowdsec/stream.lua +++ b/lib/plugins/crowdsec/stream.lua @@ -70,7 +70,7 @@ end --- @return number: the number of seconds --- @return string: the error message or nil if no error local function parse_duration(duration) - local match, err = ngx.re.match(duration, "^((?[0-9]+)h)?((?[0-9]+)m)?((?[0-9]+)s)?((?[0-9]+)ms)?((?[0-9]+)µs)?((?[0-9]+)ns)?$") + local match, err = ngx.re.match(duration, "^((?[0-9]+)h)?((?[0-9]+)m)?((?[0-9]+)s)?((?[0-9]+)ms)?((?[0-9]+)(µ|u)s)?((?[0-9]+)ns)?$") local ttl = 0 if not match or err then if err then