# Debugging checks When working on more complex queries (or when learning Rego), it's useful to see exactly how the policy is applied. For this purpose you can use the `--trace-rego` flag. This will output a large trace from Open Policy Agent like the following: !!! tip Only failed checks show traces. If you want to debug a passed check, you need to make it fail on purpose. ```shell $ trivy config --trace-rego configs/ 2022-05-16T13:47:58.853+0100 INFO Detected config files: 1 Dockerfile (dockerfile) ======================= Tests: 23 (SUCCESSES: 21, FAILURES: 2) 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 ID: DS002 File: Dockerfile Namespace: builtin.dockerfile.DS002 Query: data.builtin.dockerfile.DS002.deny Message: Last USER command in Dockerfile should not be 'root' 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 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 | | | | | Exit 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 username = user.Value[_] 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 | | | 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 ```