go.lang.security.decompression_bomb.potential-dos-via-decompression-bomb
Verifed by r2c
Community Favorite

Author
156,963
Download Count*
License
Detected a possible denial-of-service via a zip bomb attack. By limiting the max bytes read, you can mitigate this attack. io.CopyN()
can specify a size. Refer to https://bomb.codes/ to learn more about this attack and other ways to mitigate it.
Run Locally
Run in CI
Defintion
rules:
- id: potential-dos-via-decompression-bomb
message: Detected a possible denial-of-service via a zip bomb attack. By
limiting the max bytes read, you can mitigate this attack. `io.CopyN()`
can specify a size. Refer to https://bomb.codes/ to learn more about this
attack and other ways to mitigate it.
severity: WARNING
languages:
- go
patterns:
- pattern-either:
- pattern: io.Copy(...)
- pattern: io.CopyBuffer(...)
- pattern-either:
- pattern-inside: |
gzip.NewReader(...)
...
- pattern-inside: |
zlib.NewReader(...)
...
- pattern-inside: |
zlib.NewReaderDict(...)
...
- pattern-inside: |
bzip2.NewReader(...)
...
- pattern-inside: |
flate.NewReader(...)
...
- pattern-inside: |
flate.NewReaderDict(...)
...
- pattern-inside: |
lzw.NewReader(...)
...
- pattern-inside: |
tar.NewReader(...)
...
- pattern-inside: |
zip.NewReader(...)
...
- pattern-inside: |
zip.OpenReader(...)
...
fix-regex:
regex: (.*)(Copy|CopyBuffer)\((.*?),(.*?)(\)|,.*\))
replacement: \1CopyN(\3, \4, 1024*1024*256)
metadata:
cwe:
- "CWE-400: Uncontrolled Resource Consumption"
source-rule-url: https://github.com/securego/gosec
references:
- https://bomb.codes/
- https://golang.org/pkg/io/#CopyN
- https://github.com/securego/gosec/blob/master/rules/decompression-bomb.go
category: security
technology:
- go
confidence: LOW
cwe2022-top25: true
subcategory:
- audit
likelihood: LOW
impact: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Denial-of-Service (DoS)
Examples
decompression_bomb.go
// cf. https://github.com/securego/gosec/blob/master/testutils/source.go#L684
package main
import (
"bytes"
"compress/zlib"
"io"
"os"
)
func blah() {
buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
b := bytes.NewReader(buff)
r, err := zlib.NewReader(b)
if err != nil {
panic(err)
}
// ruleid: potential-dos-via-decompression-bomb
_, err := io.Copy(os.Stdout, r)
if err != nil {
panic(err)
}
r.Close()
}
func blah2() {
buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
b := bytes.NewReader(buff)
r, err := zlib.NewReader(b)
if err != nil {
panic(err)
}
buf := make([]byte, 8)
// ruleid: potential-dos-via-decompression-bomb
_, err := io.CopyBuffer(os.Stdout, r, buf)
if err != nil {
panic(err)
}
r.Close()
}
func blah3() {
r, err := zip.OpenReader("tmp.zip")
if err != nil {
panic(err)
}
defer r.Close()
for i, f := range r.File {
out, err := os.OpenFile("output" + strconv.Itoa(i), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
panic(err)
}
rc, err := f.Open()
if err != nil {
panic(err)
}
// ruleid: potential-dos-via-decompression-bomb
_, err = io.Copy(out, rc)
out.Close()
rc.Close()
if err != nil {
panic(err)
}
}
}
func benign() {
s, err := os.Open("src")
if err != nil {
panic(err)
}
defer s.Close()
d, err := os.Create("dst")
if err != nil {
panic(err)
}
defer d.Close()
// ok: potential-dos-via-decompression-bomb
_, err = io.Copy(d, s)
if err != nil {
panic(err)
}
}
func ok() {
buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
b := bytes.NewReader(buff)
r, err := zlib.NewReader(b)
if err != nil {
panic(err)
}
buf := make([]byte, 8)
// ok: potential-dos-via-decompression-bomb
_, err := io.CopyN(os.Stdout, r, buf, 1024*1024*4)
if err != nil {
panic(err)
}
r.Close()
}
Short Link: https://sg.run/RodK