Plugin = { name = "TruffleHog", description = [[ Scans request and response bodies for secrets using [TruffleHog](https://github.com/trufflesecurity/trufflehog). Requires `trufflehog` v3+ to be installed and available in PATH. Each finding is stored on the **Findings** page with the matched detector output. Findings are deduplicated per host+path+body content so repeated requests do not create duplicates. ]], on_request = { sync = false }, on_response = { sync = false }, disable_by_default = true, } local function scan(label, content, host, path) if not content or content == "" then return end local out, err = shell_pipe("f=$(mktemp) && cat > \"$f\" && trufflehog filesystem --no-color \"$f\"; rc=$?; rm -f \"$f\"; exit $rc", content) if err and err ~= "" then log("trufflehog error on " .. label .. ": " .. err) return end if not out or out == "" then return end local blocks = {} local current = nil for line in out:gmatch("[^\n]+") do if line:match("^Found ") then if current then table.insert(blocks, current) end current = line elseif current then current = current .. "\n" .. line end end if current then table.insert(blocks, current) end for _, block in ipairs(blocks) do create_finding({ title = "Secret detected in " .. label .. " (" .. host .. ")", description = "**Host:** `" .. host .. "` \n**Path:** `" .. path .. "`\n\n```\n" .. block .. "\n```", key = host .. "|" .. path .. "|" .. label .. "|" .. block, severity = "high", }) end end function on_request(req) scan("request", req:get_body(), req.host, req.path) end function on_response(req, res) scan("response", res:get_body(), req.host, req.path) end