forked from gbrindisi/dockerfile-security
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dockerfile-security.rego
107 lines (94 loc) · 2.48 KB
/
dockerfile-security.rego
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package main
# Do Not store secrets in ENV variables
secrets_env = [
"passwd",
"password",
"pass",
"secret",
"key",
"access",
"api_key",
"apikey",
"token",
"tkn"
]
deny[msg] {
input[i].Cmd == "env"
val := input[i].Value
contains(lower(val[_]), secrets_env[_])
msg = sprintf("Line %d: Potential secret in ENV key found: %s", [i, val])
}
# Only use trusted base images
deny[msg] {
input[i].Cmd == "from"
val := split(input[i].Value[0], "/")
count(val) > 1
msg = sprintf("Line %d: use a trusted base image", [i])
}
# Do not use 'latest' tag for base imagedeny[msg] {
deny[msg] {
input[i].Cmd == "from"
val := split(input[i].Value[0], ":")
contains(lower(val[1]), "latest")
msg = sprintf("Line %d: do not use 'latest' tag for base images", [i])
}
# Avoid curl bashing
deny[msg] {
input[i].Cmd == "run"
val := concat(" ", input[i].Value)
matches := regex.find_n("(curl|wget)[^|^>]*[|>]", lower(val), -1)
count(matches) > 0
msg = sprintf("Line %d: Avoid curl bashing", [i])
}
# Do not upgrade your system packages
warn[msg] {
input[i].Cmd == "run"
val := concat(" ", input[i].Value)
matches := regex.match(".*?(apk|yum|dnf|apt|pip).+?(install|[dist-|check-|group]?up[grade|date]).*", lower(val))
matches == true
msg = sprintf("Line: %d: Do not upgrade your system packages: %s", [i, val])
}
# Do not use ADD if possible
deny[msg] {
input[i].Cmd == "add"
msg = sprintf("Line %d: Use COPY instead of ADD", [i])
}
# Any user...
any_user {
input[i].Cmd == "user"
}
deny[msg] {
not any_user
msg = "Do not run as root, use USER instead"
}
# ... but do not root
forbidden_users = [
"root",
"toor",
"0"
]
deny[msg] {
command := "user"
users := [name | input[i].Cmd == "user"; name := input[i].Value]
lastuser := users[count(users)-1]
contains(lower(lastuser[_]), forbidden_users[_])
msg = sprintf("Line %d: Last USER directive (USER %s) is forbidden", [i, lastuser])
}
# Do not sudo
deny[msg] {
input[i].Cmd == "run"
val := concat(" ", input[i].Value)
contains(lower(val), "sudo")
msg = sprintf("Line %d: Do not use 'sudo' command", [i])
}
# Use multi-stage builds
default multi_stage = false
multi_stage = true {
input[i].Cmd == "copy"
val := concat(" ", input[i].Flags)
contains(lower(val), "--from=")
}
deny[msg] {
multi_stage == false
msg = sprintf("You COPY, but do not appear to use multi-stage builds...", [])
}