From b6cd667d2c1456b4e1a9a633ef1b294ec60d7c21 Mon Sep 17 00:00:00 2001 From: AlinsRan Date: Fri, 12 Jun 2026 11:55:47 +0800 Subject: [PATCH] fix(elasticsearch-logger): guard os.date against invalid index template The dynamic-index feature passes the user-controlled time format straight to os.date in replace_time(). os.date raises (instead of returning nil) on some invalid strftime escapes, so a crafted index template would throw in the log phase rather than degrade gracefully. Wrap the call in pcall and fall back to an empty replacement on failure, as the existing nil-check already intended. Signed-off-by: AlinsRan --- apisix/plugins/elasticsearch-logger.lua | 10 ++++++++-- t/plugin/elasticsearch-logger2.t | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/apisix/plugins/elasticsearch-logger.lua b/apisix/plugins/elasticsearch-logger.lua index a53f3c051a34..e03d75c72098 100644 --- a/apisix/plugins/elasticsearch-logger.lua +++ b/apisix/plugins/elasticsearch-logger.lua @@ -24,6 +24,8 @@ local ngx_re = ngx.re local str_format = core.string.format local math_random = math.random local os_date = os.date +local pcall = pcall +local type = type local pairs = pairs local plugin_name = "elasticsearch-logger" @@ -204,8 +206,12 @@ end local function replace_time(m) local time_format = m[1] - local time = os_date(time_format) - if not time then + -- os.date returns a *table* (not a string) for the "*t"/"!*t" formats, and + -- on non-LuaJIT runtimes can raise on a bad strftime escape. Either way the + -- result would be stringified into a garbage index name, so require a + -- string and fall back to an empty replacement otherwise. + local ok, time = pcall(os_date, time_format) + if not ok or type(time) ~= "string" then core.log.error("failed to parse time format: ", time_format) return "" end diff --git a/t/plugin/elasticsearch-logger2.t b/t/plugin/elasticsearch-logger2.t index e28cabe1dd3f..108176a8e401 100644 --- a/t/plugin/elasticsearch-logger2.t +++ b/t/plugin/elasticsearch-logger2.t @@ -464,3 +464,27 @@ qr/body: \{"index":\{"_index":"services-myservice-\d\d\d\d\.\d\d\.\d\d"\}\}/ --- no_error_log failed to parse time format --- timeout: 5 + + + +=== TEST 10: non-string time format (os.date "*t" returns a table) falls back +--- config + location /t { + content_by_lua_block { + local plugin = require("apisix.plugins.elasticsearch-logger") + -- "*t"/"!*t" make os.date return a table instead of a string; + -- replace_time must reject it rather than stringify a garbage index. + for _, fmt in ipairs({"*t", "!*t"}) do + local new = plugin._resolve_index_vars("prefix{" .. fmt .. "}suffix") + if new ~= "prefixsuffix" then + ngx.say("error: " .. new) + return + end + end + ngx.say("ok") + } + } +--- response_body +ok +--- error_log +failed to parse time format