Crash with 1.1.1 when issuing ban command
Hello, I downloaded the 1.1.1 deb file from the Release page: ``` $ dpkg -I reaction.deb new Debian package, version 2.0. size 1704528 bytes: control archive=1412 bytes. 261 bytes, 9 lines control 1527 bytes, 50 lines * postinst #!/bin/sh 1037 bytes, 40 lines * postrm #!/bin/sh 169 bytes, 6 lines * prerm #!/bin/sh Package: reaction Version: 1.1.1 Architecture: amd64 Maintainer: ppom <> Sections: utils Package-Type: deb Priority: Optional Homepage: https://framagit.org/ppom/reaction Description: A daemon that scans program outputs for repeated patterns, and takes action. ``` And I got this crash with a fairly simple configuration: ``` Jan 10 21:24:07 vps systemd[1]: Started reaction.service - A daemon that scans program outputs for repeated patterns, and takes action.. Jan 10 21:24:07 vps reaction[11413]: 2024/01/10 21:24:07 INFO start command: run [iptables -w -N reaction] Jan 10 21:24:07 vps reaction[11413]: 2024/01/10 21:24:07 ERROR start command: run [iptables -w -N reaction]: exit status 1 Jan 10 21:24:07 vps reaction[11413]: 2024/01/10 21:24:07 INFO start command: run [iptables -w -I INPUT -p all -j reaction] Jan 10 21:24:07 vps reaction[11413]: 2024/01/10 21:24:07 INFO nginx.failedreq.ban: run [] Jan 10 21:24:07 vps reaction[11413]: panic: runtime error: slice bounds out of range [1:0] Jan 10 21:24:07 vps reaction[11413]: goroutine 11 [running]: Jan 10 21:24:07 vps reaction[11413]: framagit.org/ppom/reaction/app.(*Action).exec(0xc00005a6e0, {0xc000122a10?, 0xe?}) Jan 10 21:24:07 vps reaction[11413]: /tmp/code/app/daemon.go:119 +0x3cd Jan 10 21:24:07 vps reaction[11413]: framagit.org/ppom/reaction/app.ActionsManager.func1() Jan 10 21:24:07 vps reaction[11413]: /tmp/code/app/daemon.go:135 +0x4a Jan 10 21:24:07 vps reaction[11413]: created by framagit.org/ppom/reaction/app.ActionsManager Jan 10 21:24:07 vps reaction[11413]: /tmp/code/app/daemon.go:131 +0xc7e ``` Here is the configuration: ```jsonnet local banFor(time) = { ban: { cmd: ['ip46tables', '-w', '-A', 'reaction', '-s', '<ip>', '-j', 'DROP'], }, unban: { after: time, cmd: ['ip46tables', '-w', '-D', 'reaction', '-s', '<ip>', '-j', 'DROP'], }, }; { patterns: { ip: { regex: @'(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|(?:(?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))', ignore: ['127.0.0.1', '::1'], }, dqs: { regex: @'"((?:\\.|[^\\])*?)"', }, }, start: [ ['ip46tables', '-w', '-N', 'reaction'], ['ip46tables', '-w', '-I', 'INPUT', '-p', 'all', '-j', 'reaction'], ], stop: [ ['ip46tables', '-w,', '-D', 'INPUT', '-p', 'all', '-j', 'reaction'], ['ip46tables', '-w', '-F', 'reaction'], ['ip46tables', '-w', '-X', 'reaction'], ], streams: { nginx: { cmd: ['tail', '-f', '/var/log/nginx/access.log'], filters: { failedreq: { regex: [@'^<ip> [^"]*"(?:\\.|[^\\])*?" [45]\d\d '], retry: 5, retryperiod: '15m', actions: banFor('1h'), }, }, }, }, } ``` I then cloned the repo, checked out the v1.1.1 tag and investigated a little. I removed most of the content of the config/server.jsonnet config file to only keep the filter "suspectRequests" for nginx. I also replaced the tail command by a cat of a sample log file. I then compiled using the Makefile on fedora using go version go1.21.5 linux/amd64. This reproduced the issue and, with the help of a lot of printf, as I'm not familiar with go, I ended-up with the following fix: ```diff diff --git a/app/daemon.go b/app/daemon.go index f249c83..f4b8e6e 100644 --- a/app/daemon.go +++ b/app/daemon.go @@ -105,7 +105,7 @@ func (a *Action) exec(match string) { var computedCommand []string if a.filter.pattern != nil { - computedCommand := make([]string, 0, len(a.Cmd)) + computedCommand = make([]string, 0, len(a.Cmd)) for _, item := range a.Cmd { computedCommand = append(computedCommand, strings.ReplaceAll(item, a.filter.pattern.nameWithBraces, match)) ``` Does that make sense? I do not know go.
issue