From 4a7544caea0c669eb730ad5fd2942de1f2924715 Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Mon, 16 May 2022 14:16:55 +0100 Subject: [PATCH] docs: Update misconfig output in examples (#2128) --- docs/docs/misconfiguration/custom/debug.md | 457 +++++++++++-------- docs/docs/misconfiguration/options/filter.md | 220 ++------- docs/docs/misconfiguration/options/policy.md | 53 --- docs/docs/misconfiguration/scanning.md | 157 +++---- docs/getting-started/quickstart.md | 69 +-- 5 files changed, 402 insertions(+), 554 deletions(-) diff --git a/docs/docs/misconfiguration/custom/debug.md b/docs/docs/misconfiguration/custom/debug.md index 923ac0627a..8ea0cc5e0e 100644 --- a/docs/docs/misconfiguration/custom/debug.md +++ b/docs/docs/misconfiguration/custom/debug.md @@ -6,38 +6,209 @@ This will output a large trace from Open Policy Agent like the following: !!! tip Only failed policies show traces. If you want to debug a passed policy, you need to make it fail on purpose. -```bash +```shell $ trivy conf --trace configs/ -2021-07-11T16:45:58.493+0300 INFO Detected config files: 1 +2022-05-16T13:47:58.853+0100 INFO Detected config files: 1 Dockerfile (dockerfile) ======================= -Tests: 23 (SUCCESSES: 22, FAILURES: 1, EXCEPTIONS: 0) -Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) +Tests: 23 (SUCCESSES: 21, FAILURES: 2, EXCEPTIONS: 0) +Failures: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 1, CRITICAL: 0) + +MEDIUM: Specify a tag in the 'FROM' statement for image 'alpine' +═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +When using a 'FROM' statement you should use a specific tag to avoid uncontrolled behavior when the image is updated. + +See https://avd.aquasec.com/misconfig/ds001 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Dockerfile:1 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 1 [ FROM alpine:latest +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + +HIGH: Last USER command in Dockerfile should not be 'root' +═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile. + +See https://avd.aquasec.com/misconfig/ds002 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Dockerfile:3 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 3 [ USER root +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + +ID: DS001 +File: Dockerfile +Namespace: builtin.dockerfile.DS001 +Query: data.builtin.dockerfile.DS001.deny +Message: Specify a tag in the 'FROM' statement for image 'alpine' +TRACE Enter data.builtin.dockerfile.DS001.deny = _ +TRACE | Eval data.builtin.dockerfile.DS001.deny = _ +TRACE | Index data.builtin.dockerfile.DS001.deny (matched 1 rule) +TRACE | Enter data.builtin.dockerfile.DS001.deny +TRACE | | Eval output = data.builtin.dockerfile.DS001.fail_latest[_] +TRACE | | Index data.builtin.dockerfile.DS001.fail_latest (matched 1 rule) +TRACE | | Enter data.builtin.dockerfile.DS001.fail_latest +TRACE | | | Eval output = data.builtin.dockerfile.DS001.image_tags[_] +TRACE | | | Index data.builtin.dockerfile.DS001.image_tags (matched 2 rules) +TRACE | | | Enter data.builtin.dockerfile.DS001.image_tags +TRACE | | | | Eval from = data.lib.docker.from[_] +TRACE | | | | Index data.lib.docker.from (matched 1 rule) +TRACE | | | | Enter data.lib.docker.from +TRACE | | | | | Eval instruction = input.stages[_][_] +TRACE | | | | | Eval instruction.Cmd = "from" +TRACE | | | | | Exit data.lib.docker.from +TRACE | | | | Redo data.lib.docker.from +TRACE | | | | | Redo instruction.Cmd = "from" +TRACE | | | | | Redo instruction = input.stages[_][_] +TRACE | | | | | Eval instruction.Cmd = "from" +TRACE | | | | | Fail instruction.Cmd = "from" +TRACE | | | | | Redo instruction = input.stages[_][_] +TRACE | | | | | Eval instruction.Cmd = "from" +TRACE | | | | | Fail instruction.Cmd = "from" +TRACE | | | | | Redo instruction = input.stages[_][_] +TRACE | | | | Eval name = from.Value[0] +TRACE | | | | Eval not startswith(name, "$") +TRACE | | | | Enter startswith(name, "$") +TRACE | | | | | Eval startswith(name, "$") +TRACE | | | | | Fail startswith(name, "$") +TRACE | | | | Eval data.builtin.dockerfile.DS001.parse_tag(name, __local505__) +TRACE | | | | Index data.builtin.dockerfile.DS001.parse_tag (matched 2 rules) +TRACE | | | | Enter data.builtin.dockerfile.DS001.parse_tag +TRACE | | | | | Eval split(name, ":", __local504__) +TRACE | | | | | Eval [img, tag] = __local504__ +TRACE | | | | | Exit data.builtin.dockerfile.DS001.parse_tag +TRACE | | | | Eval [img, tag] = __local505__ +TRACE | | | | Eval output = {"cmd": from, "img": img, "tag": tag} +TRACE | | | | Exit data.builtin.dockerfile.DS001.image_tags +TRACE | | | Redo data.builtin.dockerfile.DS001.image_tags +TRACE | | | | Redo output = {"cmd": from, "img": img, "tag": tag} +TRACE | | | | Redo [img, tag] = __local505__ +TRACE | | | | Redo data.builtin.dockerfile.DS001.parse_tag(name, __local505__) +TRACE | | | | Redo data.builtin.dockerfile.DS001.parse_tag +TRACE | | | | | Redo [img, tag] = __local504__ +TRACE | | | | | Redo split(name, ":", __local504__) +TRACE | | | | Enter data.builtin.dockerfile.DS001.parse_tag +TRACE | | | | | Eval tag = "latest" +TRACE | | | | | Eval not contains(img, ":") +TRACE | | | | | Enter contains(img, ":") +TRACE | | | | | | Eval contains(img, ":") +TRACE | | | | | | Exit contains(img, ":") +TRACE | | | | | Redo contains(img, ":") +TRACE | | | | | | Redo contains(img, ":") +TRACE | | | | | Fail not contains(img, ":") +TRACE | | | | | Redo tag = "latest" +TRACE | | | | Redo name = from.Value[0] +TRACE | | | | Redo from = data.lib.docker.from[_] +TRACE | | | Enter data.builtin.dockerfile.DS001.image_tags +TRACE | | | | Eval from = data.lib.docker.from[i] +TRACE | | | | Index data.lib.docker.from (matched 1 rule) +TRACE | | | | Eval name = from.Value[0] +TRACE | | | | Eval cmd_obj = input.stages[j][k] +TRACE | | | | Eval possibilities = {"arg", "env"} +TRACE | | | | Eval cmd_obj.Cmd = possibilities[l] +TRACE | | | | Fail cmd_obj.Cmd = possibilities[l] +TRACE | | | | Redo possibilities = {"arg", "env"} +TRACE | | | | Redo cmd_obj = input.stages[j][k] +TRACE | | | | Eval possibilities = {"arg", "env"} +TRACE | | | | Eval cmd_obj.Cmd = possibilities[l] +TRACE | | | | Fail cmd_obj.Cmd = possibilities[l] +TRACE | | | | Redo possibilities = {"arg", "env"} +TRACE | | | | Redo cmd_obj = input.stages[j][k] +TRACE | | | | Eval possibilities = {"arg", "env"} +TRACE | | | | Eval cmd_obj.Cmd = possibilities[l] +TRACE | | | | Fail cmd_obj.Cmd = possibilities[l] +TRACE | | | | Redo possibilities = {"arg", "env"} +TRACE | | | | Redo cmd_obj = input.stages[j][k] +TRACE | | | | Redo name = from.Value[0] +TRACE | | | | Redo from = data.lib.docker.from[i] +TRACE | | | Eval __local752__ = output.img +TRACE | | | Eval neq(__local752__, "scratch") +TRACE | | | Eval __local753__ = output.img +TRACE | | | Eval not data.builtin.dockerfile.DS001.is_alias(__local753__) +TRACE | | | Enter data.builtin.dockerfile.DS001.is_alias(__local753__) +TRACE | | | | Eval data.builtin.dockerfile.DS001.is_alias(__local753__) +TRACE | | | | Index data.builtin.dockerfile.DS001.is_alias (matched 1 rule, early exit) +TRACE | | | | Enter data.builtin.dockerfile.DS001.is_alias +TRACE | | | | | Eval img = data.builtin.dockerfile.DS001.get_aliases[_] +TRACE | | | | | Index data.builtin.dockerfile.DS001.get_aliases (matched 1 rule) +TRACE | | | | | Enter data.builtin.dockerfile.DS001.get_aliases +TRACE | | | | | | Eval from_cmd = data.lib.docker.from[_] +TRACE | | | | | | Index data.lib.docker.from (matched 1 rule) +TRACE | | | | | | Eval __local749__ = from_cmd.Value +TRACE | | | | | | Eval data.builtin.dockerfile.DS001.get_alias(__local749__, __local503__) +TRACE | | | | | | Index data.builtin.dockerfile.DS001.get_alias (matched 1 rule) +TRACE | | | | | | Enter data.builtin.dockerfile.DS001.get_alias +TRACE | | | | | | | Eval __local748__ = values[i] +TRACE | | | | | | | Eval lower(__local748__, __local501__) +TRACE | | | | | | | Eval "as" = __local501__ +TRACE | | | | | | | Fail "as" = __local501__ +TRACE | | | | | | | Redo lower(__local748__, __local501__) +TRACE | | | | | | | Redo __local748__ = values[i] +TRACE | | | | | | Fail data.builtin.dockerfile.DS001.get_alias(__local749__, __local503__) +TRACE | | | | | | Redo __local749__ = from_cmd.Value +TRACE | | | | | | Redo from_cmd = data.lib.docker.from[_] +TRACE | | | | | Fail img = data.builtin.dockerfile.DS001.get_aliases[_] +TRACE | | | | Fail data.builtin.dockerfile.DS001.is_alias(__local753__) +TRACE | | | Eval output.tag = "latest" +TRACE | | | Exit data.builtin.dockerfile.DS001.fail_latest +TRACE | | Redo data.builtin.dockerfile.DS001.fail_latest +TRACE | | | Redo output.tag = "latest" +TRACE | | | Redo __local753__ = output.img +TRACE | | | Redo neq(__local752__, "scratch") +TRACE | | | Redo __local752__ = output.img +TRACE | | | Redo output = data.builtin.dockerfile.DS001.image_tags[_] +TRACE | | Eval __local754__ = output.img +TRACE | | Eval sprintf("Specify a tag in the 'FROM' statement for image '%s'", [__local754__], __local509__) +TRACE | | Eval msg = __local509__ +TRACE | | Eval __local755__ = output.cmd +TRACE | | Eval data.lib.docker.result(msg, __local755__, __local510__) +TRACE | | Index data.lib.docker.result (matched 1 rule) +TRACE | | Enter data.lib.docker.result +TRACE | | | Eval object.get(cmd, "EndLine", 0, __local470__) +TRACE | | | Eval object.get(cmd, "Path", "", __local471__) +TRACE | | | Eval object.get(cmd, "StartLine", 0, __local472__) +TRACE | | | Eval result = {"endline": __local470__, "filepath": __local471__, "msg": msg, "startline": __local472__} +TRACE | | | Exit data.lib.docker.result +TRACE | | Eval res = __local510__ +TRACE | | Exit data.builtin.dockerfile.DS001.deny +TRACE | Redo data.builtin.dockerfile.DS001.deny +TRACE | | Redo res = __local510__ +TRACE | | Redo data.lib.docker.result(msg, __local755__, __local510__) +TRACE | | Redo data.lib.docker.result +TRACE | | | Redo result = {"endline": __local470__, "filepath": __local471__, "msg": msg, "startline": __local472__} +TRACE | | | Redo object.get(cmd, "StartLine", 0, __local472__) +TRACE | | | Redo object.get(cmd, "Path", "", __local471__) +TRACE | | | Redo object.get(cmd, "EndLine", 0, __local470__) +TRACE | | Redo __local755__ = output.cmd +TRACE | | Redo msg = __local509__ +TRACE | | Redo sprintf("Specify a tag in the 'FROM' statement for image '%s'", [__local754__], __local509__) +TRACE | | Redo __local754__ = output.img +TRACE | | Redo output = data.builtin.dockerfile.DS001.fail_latest[_] +TRACE | Exit data.builtin.dockerfile.DS001.deny = _ +TRACE Redo data.builtin.dockerfile.DS001.deny = _ +TRACE | Redo data.builtin.dockerfile.DS001.deny = _ +TRACE -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| Dockerfile Security Check | DS002 | Image user is 'root' | HIGH | Last USER command in | -| | | | | Dockerfile should not be 'root' | -| | | | | -->avd.aquasec.com/appshield/ds002 | -+---------------------------+------------+----------------------+----------+------------------------------------------+ ID: DS002 File: Dockerfile -Namespace: appshield.dockerfile.DS002 -Query: data.appshield.dockerfile.DS002.deny +Namespace: builtin.dockerfile.DS002 +Query: data.builtin.dockerfile.DS002.deny Message: Last USER command in Dockerfile should not be 'root' -TRACE Enter data.appshield.dockerfile.DS002.deny = _ -TRACE | Eval data.appshield.dockerfile.DS002.deny = _ -TRACE | Index data.appshield.dockerfile.DS002.deny matched 2 rules) -TRACE | Enter data.appshield.dockerfile.DS002.deny -TRACE | | Eval data.appshield.dockerfile.DS002.fail_user_count -TRACE | | Index data.appshield.dockerfile.DS002.fail_user_count (matched 1 rule) -TRACE | | Enter data.appshield.dockerfile.DS002.fail_user_count -TRACE | | | Eval __local559__ = data.appshield.dockerfile.DS002.get_user -TRACE | | | Index data.appshield.dockerfile.DS002.get_user (matched 1 rule) -TRACE | | | Enter data.appshield.dockerfile.DS002.get_user +TRACE Enter data.builtin.dockerfile.DS002.deny = _ +TRACE | Eval data.builtin.dockerfile.DS002.deny = _ +TRACE | Index data.builtin.dockerfile.DS002.deny (matched 2 rules) +TRACE | Enter data.builtin.dockerfile.DS002.deny +TRACE | | Eval data.builtin.dockerfile.DS002.fail_user_count +TRACE | | Index data.builtin.dockerfile.DS002.fail_user_count (matched 1 rule, early exit) +TRACE | | Enter data.builtin.dockerfile.DS002.fail_user_count +TRACE | | | Eval __local771__ = data.builtin.dockerfile.DS002.get_user +TRACE | | | Index data.builtin.dockerfile.DS002.get_user (matched 1 rule) +TRACE | | | Enter data.builtin.dockerfile.DS002.get_user TRACE | | | | Eval user = data.lib.docker.user[_] TRACE | | | | Index data.lib.docker.user (matched 1 rule) TRACE | | | | Enter data.lib.docker.user @@ -46,180 +217,88 @@ TRACE | | | | | Eval instruction.Cmd = "user" TRACE | | | | | Fail instruction.Cmd = "user" TRACE | | | | | Redo instruction = input.stages[_][_] TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" TRACE | | | | | Exit data.lib.docker.user -TRACE | | | | Eval username = user.Value[_] -TRACE | | | | Exit data.appshield.dockerfile.DS002.get_user -TRACE | | | Redo data.appshield.dockerfile.DS002.get_user -TRACE | | | | Redo username = user.Value[_] -TRACE | | | | Redo user = data.lib.docker.user[_] -TRACE | | | | Redo data.lib.docker.user -TRACE | | | | | Redo instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Exit data.lib.docker.user -TRACE | | | | Eval username = user.Value[_] -TRACE | | | | Exit data.appshield.dockerfile.DS002.get_user -TRACE | | | Redo data.appshield.dockerfile.DS002.get_user -TRACE | | | | Redo username = user.Value[_] -TRACE | | | | Redo user = data.lib.docker.user[_] TRACE | | | | Redo data.lib.docker.user TRACE | | | | | Redo instruction.Cmd = "user" TRACE | | | | | Redo instruction = input.stages[_][_] TRACE | | | | | Eval instruction.Cmd = "user" TRACE | | | | | Fail instruction.Cmd = "user" TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | Eval count(__local559__, __local391__) -TRACE | | | Eval lt(__local391__, 1) -TRACE | | | Fail lt(__local391__, 1) -TRACE | | | Redo count(__local559__, __local391__) -TRACE | | | Redo __local559__ = data.appshield.dockerfile.DS002.get_user -TRACE | | Fail data.appshield.dockerfile.DS002.fail_user_count -TRACE | Enter data.appshield.dockerfile.DS002.deny -TRACE | | Eval data.appshield.dockerfile.DS002.fail_last_user_root -TRACE | | Index data.appshield.dockerfile.DS002.fail_last_user_root (matched 1 rule) -TRACE | | Enter data.appshield.dockerfile.DS002.fail_last_user_root -TRACE | | | Eval __local560__ = data.appshield.dockerfile.DS002.get_user -TRACE | | | Index data.appshield.dockerfile.DS002.get_user (matched 1 rule) -TRACE | | | Enter data.appshield.dockerfile.DS002.get_user -TRACE | | | | Eval user = data.lib.docker.user[_] -TRACE | | | | Index data.lib.docker.user (matched 1 rule) -TRACE | | | | Enter data.lib.docker.user -TRACE | | | | | Eval instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Exit data.lib.docker.user TRACE | | | | Eval username = user.Value[_] -TRACE | | | | Exit data.appshield.dockerfile.DS002.get_user -TRACE | | | Redo data.appshield.dockerfile.DS002.get_user +TRACE | | | | Exit data.builtin.dockerfile.DS002.get_user +TRACE | | | Redo data.builtin.dockerfile.DS002.get_user TRACE | | | | Redo username = user.Value[_] TRACE | | | | Redo user = data.lib.docker.user[_] -TRACE | | | | Redo data.lib.docker.user -TRACE | | | | | Redo instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Exit data.lib.docker.user -TRACE | | | | Eval username = user.Value[_] -TRACE | | | | Exit data.appshield.dockerfile.DS002.get_user -TRACE | | | Redo data.appshield.dockerfile.DS002.get_user -TRACE | | | | Redo username = user.Value[_] -TRACE | | | | Redo user = data.lib.docker.user[_] -TRACE | | | | Redo data.lib.docker.user -TRACE | | | | | Redo instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | Eval cast_array(__local560__, __local392__) -TRACE | | | Eval user = __local392__ -TRACE | | | Eval __local561__ = data.appshield.dockerfile.DS002.get_user -TRACE | | | Index data.appshield.dockerfile.DS002.get_user (matched 1 rule) -TRACE | | | Enter data.appshield.dockerfile.DS002.get_user -TRACE | | | | Eval user = data.lib.docker.user[_] -TRACE | | | | Index data.lib.docker.user (matched 1 rule) -TRACE | | | | Enter data.lib.docker.user -TRACE | | | | | Eval instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Exit data.lib.docker.user -TRACE | | | | Eval username = user.Value[_] -TRACE | | | | Exit data.appshield.dockerfile.DS002.get_user -TRACE | | | Redo data.appshield.dockerfile.DS002.get_user -TRACE | | | | Redo username = user.Value[_] -TRACE | | | | Redo user = data.lib.docker.user[_] -TRACE | | | | Redo data.lib.docker.user -TRACE | | | | | Redo instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Exit data.lib.docker.user -TRACE | | | | Eval username = user.Value[_] -TRACE | | | | Exit data.appshield.dockerfile.DS002.get_user -TRACE | | | Redo data.appshield.dockerfile.DS002.get_user -TRACE | | | | Redo username = user.Value[_] -TRACE | | | | Redo user = data.lib.docker.user[_] -TRACE | | | | Redo data.lib.docker.user -TRACE | | | | | Redo instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | | | Eval instruction.Cmd = "user" -TRACE | | | | | Fail instruction.Cmd = "user" -TRACE | | | | | Redo instruction = input.stages[_][_] -TRACE | | | Eval count(__local561__, __local393__) -TRACE | | | Eval len = __local393__ -TRACE | | | Eval minus(len, 1, __local394__) -TRACE | | | Eval user[__local394__] = "root" -TRACE | | | Exit data.appshield.dockerfile.DS002.fail_last_user_root -TRACE | | Eval res = "Last USER command in Dockerfile should not be 'root'" -TRACE | | Exit data.appshield.dockerfile.DS002.deny -TRACE | Redo data.appshield.dockerfile.DS002.deny -TRACE | | Redo res = "Last USER command in Dockerfile should not be 'root'" -TRACE | | Redo data.appshield.dockerfile.DS002.fail_last_user_root -TRACE | | Redo data.appshield.dockerfile.DS002.fail_last_user_root -TRACE | | | Redo user[__local394__] = "root" -TRACE | | | Redo minus(len, 1, __local394__) -TRACE | | | Redo len = __local393__ -TRACE | | | Redo count(__local561__, __local393__) -TRACE | | | Redo __local561__ = data.appshield.dockerfile.DS002.get_user -TRACE | | | Redo user = __local392__ -TRACE | | | Redo cast_array(__local560__, __local392__) -TRACE | | | Redo __local560__ = data.appshield.dockerfile.DS002.get_user -TRACE | Exit data.appshield.dockerfile.DS002.deny = _ -TRACE Redo data.appshield.dockerfile.DS002.deny = _ -TRACE | Redo data.appshield.dockerfile.DS002.deny = _ +TRACE | | | Eval count(__local771__, __local536__) +TRACE | | | Eval lt(__local536__, 1) +TRACE | | | Fail lt(__local536__, 1) +TRACE | | | Redo count(__local771__, __local536__) +TRACE | | | Redo __local771__ = data.builtin.dockerfile.DS002.get_user +TRACE | | Fail data.builtin.dockerfile.DS002.fail_user_count +TRACE | Enter data.builtin.dockerfile.DS002.deny +TRACE | | Eval cmd = data.builtin.dockerfile.DS002.fail_last_user_root[_] +TRACE | | Index data.builtin.dockerfile.DS002.fail_last_user_root (matched 1 rule) +TRACE | | Enter data.builtin.dockerfile.DS002.fail_last_user_root +TRACE | | | Eval stage_users = data.lib.docker.stage_user[_] +TRACE | | | Index data.lib.docker.stage_user (matched 1 rule) +TRACE | | | Enter data.lib.docker.stage_user +TRACE | | | | Eval stage = input.stages[stage_name] +TRACE | | | | Eval users = [cmd | cmd = stage[_]; cmd.Cmd = "user"] +TRACE | | | | Enter cmd = stage[_]; cmd.Cmd = "user" +TRACE | | | | | Eval cmd = stage[_] +TRACE | | | | | Eval cmd.Cmd = "user" +TRACE | | | | | Fail cmd.Cmd = "user" +TRACE | | | | | Redo cmd = stage[_] +TRACE | | | | | Eval cmd.Cmd = "user" +TRACE | | | | | Exit cmd = stage[_]; cmd.Cmd = "user" +TRACE | | | | Redo cmd = stage[_]; cmd.Cmd = "user" +TRACE | | | | | Redo cmd.Cmd = "user" +TRACE | | | | | Redo cmd = stage[_] +TRACE | | | | | Eval cmd.Cmd = "user" +TRACE | | | | | Fail cmd.Cmd = "user" +TRACE | | | | | Redo cmd = stage[_] +TRACE | | | | Exit data.lib.docker.stage_user +TRACE | | | Redo data.lib.docker.stage_user +TRACE | | | | Redo users = [cmd | cmd = stage[_]; cmd.Cmd = "user"] +TRACE | | | | Redo stage = input.stages[stage_name] +TRACE | | | Eval count(stage_users, __local537__) +TRACE | | | Eval len = __local537__ +TRACE | | | Eval minus(len, 1, __local538__) +TRACE | | | Eval last = stage_users[__local538__] +TRACE | | | Eval user = last.Value[0] +TRACE | | | Eval user = "root" +TRACE | | | Exit data.builtin.dockerfile.DS002.fail_last_user_root +TRACE | | Redo data.builtin.dockerfile.DS002.fail_last_user_root +TRACE | | | Redo user = "root" +TRACE | | | Redo user = last.Value[0] +TRACE | | | Redo last = stage_users[__local538__] +TRACE | | | Redo minus(len, 1, __local538__) +TRACE | | | Redo len = __local537__ +TRACE | | | Redo count(stage_users, __local537__) +TRACE | | | Redo stage_users = data.lib.docker.stage_user[_] +TRACE | | Eval msg = "Last USER command in Dockerfile should not be 'root'" +TRACE | | Eval data.lib.docker.result(msg, cmd, __local540__) +TRACE | | Index data.lib.docker.result (matched 1 rule) +TRACE | | Enter data.lib.docker.result +TRACE | | | Eval object.get(cmd, "EndLine", 0, __local470__) +TRACE | | | Eval object.get(cmd, "Path", "", __local471__) +TRACE | | | Eval object.get(cmd, "StartLine", 0, __local472__) +TRACE | | | Eval result = {"endline": __local470__, "filepath": __local471__, "msg": msg, "startline": __local472__} +TRACE | | | Exit data.lib.docker.result +TRACE | | Eval res = __local540__ +TRACE | | Exit data.builtin.dockerfile.DS002.deny +TRACE | Redo data.builtin.dockerfile.DS002.deny +TRACE | | Redo res = __local540__ +TRACE | | Redo data.lib.docker.result(msg, cmd, __local540__) +TRACE | | Redo data.lib.docker.result +TRACE | | | Redo result = {"endline": __local470__, "filepath": __local471__, "msg": msg, "startline": __local472__} +TRACE | | | Redo object.get(cmd, "StartLine", 0, __local472__) +TRACE | | | Redo object.get(cmd, "Path", "", __local471__) +TRACE | | | Redo object.get(cmd, "EndLine", 0, __local470__) +TRACE | | Redo msg = "Last USER command in Dockerfile should not be 'root'" +TRACE | | Redo cmd = data.builtin.dockerfile.DS002.fail_last_user_root[_] +TRACE | Exit data.builtin.dockerfile.DS002.deny = _ +TRACE Redo data.builtin.dockerfile.DS002.deny = _ +TRACE | Redo data.builtin.dockerfile.DS002.deny = _ +TRACE ``` \ No newline at end of file diff --git a/docs/docs/misconfiguration/options/filter.md b/docs/docs/misconfiguration/options/filter.md index 0983f31fcc..741463613c 100644 --- a/docs/docs/misconfiguration/options/filter.md +++ b/docs/docs/misconfiguration/options/filter.md @@ -11,202 +11,50 @@ trivy conf --severity HIGH,CRITICAL examples/misconf/mixed
Result -```bash -2021-07-10T17:37:13.267+0300 INFO Detected config files: 4 +```shell +2022-05-16T13:50:42.718+0100 INFO Detected config files: 3 -configs/Dockerfile (dockerfile) -=============================== -Tests: 23 (SUCCESSES: 21, FAILURES: 2, EXCEPTIONS: 0) -Failures: 2 (HIGH: 1, CRITICAL: 0) +Dockerfile (dockerfile) +======================= +Tests: 17 (SUCCESSES: 16, FAILURES: 1, EXCEPTIONS: 0) +Failures: 1 (HIGH: 1, CRITICAL: 0) -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| Dockerfile Security Check | DS002 | Image user is 'root' | HIGH | Specify at least 1 USER | -| | | | | command in Dockerfile with | -| | | | | non-root user as argument | -| | | | | -->avd.aquasec.com/appshield/ds002 | -+---------------------------+------------+----------------------+----------+------------------------------------------+ +HIGH: Last USER command in Dockerfile should not be 'root' +═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile. -configs/deployment.yaml (kubernetes) -==================================== -Tests: 28 (SUCCESSES: 14, FAILURES: 14, EXCEPTIONS: 0) -Failures: 14 (HIGH: 1, CRITICAL: 0) +See https://avd.aquasec.com/misconfig/ds002 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Dockerfile:3 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 3 [ USER root +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── -+---------------------------+------------+-------------------------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+---------------------------+------------+-------------------------------------+----------+------------------------------------------+ -| Kubernetes Security Check | KSV006 | docker.sock is mounted to container | HIGH | Deployment 'hello-kubernetes' should | -| | | | | not specify '/var/run/docker.socker' in | -| | | | | 'spec.template.volumes.hostPath.path' | -| | | | | -->avd.aquasec.com/appshield/ksv006 | -+---------------------------+------------+-------------------------------------+----------+------------------------------------------+ -configs/main.tf (terraform) -=========================== -Tests: 19 (SUCCESSES: 11, FAILURES: 8, EXCEPTIONS: 0) -Failures: 8 (HIGH: 6, CRITICAL: 1) -+------------------------------------------+------------+------------------------------------------+----------+--------------------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+------------------------------------------+------------+------------------------------------------+----------+--------------------------------------------------------+ -| Terraform Security Check powered by | AWS003 | AWS Classic resource usage. | HIGH | Resource | -| tfsec | | | | 'aws_db_security_group.my-group' | -| | | | | uses EC2 Classic. Use a VPC instead. | -| | | | | -->tfsec.dev/docs/aws/AWS003/ | -+ +------------+------------------------------------------+----------+--------------------------------------------------------+ -| | AWS004 | Use of plain HTTP. | CRITICAL | Resource | -| | | | | 'aws_alb_listener.my-alb-listener' | -| | | | | uses plain HTTP instead of HTTPS. | -| | | | | -->tfsec.dev/docs/aws/AWS004/ | -+ +------------+------------------------------------------+----------+--------------------------------------------------------+ -| | AWS018 | Missing description for security | HIGH | Resource | -| | | group/security group rule. | | 'aws_security_group_rule.my-rule' should | -| | | | | include a description for auditing | -| | | | | purposes. -->tfsec.dev/docs/aws/AWS018/ | -+ +------------+------------------------------------------+ +--------------------------------------------------------+ -| | AWS025 | API Gateway domain name uses outdated | | Resource | -| | | SSL/TLS protocols. | | 'aws_api_gateway_domain_name.empty_security_policy' | -| | | | | defines outdated SSL/TLS policies (not using | -| | | | | TLS_1_2). -->tfsec.dev/docs/aws/AWS025/ | -+ + + + +--------------------------------------------------------+ -| | | | | Resource | -| | | | | 'aws_api_gateway_domain_name.missing_security_policy' | -| | | | | should include security_policy (defaults to outdated | -| | | | | SSL/TLS policy). -->tfsec.dev/docs/aws/AWS025/ | -+ + + + +--------------------------------------------------------+ -| | | | | Resource | -| | | | | 'aws_api_gateway_domain_name.outdated_security_policy' | -| | | | | defines outdated SSL/TLS policies (not using TLS_1_2). | -| | | | | -->tfsec.dev/docs/aws/AWS025/ | -+ +------------+------------------------------------------+ +--------------------------------------------------------+ -| | AZU003 | Unencrypted managed disk. | | Resource 'azurerm_managed_disk.source' | -| | | | | defines an unencrypted managed disk. | -| | | | | -->tfsec.dev/docs/azure/AZU003/ | -+------------------------------------------+------------+------------------------------------------+----------+--------------------------------------------------------+ - -configs/variables.tf (terraform) -================================ -Tests: 1 (SUCCESSES: 1, FAILURES: 0, EXCEPTIONS: 0) +deployment.yaml (kubernetes) +============================ +Tests: 8 (SUCCESSES: 8, FAILURES: 0, EXCEPTIONS: 0) Failures: 0 (HIGH: 0, CRITICAL: 0) -``` -
-## By Misconfiguration IDs +main.tf (terraform) +=================== +Tests: 1 (SUCCESSES: 0, FAILURES: 1, EXCEPTIONS: 0) +Failures: 1 (HIGH: 0, CRITICAL: 1) -Use `.trivyignore`. +CRITICAL: Classic resources should not be used. +═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +AWS Classic resources run in a shared environment with infrastructure owned by other AWS customers. You should run +resources in a VPC instead. -```bash -$ cat .trivyignore -# Accept the risk -AWS003 -AWS018 -AWS025 - -$ trivy conf --severity HIGH,CRITICAL examples/misconf/mixed -``` - -
-Result - -```bash -2021-07-10T17:38:51.306+0300 INFO Detected config files: 4 - -configs/Dockerfile (dockerfile) -=============================== -Tests: 23 (SUCCESSES: 21, FAILURES: 2, EXCEPTIONS: 0) -Failures: 2 (HIGH: 1, CRITICAL: 0) - -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| Dockerfile Security Check | DS002 | Image user is 'root' | HIGH | Specify at least 1 USER | -| | | | | command in Dockerfile with | -| | | | | non-root user as argument | -| | | | | -->avd.aquasec.com/appshield/ds002 | -+---------------------------+------------+----------------------+----------+------------------------------------------+ - -configs/deployment.yaml (kubernetes) -==================================== -Tests: 28 (SUCCESSES: 14, FAILURES: 14, EXCEPTIONS: 0) -Failures: 14 (HIGH: 1, CRITICAL: 0) - -+---------------------------+------------+-------------------------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+---------------------------+------------+-------------------------------------+----------+------------------------------------------+ -| Kubernetes Security Check | KSV006 | docker.sock is mounted to container | HIGH | Deployment 'hello-kubernetes' should | -| | | | | not specify '/var/run/docker.socker' in | -| | | | | 'spec.template.volumes.hostPath.path' | -| | | | | -->avd.aquasec.com/appshield/ksv006 | -+---------------------------+------------+-------------------------------------+----------+------------------------------------------+ - -configs/main.tf (terraform) -=========================== -Tests: 19 (SUCCESSES: 11, FAILURES: 8, EXCEPTIONS: 0) -Failures: 8 (HIGH: 1, CRITICAL: 1) - -+------------------------------------------+------------+---------------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+------------------------------------------+------------+---------------------------+----------+------------------------------------------+ -| Terraform Security Check powered by | AWS004 | Use of plain HTTP. | CRITICAL | Resource | -| tfsec | | | | 'aws_alb_listener.my-alb-listener' | -| | | | | uses plain HTTP instead of HTTPS. | -| | | | | -->tfsec.dev/docs/aws/AWS004/ | -+ +------------+---------------------------+----------+------------------------------------------+ -| | AZU003 | Unencrypted managed disk. | HIGH | Resource 'azurerm_managed_disk.source' | -| | | | | defines an unencrypted managed disk. | -| | | | | -->tfsec.dev/docs/azure/AZU003/ | -+------------------------------------------+------------+---------------------------+----------+------------------------------------------+ - -configs/variables.tf (terraform) -================================ -Tests: 1 (SUCCESSES: 1, FAILURES: 0, EXCEPTIONS: 0) -Failures: 0 (HIGH: 0, CRITICAL: 0) -``` - -
- -## By Exceptions -See [Exceptions](../policy/exceptions.md) - -## Show Successes and Exceptions -Use `--include-non-failures` option to show successes and exceptions as well as failures. - -```bash -trivy conf --severity CRITICAL --include-non-failures examples/misconf/mixed -``` - -
-Result -``` -2021-07-10T17:44:02.049+0300 INFO Detected config files: 4 - -configs/Dockerfile (dockerfile) -=============================== -Tests: 23 (SUCCESSES: 21, FAILURES: 2, EXCEPTIONS: 0) -Failures: 2 (CRITICAL: 0) - -+---------------------------+------------+------------------------------------------+----------+--------+-----------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | STATUS | MESSAGE | -+---------------------------+------------+------------------------------------------+----------+--------+-----------------+ -| Dockerfile Security Check | DS006 | COPY '--from' refers to the current | CRITICAL | PASS | No issues found | -| | | image | | | | -+ +------------+------------------------------------------+ + + + -| | DS007 | Multiple ENTRYPOINT instructions are | | | | -| | | listed | | | | -+ +------------+------------------------------------------+ + + + -| | DS008 | Exposed port is out of range | | | | -+ +------------+------------------------------------------+ + + + -| | DS010 | 'sudo' is used | | | | -+ +------------+------------------------------------------+ + + + -| | DS011 | COPY with more than two arguments is not | | | | -| | | ending with slash | | | | -+ +------------+------------------------------------------+ + + + -| | DS012 | Duplicate aliases are defined in | | | | -| | | different FROMs | | | | -+---------------------------+------------+------------------------------------------+----------+--------+-----------------+ - -... +See https://avd.aquasec.com/misconfig/avd-aws-0081 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + main.tf:2-4 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 2 ┌ resource "aws_db_security_group" "sg" { + 3 │ + 4 └ } +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ```
diff --git a/docs/docs/misconfiguration/options/policy.md b/docs/docs/misconfiguration/options/policy.md index 24f8f854d0..4505a1b8ac 100644 --- a/docs/docs/misconfiguration/options/policy.md +++ b/docs/docs/misconfiguration/options/policy.md @@ -33,56 +33,3 @@ This can be repeated for specifying multiple packages. ``` bash trivy conf --policy ./policy --namespaces main --namespaces user ./configs ``` - -## Skip update of built-in policies -`Trivy` downloads built-in policies when it starts operating. -Then, it checks for updates every 24 hours. -You can use the `--skip-policy-update` option to skip it. -If you skip it the first time, the built-in policies will not be loaded. - -!!! note - Even if you specify the option the first time, it will be loaded as Terraform policies are written in Go. - -``` -trivy conf --skip-policy-update examples/misconf/mixed [~/src/github.com/aquasecurity/trivy] - -``` - -
-Result - -``` -2021-07-10T18:04:19.083+0300 INFO No builtin policies were loaded -2021-07-10T18:04:19.174+0300 INFO Detected config files: 2 - -configs/main.tf (terraform) -=========================== -Tests: 19 (SUCCESSES: 11, FAILURES: 8, EXCEPTIONS: 0) -Failures: 8 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 1, CRITICAL: 1) - -+------------------------------------------+------------+------------------------------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+------------------------------------------+------------+------------------------------------------+----------+------------------------------------------+ -| Terraform Security Check powered by | AWS004 | Use of plain HTTP. | CRITICAL | Resource | -| tfsec | | | | 'aws_alb_listener.my-alb-listener' | -| | | | | uses plain HTTP instead of HTTPS. | -| | | | | -->tfsec.dev/docs/aws/AWS004/ | -+ +------------+------------------------------------------+----------+------------------------------------------+ -| | AWS006 | An ingress security group rule allows | MEDIUM | Resource | -| | | traffic from /0. | | 'aws_security_group_rule.my-rule' | -| | | | | defines a fully open | -| | | | | ingress security group rule. | -| | | | | -->tfsec.dev/docs/aws/AWS006/ | -+ +------------+------------------------------------------+----------+------------------------------------------+ -| | AZU003 | Unencrypted managed disk. | HIGH | Resource 'azurerm_managed_disk.source' | -| | | | | defines an unencrypted managed disk. | -| | | | | -->tfsec.dev/docs/azure/AZU003/ | -+------------------------------------------+------------+------------------------------------------+----------+------------------------------------------+ - -configs/variables.tf (terraform) -================================ -Tests: 1 (SUCCESSES: 1, FAILURES: 0, EXCEPTIONS: 0) -Failures: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0) -``` -
- diff --git a/docs/docs/misconfiguration/scanning.md b/docs/docs/misconfiguration/scanning.md index 4f8c0d2a0c..80dd921319 100644 --- a/docs/docs/misconfiguration/scanning.md +++ b/docs/docs/misconfiguration/scanning.md @@ -18,22 +18,23 @@ $ trivy config [YOUR_IaC_DIRECTORY] $ ls build/ Dockerfile $ trivy config ./build - 2021-07-09T10:06:29.188+0300 INFO Need to update the built-in policies - 2021-07-09T10:06:29.188+0300 INFO Downloading the built-in policies... - 2021-07-09T10:06:30.520+0300 INFO Detected config files: 1 + 2022-05-16T13:29:29.952+0100 INFO Detected config files: 1 Dockerfile (dockerfile) ======================= Tests: 23 (SUCCESSES: 22, FAILURES: 1, EXCEPTIONS: 0) - Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) + Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0) - +---------------------------+------------+----------------------+----------+------------------------------------------+ - | TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | - +---------------------------+------------+----------------------+----------+------------------------------------------+ - | Dockerfile Security Check | DS002 | Image user is 'root' | HIGH | Last USER command in | - | | | | | Dockerfile should not be 'root' | - | | | | | -->avd.aquasec.com/appshield/ds002 | - +---------------------------+------------+----------------------+----------+------------------------------------------+ + MEDIUM: Specify a tag in the 'FROM' statement for image 'alpine' + ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ + When using a 'FROM' statement you should use a specific tag to avoid uncontrolled behavior when the image is updated. + + See https://avd.aquasec.com/misconfig/ds001 + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Dockerfile:1 + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 1 [ FROM alpine:latest + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ``` You can also enable misconfiguration detection in container image, filesystem and git repository scanning via `--security-checks config`. @@ -58,35 +59,37 @@ You can specify `--security-checks vuln,config,secret` to enable vulnerability a $ ls myapp/ Dockerfile Pipfile.lock $ trivy fs --security-checks vuln,config,secret --severity HIGH,CRITICAL myapp/ - 2021-07-09T12:03:27.564+0300 INFO Number of language-specific files: 1 - 2021-07-09T12:03:27.564+0300 INFO Detecting pipenv vulnerabilities... - 2021-07-09T12:03:27.566+0300 INFO Detected config files: 1 + 2022-05-16T13:42:21.440+0100 INFO Number of language-specific files: 1 + 2022-05-16T13:42:21.440+0100 INFO Detecting pipenv vulnerabilities... + 2022-05-16T13:42:21.440+0100 INFO Detected config files: 1 Pipfile.lock (pipenv) ===================== Total: 1 (HIGH: 1, CRITICAL: 0) - +----------+------------------+----------+-------------------+---------------+---------------------------------------+ - | LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION | TITLE | - +----------+------------------+----------+-------------------+---------------+---------------------------------------+ - | httplib2 | CVE-2021-21240 | HIGH | 0.12.1 | 0.19.0 | python-httplib2: Regular | - | | | | | | expression denial of | - | | | | | | service via malicious header | - | | | | | | -->avd.aquasec.com/nvd/cve-2021-21240 | - +----------+------------------+----------+-------------------+---------------+---------------------------------------+ + ┌──────────┬────────────────┬──────────┬───────────────────┬───────────────┬───────────────────────────────────────────────────────────┐ + │ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │ + ├──────────┼────────────────┼──────────┼───────────────────┼───────────────┼───────────────────────────────────────────────────────────┤ + │ httplib2 │ CVE-2021-21240 │ HIGH │ 0.12.1 │ 0.19.0 │ python-httplib2: Regular expression denial of service via │ + │ │ │ │ │ │ malicious header │ + │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-21240 │ + └──────────┴────────────────┴──────────┴───────────────────┴───────────────┴───────────────────────────────────────────────────────────┘ Dockerfile (dockerfile) ======================= - Tests: 23 (SUCCESSES: 22, FAILURES: 1, EXCEPTIONS: 0) + Tests: 17 (SUCCESSES: 16, FAILURES: 1, EXCEPTIONS: 0) Failures: 1 (HIGH: 1, CRITICAL: 0) - +---------------------------+------------+----------------------+----------+------------------------------------------+ - | TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | - +---------------------------+------------+----------------------+----------+------------------------------------------+ - | Dockerfile Security Check | DS002 | Image user is 'root' | HIGH | Last USER command in | - | | | | | Dockerfile should not be 'root' | - | | | | | -->avd.aquasec.com/appshield/ds002 | - +---------------------------+------------+----------------------+----------+------------------------------------------+ + HIGH: Last USER command in Dockerfile should not be 'root' + ════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ + Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile. + + See https://avd.aquasec.com/misconfig/ds002 + ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Dockerfile:3 + ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 3 [ USER root + ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ``` In the above example, Trivy detected vulnerabilities of Python dependencies and misconfigurations in Dockerfile. @@ -107,83 +110,53 @@ $ trivy conf --severity HIGH,CRITICAL ./iac Result ``` -2021-07-09T11:51:08.212+0300 INFO Need to update the built-in policies -2021-07-09T11:51:08.212+0300 INFO Downloading the built-in policies... -2021-07-09T11:51:09.527+0300 INFO Detected config files: 3 +2022-05-16T13:46:31.115+0100 INFO Detected config files: 3 Dockerfile (dockerfile) ======================= -Tests: 23 (SUCCESSES: 22, FAILURES: 1, EXCEPTIONS: 0) +Tests: 17 (SUCCESSES: 16, FAILURES: 1, EXCEPTIONS: 0) Failures: 1 (HIGH: 1, CRITICAL: 0) -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| Dockerfile Security Check | DS002 | Image user is 'root' | HIGH | Last USER command in | -| | | | | Dockerfile should not be 'root' | -| | | | | -->avd.aquasec.com/appshield/ds002 | -+---------------------------+------------+----------------------+----------+------------------------------------------+ +HIGH: Last USER command in Dockerfile should not be 'root' +═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile. + +See https://avd.aquasec.com/misconfig/ds002 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Dockerfile:3 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 3 [ USER root +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + deployment.yaml (kubernetes) ============================ -Tests: 28 (SUCCESSES: 15, FAILURES: 13, EXCEPTIONS: 0) -Failures: 13 (HIGH: 1, CRITICAL: 0) +Tests: 8 (SUCCESSES: 8, FAILURES: 0, EXCEPTIONS: 0) +Failures: 0 (HIGH: 0, CRITICAL: 0) -+---------------------------+------------+----------------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+---------------------------+------------+----------------------------+----------+------------------------------------------+ -| Kubernetes Security Check | KSV005 | SYS_ADMIN capability added | HIGH | Container 'hello-kubernetes' of | -| | | | | Deployment 'hello-kubernetes' | -| | | | | should not include 'SYS_ADMIN' in | -| | | | | 'securityContext.capabilities.add' | -| | | | | -->avd.aquasec.com/appshield/ksv005 | -+---------------------------+------------+----------------------------+----------+------------------------------------------+ main.tf (terraform) =================== -Tests: 23 (SUCCESSES: 14, FAILURES: 9, EXCEPTIONS: 0) -Failures: 9 (HIGH: 6, CRITICAL: 1) +Tests: 1 (SUCCESSES: 0, FAILURES: 1, EXCEPTIONS: 0) +Failures: 1 (HIGH: 0, CRITICAL: 1) -+------------------------------------------+------------+------------------------------------------+----------+--------------------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+------------------------------------------+------------+------------------------------------------+----------+--------------------------------------------------------+ -| Terraform Security Check powered by | AWS003 | AWS Classic resource usage. | HIGH | Resource | -| tfsec | | | | 'aws_db_security_group.my-group' | -| | | | | uses EC2 Classic. Use a VPC instead. | -| | | | | -->tfsec.dev/docs/aws/AWS003/ | -+ +------------+------------------------------------------+----------+--------------------------------------------------------+ -| | AWS004 | Use of plain HTTP. | CRITICAL | Resource | -| | | | | 'aws_alb_listener.my-alb-listener' | -| | | | | uses plain HTTP instead of HTTPS. | -| | | | | -->tfsec.dev/docs/aws/AWS004/ | -+ +------------+------------------------------------------+----------+--------------------------------------------------------+ -| | AWS018 | Missing description for security | HIGH | Resource | -| | | group/security group rule. | | 'aws_security_group_rule.my-rule' should | -| | | | | include a description for auditing | -| | | | | purposes. -->tfsec.dev/docs/aws/AWS018/ | -+ +------------+------------------------------------------+ +--------------------------------------------------------+ -| | AWS025 | API Gateway domain name uses outdated | | Resource | -| | | SSL/TLS protocols. | | 'aws_api_gateway_domain_name.empty_security_policy' | -| | | | | defines outdated SSL/TLS policies (not using | -| | | | | TLS_1_2). -->tfsec.dev/docs/aws/AWS025/ | -+ + + + +--------------------------------------------------------+ -| | | | | Resource | -| | | | | 'aws_api_gateway_domain_name.missing_security_policy' | -| | | | | should include security_policy (defaults to outdated | -| | | | | SSL/TLS policy). -->tfsec.dev/docs/aws/AWS025/ | -+ + + + +--------------------------------------------------------+ -| | | | | Resource | -| | | | | 'aws_api_gateway_domain_name.outdated_security_policy' | -| | | | | defines outdated SSL/TLS policies (not using TLS_1_2). | -| | | | | -->tfsec.dev/docs/aws/AWS025/ | -+ +------------+------------------------------------------+ +--------------------------------------------------------+ -| | AZU003 | Unencrypted managed disk. | | Resource 'azurerm_managed_disk.source' | -| | | | | defines an unencrypted managed disk. | -| | | | | -->tfsec.dev/docs/azure/AZU003/ | -+------------------------------------------+------------+------------------------------------------+----------+--------------------------------------------------------+ +CRITICAL: Classic resources should not be used. +═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +AWS Classic resources run in a shared environment with infrastructure owned by other AWS customers. You should run +resources in a VPC instead. + +See https://avd.aquasec.com/misconfig/avd-aws-0081 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + main.tf:2-4 +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 2 ┌ resource "aws_db_security_group" "sg" { + 3 │ + 4 └ } +─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ``` - + You can see the config type next to each file name. diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index 3cf1f985c6..e5d3f14fc1 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -12,35 +12,35 @@ For example: ``` shell $ trivy image myimage:1.0.0 -2022-04-21T18:56:44.099+0300 INFO Detected OS: alpine -2022-04-21T18:56:44.099+0300 INFO Detecting Alpine vulnerabilities... -2022-04-21T18:56:44.101+0300 INFO Number of language-specific files: 0 +2022-05-16T13:25:17.826+0100 INFO Detected OS: alpine +2022-05-16T13:25:17.826+0100 INFO Detecting Alpine vulnerabilities... +2022-05-16T13:25:17.826+0100 INFO Number of language-specific files: 0 -myimage:1.0.0 (alpine 3.15.0) -============================= -Total: 6 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2) +myimage:1.0.0 (alpine 3.15.3) -+--------------+------------------+----------+-------------------+---------------+---------------------------------------+ -| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION | TITLE | -+--------------+------------------+----------+-------------------+---------------+---------------------------------------+ -| busybox | CVE-2022-28391 | CRITICAL | 1.34.1-r3 | 1.34.1-r5 | CVE-2022-28391 affecting | -| | | | | | package busybox 1.35.0 | -| | | | | | -->avd.aquasec.com/nvd/cve-2022-28391 | -+--------------+------------------| |-------------------+---------------+---------------------------------------+ -| ssl_client | CVE-2022-28391 | | 1.34.1-r3 | 1.34.1-r5 | CVE-2022-28391 affecting | -| | | | | | package busybox 1.35.0 | -| | | | | | -->avd.aquasec.com/nvd/cve-2022-28391 | -+--------------+------------------+----------+-------------------+---------------+---------------------------------------+ +Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2) + +┌────────────┬────────────────┬──────────┬───────────────────┬───────────────┬─────────────────────────────────────────────────────────┐ +│ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │ +├────────────┼────────────────┼──────────┼───────────────────┼───────────────┼─────────────────────────────────────────────────────────┤ +│ busybox │ CVE-2022-28391 │ CRITICAL │ 1.34.1-r4 │ 1.34.1-r5 │ busybox: remote attackers may execute arbitrary code if │ +│ │ │ │ │ │ netstat is used │ +│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2022-28391 │ +├────────────┤ │ │ │ │ │ +│ ssl_client │ │ │ │ │ │ +│ │ │ │ │ │ │ +│ │ │ │ │ │ │ +└────────────┴────────────────┴──────────┴───────────────────┴───────────────┴─────────────────────────────────────────────────────────┘ app/deploy.sh (secrets) -======================= + Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 1) -+----------+-------------------+----------+---------+--------------------------------+ -| CATEGORY | DESCRIPTION | SEVERITY | LINE NO | MATCH | -+----------+-------------------+----------+---------+--------------------------------+ -| AWS | AWS Access Key ID | CRITICAL | 10 | export AWS_ACCESS_KEY_ID=***** | -+----------+-------------------+----------+---------+--------------------------------+ +┌──────────┬───────────────────┬──────────┬─────────┬────────────────────────────────┐ +│ Category │ Description │ Severity │ Line No │ Match │ +├──────────┼───────────────────┼──────────┼─────────┼────────────────────────────────┤ +│ AWS │ AWS Access Key ID │ CRITICAL │ 3 │ export AWS_ACCESS_KEY_ID=***** │ +└──────────┴───────────────────┴──────────┴─────────┴────────────────────────────────┘ ``` For more details, see [vulnerability][vulnerability] and [secret][secret] pages. @@ -59,22 +59,23 @@ For example: $ ls build/ Dockerfile $ trivy config ./build -2021-07-09T10:06:29.188+0300 INFO Need to update the built-in policies -2021-07-09T10:06:29.188+0300 INFO Downloading the built-in policies... -2021-07-09T10:06:30.520+0300 INFO Detected config files: 1 +2022-05-16T13:29:29.952+0100 INFO Detected config files: 1 Dockerfile (dockerfile) ======================= Tests: 23 (SUCCESSES: 22, FAILURES: 1, EXCEPTIONS: 0) -Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) +Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0) -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE | -+---------------------------+------------+----------------------+----------+------------------------------------------+ -| Dockerfile Security Check | DS002 | Image user is 'root' | HIGH | Last USER command in | -| | | | | Dockerfile should not be 'root' | -| | | | | -->avd.aquasec.com/appshield/ds002 | -+---------------------------+------------+----------------------+----------+------------------------------------------+ +MEDIUM: Specify a tag in the 'FROM' statement for image 'alpine' +══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +When using a 'FROM' statement you should use a specific tag to avoid uncontrolled behavior when the image is updated. + +See https://avd.aquasec.com/misconfig/ds001 +────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Dockerfile:1 +────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + 1 [ FROM alpine:latest +────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ``` For more details, see [here][misconf].