From 1d2b4f8e9f4e7ba98f4b101c2eef5af08ba46449 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Mon, 23 Mar 2026 16:37:29 +0000 Subject: [PATCH 1/4] First tests --- assets/libraries/dockerfile.rego | 5 +++++ .../queries/dockerfile/missing_user_instruction/query.rego | 6 ++++-- pkg/parser/docker/parser.go | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/assets/libraries/dockerfile.rego b/assets/libraries/dockerfile.rego index 1ef6f6244f2..98990ee5a6e 100644 --- a/assets/libraries/dockerfile.rego +++ b/assets/libraries/dockerfile.rego @@ -70,3 +70,8 @@ check_multi_stage(imageName, images) { sortedIndex := sort(unsortedIndex) imageName == sortedIndex[minus(count(sortedIndex), 1)].Name } + +get_original_from_command(commands) = from_command { + commands[i].Cmd == "from" + from_command := substring(commands[i].Original, 0, 4) +} diff --git a/assets/queries/dockerfile/missing_user_instruction/query.rego b/assets/queries/dockerfile/missing_user_instruction/query.rego index 51913455708..19c41a7312d 100644 --- a/assets/queries/dockerfile/missing_user_instruction/query.rego +++ b/assets/queries/dockerfile/missing_user_instruction/query.rego @@ -9,12 +9,14 @@ CxPolicy[result] { not name == "scratch" not has_user_instruction(resource) + from_command := dockerLib.get_original_from_command(resource) + result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}", [name]), + "searchKey": sprintf("%s={{%s}}", [from_command, name]), "issueType": "MissingAttribute", "keyExpectedValue": "The 'Dockerfile' should contain the 'USER' instruction", - "keyActualValue": "The 'Dockerfile' does not contain any 'USER' instruction", + "keyActualValue": "The 'Dockerfile' does not contain any 'USER' instruction" } } diff --git a/pkg/parser/docker/parser.go b/pkg/parser/docker/parser.go index 7f97835b07e..82b860308e1 100644 --- a/pkg/parser/docker/parser.go +++ b/pkg/parser/docker/parser.go @@ -59,7 +59,7 @@ func (p *Parser) Parse(_ string, fileContent []byte) ([]model.Document, []int, e for _, child := range parsed.AST.Children { child.Value = strings.ToLower(child.Value) if child.Value == "from" { - fromValue = strings.TrimPrefix(child.Original, "FROM ") + fromValue = child.Original[5:] } if ignoreStruct.getIgnoreComments(child) { From 14154b2cdf24f207b6630f5a1aadbc481b86d0d6 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Mon, 23 Mar 2026 18:26:03 +0000 Subject: [PATCH 2/4] First commit with changes to all dockerfile queries for case insesitivity support + tests --- .../dockerfile/add_instead_of_copy/query.rego | 4 +- .../test/negative2.dockerfile | 10 + .../test/positive2.dockerfile | 9 + .../test/positive_expected_result.json | 19 +- .../apk_add_using_local_cache_path/query.rego | 4 +- .../test/negative3.dockerfile | 7 + .../test/positive3.dockerfile | 7 + .../test/positive_expected_result.json | 8 +- .../query.rego | 6 +- .../test/negative3.dockerfile | 15 ++ .../test/positive3.dockerfile | 14 ++ .../test/positive_expected_result.json | 86 +++++--- .../query.rego | 8 +- .../test/negative4.dockerfile | 2 + .../test/positive3.dockerfile | 14 ++ .../test/positive_expected_result.json | 48 +++++ .../query.rego | 6 +- .../test/negative9.dockerfile | 4 + .../test/positive8.dockerfile | 4 + .../test/positive_expected_result.json | 198 ++++++++++-------- .../query.rego | 8 +- .../test/negative2.dockerfile | 4 + .../test/positive2.dockerfile | 3 + .../test/positive_expected_result.json | 20 +- .../query.rego | 9 +- .../test/negative5.dockerfile | 11 + .../test/positive3.dockerfile | 11 + .../test/positive_expected_result.json | 8 +- .../dockerfile/chown_flag_exists/query.rego | 5 +- .../test/negative2.dockerfile | 7 + .../test/positive2.dockerfile | 7 + .../test/positive_expected_result.json | 19 +- .../query.rego | 6 +- .../test/negative2.dockerfile | 12 ++ .../test/positive2.dockerfile | 3 + .../test/positive_expected_result.json | 17 +- .../query.rego | 6 +- .../test/negative3.dockerfile | 2 + .../test/positive2.dockerfile | 2 + .../test/positive_expected_result.json | 18 +- .../curl_or_wget_instead_of_add/query.rego | 6 +- .../test/negative3.dockerfile | 5 + .../test/positive2.dockerfile | 5 + .../test/positive_expected_result.json | 19 +- .../dockerfile/exposing_port_22/query.rego | 6 +- .../test/negative2.dockerfile | 4 + .../test/positive2.dockerfile | 4 + .../test/positive_expected_result.json | 19 +- .../gem_install_without_version/query.rego | 8 +- .../test/negative2.dockerfile | 13 ++ .../test/positive2.dockerfile | 12 ++ .../test/positive_expected_result.json | 53 +++-- .../query.rego | 3 +- .../test/negative3.dockerfile | 8 + .../test/positive3.dockerfile | 7 + .../test/positive_expected_result.json | 8 +- .../image_version_not_explicit/query.rego | 6 +- .../test/negative5.dockerfile | 11 + .../test/positive5.dockerfile | 9 + .../test/positive_expected_result.json | 8 +- .../image_version_using_latest/query.rego | 6 +- .../test/negative2.dockerfile | 9 + .../test/positive2.dockerfile | 9 + .../test/positive_expected_result.json | 11 +- .../dockerfile/last_user_is_root/query.rego | 3 +- .../test/negative3.dockerfile | 4 + .../test/positive2.dockerfile | 3 + .../test/positive_expected_result.json | 17 +- .../query.rego | 6 +- .../test/negative2.dockerfile | 10 + .../test/positive2.dockerfile | 10 + .../test/positive_expected_result.json | 11 +- .../missing_dnf_clean_all/query.rego | 4 +- .../test/negative3.dockerfile | 7 + .../test/positive2.dockerfile | 6 + .../test/positive_expected_result.json | 17 +- .../missing_flag_from_dnf_install/query.rego | 4 +- .../test/negative5.dockerfile | 5 + .../test/positive5.dockerfile | 11 + .../test/positive_expected_result.json | 84 ++++---- .../test/negative4.dockerfile | 14 ++ .../test/positive3.dockerfile | 6 + .../test/positive_expected_result.json | 8 +- .../query.rego | 8 +- .../test/negative2.dockerfile | 6 + .../test/positive2.dockerfile | 6 + .../test/positive_expected_result.json | 30 ++- .../missing_zypper_clean/query.rego | 3 +- .../test/negative3.dockerfile | 3 + .../test/positive2.dockerfile | 3 + .../test/positive_expected_result.json | 17 +- .../query.rego | 3 +- .../test/negative3.dockerfile | 3 + .../test/positive2.dockerfile | 3 + .../test/positive_expected_result.json | 11 +- .../query.rego | 3 +- .../test/negative3.dockerfile | 12 ++ .../test/positive2.dockerfile | 12 ++ .../test/positive_expected_result.json | 18 +- .../query.rego | 3 +- .../test/negative3.dockerfile | 12 ++ .../test/positive2.dockerfile | 12 ++ .../test/positive_expected_result.json | 18 +- .../query.rego | 3 +- .../test/negative6.dockerfile | 2 + .../test/positive4.dockerfile | 6 + .../test/positive_expected_result.json | 44 ++-- .../query.rego | 8 +- .../test/negative3.dockerfile | 11 + .../test/positive2.dockerfile | 11 + .../test/positive_expected_result.json | 20 +- .../query.rego | 6 +- .../test/negative2.dockerfile | 11 + .../test/positive2.dockerfile | 8 + .../test/positive_expected_result.json | 126 +++++++---- .../query.rego | 8 +- .../test/negative2.dockerfile | 7 + .../test/positive2.dockerfile | 12 ++ .../test/positive_expected_result.json | 61 +++--- .../query.rego | 6 +- .../test/negative3.dockerfile | 5 + .../test/positive2.dockerfile | 17 ++ .../test/positive_expected_result.json | 59 ++++-- .../dockerfile/run_using_apt/query.rego | 5 +- .../run_using_apt/test/negative2.dockerfile | 3 + .../run_using_apt/test/positive2.dockerfile | 3 + .../test/positive_expected_result.json | 17 +- .../dockerfile/run_using_sudo/query.rego | 8 +- .../run_using_sudo/test/negative2.dockerfile | 10 + .../run_using_sudo/test/positive2.dockerfile | 9 + .../test/positive_expected_result.json | 17 +- .../run_using_wget_and_curl/query.rego | 3 +- .../test/negative2.dockerfile | 4 + .../test/positive2.dockerfile | 8 + .../test/positive_expected_result.json | 51 +++-- .../query.rego | 6 +- .../test/negative2.dockerfile | 8 + .../test/positive2.dockerfile | 6 + .../test/positive_expected_result.json | 36 +++- .../same_alias_in_different_froms/query.rego | 5 +- .../test/negative2.dockerfile | 5 + .../test/positive2.dockerfile | 8 + .../test/positive_expected_result.json | 16 +- .../query.rego | 7 +- .../test/negative2.dockerfile | 7 + .../test/positive2.dockerfile | 3 + .../test/positive_expected_result.json | 34 ++- .../unix_ports_out_of_range/query.rego | 6 +- .../test/negative2.dockerfile | 4 + .../test/positive2.dockerfile | 4 + .../test/positive_expected_result.json | 17 +- .../query.rego | 16 +- .../test/negative3.dockerfile | 20 ++ .../test/positive2.dockerfile | 25 +++ .../test/positive_expected_result.json | 87 +++++--- .../query.rego | 8 +- .../test/negative4.dockerfile | 20 ++ .../test/positive2.dockerfile | 22 ++ .../test/positive_expected_result.json | 74 ++++--- .../update_instruction_alone/query.rego | 8 +- .../test/negative12.dockerfile | 8 + .../test/positive8.dockerfile | 5 + .../test/positive_expected_result.json | 90 ++++---- .../using_platform_with_from/query.rego | 9 +- .../test/negative2.dockerfile | 6 + .../test/positive2.dockerfile | 6 + .../test/positive_expected_result.json | 18 +- .../using_unnamed_build_stages/query.rego | 6 +- .../test/negative2.dockerfile | 12 ++ .../test/positive2.dockerfile | 11 + .../test/positive_expected_result.json | 8 +- .../workdir_path_not_absolute/query.rego | 6 +- .../test/negative2.dockerfile | 17 ++ .../test/positive2.dockerfile | 11 + .../test/positive_expected_result.json | 17 +- .../yum_clean_all_missing/query.rego | 4 +- .../test/negative3.dockerfile | 14 ++ .../test/positive2.dockerfile | 13 ++ .../test/positive_expected_result.json | 18 +- .../query.rego | 8 +- .../test/negative2.dockerfile | 9 + .../test/positive2.dockerfile | 10 + .../test/positive_expected_result.json | 34 ++- .../yum_install_without_version/query.rego | 8 +- .../test/negative2.dockerfile | 8 + .../test/positive2.dockerfile | 4 + .../test/positive_expected_result.json | 36 +++- .../zypper_install_without_version/query.rego | 8 +- .../test/negative2.dockerfile | 3 + .../test/positive2.dockerfile | 4 + .../test/positive_expected_result.json | 34 ++- 191 files changed, 2150 insertions(+), 632 deletions(-) create mode 100644 assets/queries/dockerfile/add_instead_of_copy/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/add_instead_of_copy/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/apk_add_using_local_cache_path/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/apk_add_using_local_cache_path/test/positive3.dockerfile create mode 100644 assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive3.dockerfile create mode 100644 assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/negative4.dockerfile create mode 100644 assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/positive3.dockerfile create mode 100644 assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/negative9.dockerfile create mode 100644 assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/positive8.dockerfile create mode 100644 assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/changing_default_shell_using_run_command/test/negative5.dockerfile create mode 100644 assets/queries/dockerfile/changing_default_shell_using_run_command/test/positive3.dockerfile create mode 100644 assets/queries/dockerfile/chown_flag_exists/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/chown_flag_exists/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/copy_from_references_current_from_alias/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/copy_from_references_current_from_alias/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/curl_or_wget_instead_of_add/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/curl_or_wget_instead_of_add/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/exposing_port_22/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/exposing_port_22/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/gem_install_without_version/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/gem_install_without_version/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/healthcheck_instruction_missing/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/healthcheck_instruction_missing/test/positive3.dockerfile create mode 100644 assets/queries/dockerfile/image_version_not_explicit/test/negative5.dockerfile create mode 100644 assets/queries/dockerfile/image_version_not_explicit/test/positive5.dockerfile create mode 100644 assets/queries/dockerfile/image_version_using_latest/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/image_version_using_latest/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/last_user_is_root/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/last_user_is_root/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/maintainer_instruction_being_used/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/maintainer_instruction_being_used/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/missing_dnf_clean_all/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/missing_dnf_clean_all/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/missing_flag_from_dnf_install/test/negative5.dockerfile create mode 100644 assets/queries/dockerfile/missing_flag_from_dnf_install/test/positive5.dockerfile create mode 100644 assets/queries/dockerfile/missing_user_instruction/test/negative4.dockerfile create mode 100644 assets/queries/dockerfile/missing_user_instruction/test/positive3.dockerfile create mode 100644 assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/missing_zypper_clean/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/missing_zypper_clean/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/multiple_cmd_instructions_listed/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/multiple_cmd_instructions_listed/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/negative6.dockerfile create mode 100644 assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/positive4.dockerfile create mode 100644 assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/npm_install_without_pinned_version/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/npm_install_without_pinned_version/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/pip_install_keeping_cached_packages/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/run_using_apt/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/run_using_apt/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/run_using_sudo/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/run_using_sudo/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/run_using_wget_and_curl/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/run_using_wget_and_curl/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/run_utilities_and_posix_commands/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/run_utilities_and_posix_commands/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/same_alias_in_different_froms/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/same_alias_in_different_froms/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/unix_ports_out_of_range/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/unix_ports_out_of_range/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/negative4.dockerfile create mode 100644 assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative12.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive8.dockerfile create mode 100644 assets/queries/dockerfile/using_platform_with_from/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/using_platform_with_from/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/using_unnamed_build_stages/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/using_unnamed_build_stages/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/workdir_path_not_absolute/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/workdir_path_not_absolute/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/yum_clean_all_missing/test/negative3.dockerfile create mode 100644 assets/queries/dockerfile/yum_clean_all_missing/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/yum_install_allows_manual_input/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/yum_install_allows_manual_input/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/yum_install_without_version/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/yum_install_without_version/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/zypper_install_without_version/test/negative2.dockerfile create mode 100644 assets/queries/dockerfile/zypper_install_without_version/test/positive2.dockerfile diff --git a/assets/queries/dockerfile/add_instead_of_copy/query.rego b/assets/queries/dockerfile/add_instead_of_copy/query.rego index add0d6e9153..509e17f14b6 100644 --- a/assets/queries/dockerfile/add_instead_of_copy/query.rego +++ b/assets/queries/dockerfile/add_instead_of_copy/query.rego @@ -8,9 +8,11 @@ CxPolicy[result] { not dockerLib.arrayContains(resource.Value, {".tar", ".tar."}) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("'COPY' %s", [resource.Value[0]]), "keyActualValue": sprintf("'ADD' %s", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/add_instead_of_copy/test/negative2.dockerfile b/assets/queries/dockerfile/add_instead_of_copy/test/negative2.dockerfile new file mode 100644 index 00000000000..b9ed2bb2d3a --- /dev/null +++ b/assets/queries/dockerfile/add_instead_of_copy/test/negative2.dockerfile @@ -0,0 +1,10 @@ +from openjdk:10-jdk +volume /tmp +arg JAR_FILE +copy ${JAR_FILE} app.jar +entrypoint ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] +add http://source.file/package.file.tar.gz /temp +run tar -xjf /temp/package.file.tar.gz \ + && make -C /tmp/package.file \ + && rm /tmp/ package.file.tar.gz +# trigger validation diff --git a/assets/queries/dockerfile/add_instead_of_copy/test/positive2.dockerfile b/assets/queries/dockerfile/add_instead_of_copy/test/positive2.dockerfile new file mode 100644 index 00000000000..2f1a27bb786 --- /dev/null +++ b/assets/queries/dockerfile/add_instead_of_copy/test/positive2.dockerfile @@ -0,0 +1,9 @@ +from openjdk:10-jdk +volume /tmp +add http://source.file/package.file.tar.gz /temp +run tar -xjf /temp/package.file.tar.gz \ + && make -C /tmp/package.file \ + && rm /tmp/ package.file.tar.gz +arg JAR_FILE +add ${JAR_FILE} app.jar +entrypoint ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] diff --git a/assets/queries/dockerfile/add_instead_of_copy/test/positive_expected_result.json b/assets/queries/dockerfile/add_instead_of_copy/test/positive_expected_result.json index 7e9efb25dd7..264f5b98a6b 100644 --- a/assets/queries/dockerfile/add_instead_of_copy/test/positive_expected_result.json +++ b/assets/queries/dockerfile/add_instead_of_copy/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Add Instead of Copy", - "severity": "MEDIUM", - "line": 8 - } -] + { + "queryName": "Add Instead of Copy", + "severity": "MEDIUM", + "line": 8, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Add Instead of Copy", + "severity": "MEDIUM", + "line": 8, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/apk_add_using_local_cache_path/query.rego b/assets/queries/dockerfile/apk_add_using_local_cache_path/query.rego index 080ce74aab4..07e155d0847 100644 --- a/assets/queries/dockerfile/apk_add_using_local_cache_path/query.rego +++ b/assets/queries/dockerfile/apk_add_using_local_cache_path/query.rego @@ -10,9 +10,11 @@ CxPolicy[result] { runCommands := dockerLib.getCommands(command.Value[0]) containsApkAddWithoutNoCache(runCommands) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, command.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, command.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "'RUN' should not contain 'apk add' command without '--no-cache' switch", "keyActualValue": "'RUN' contains 'apk add' command without '--no-cache' switch", diff --git a/assets/queries/dockerfile/apk_add_using_local_cache_path/test/negative3.dockerfile b/assets/queries/dockerfile/apk_add_using_local_cache_path/test/negative3.dockerfile new file mode 100644 index 00000000000..0d45df135fd --- /dev/null +++ b/assets/queries/dockerfile/apk_add_using_local_cache_path/test/negative3.dockerfile @@ -0,0 +1,7 @@ +from gliderlabs/alpine:3.3 +run apk add --no-cache python +workdir /app +onbuild COPY . /app +onbuild RUN virtualenv /env && /env/bin/pip install -r /app/requirements.txt +expose 8080 +cmd ["/env/bin/python", "main.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/apk_add_using_local_cache_path/test/positive3.dockerfile b/assets/queries/dockerfile/apk_add_using_local_cache_path/test/positive3.dockerfile new file mode 100644 index 00000000000..767cb6d1e26 --- /dev/null +++ b/assets/queries/dockerfile/apk_add_using_local_cache_path/test/positive3.dockerfile @@ -0,0 +1,7 @@ +from gliderlabs/alpine:3.3 +run apk add --update-cache python +workdir /app +onbuild COPY . /app +onbuild RUN virtualenv /env && /env/bin/pip install -r /app/requirements.txt +expose 8080 +cmd ["/env/bin/python", "main.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/apk_add_using_local_cache_path/test/positive_expected_result.json b/assets/queries/dockerfile/apk_add_using_local_cache_path/test/positive_expected_result.json index ab094181dbb..2cf0bb0d814 100644 --- a/assets/queries/dockerfile/apk_add_using_local_cache_path/test/positive_expected_result.json +++ b/assets/queries/dockerfile/apk_add_using_local_cache_path/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "INFO", "line": 2, "fileName": "positive2.dockerfile" + }, + { + "queryName": "Apk Add Using Local Cache Path", + "severity": "INFO", + "line": 2, + "fileName": "positive3.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/query.rego b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/query.rego index f39c4336de0..428a344be3f 100644 --- a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/query.rego +++ b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "run" @@ -10,9 +12,11 @@ CxPolicy[result] { not hasClean(resource.Value[0], aptGet[0]) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, commands]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, commands]), "issueType": "IncorrectValue", #"MissingAttribute" / "RedundantAttribute" "keyExpectedValue": "After using apt-get install, the apt-get lists should be deleted", "keyActualValue": "After using apt-get install, the apt-get lists were not deleted", diff --git a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/negative3.dockerfile b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/negative3.dockerfile new file mode 100644 index 00000000000..defd66e3610 --- /dev/null +++ b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/negative3.dockerfile @@ -0,0 +1,15 @@ +from busyboxneg1 +run apt-get update && apt-get install --no-install-recommends -y python \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +from busyboxneg2 +run apt-get update && apt-get install --no-install-recommends -y python && apt-get clean + +from busyboxneg3 +run apt-get update && apt-get install --no-install-recommends -y python \ + && apt-get clean + +from busyboxneg4 +run apt-get update && apt-get install --no-install-recommends -y python \ + && rm -rf /var/lib/apt/lists/* diff --git a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive3.dockerfile b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive3.dockerfile new file mode 100644 index 00000000000..bc2347439ef --- /dev/null +++ b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive3.dockerfile @@ -0,0 +1,14 @@ +from busybox1 +run apt-get update && apt-get install --no-install-recommends -y python + +from busybox2 +run apt-get install python + +from busybox3 +run apt-get update && apt-get install --no-install-recommends -y python +run rm -rf /var/lib/apt/lists/* + +from busybox4 +run apt-get update && apt-get install --no-install-recommends -y python +run rm -rf /var/lib/apt/lists/* +run apt-get clean diff --git a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive_expected_result.json b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive_expected_result.json index ab1370df2dd..2428b814a66 100644 --- a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive_expected_result.json +++ b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive_expected_result.json @@ -1,32 +1,56 @@ [ - { - "queryName": "Apt Get Install Lists Were Not Deleted", - "severity": "INFO", - "line": 2, - "fileName": "positive.dockerfile" - }, - { - "queryName": "Apt Get Install Lists Were Not Deleted", - "severity": "INFO", - "line": 5, - "fileName": "positive.dockerfile" - }, - { - "queryName": "Apt Get Install Lists Were Not Deleted", - "severity": "INFO", - "line": 8, - "fileName": "positive.dockerfile" - }, - { - "queryName": "Apt Get Install Lists Were Not Deleted", - "severity": "INFO", - "line": 12, - "fileName": "positive.dockerfile" - }, - { - "queryName": "Apt Get Install Lists Were Not Deleted", - "severity": "INFO", - "line": 2, - "fileName": "positive2.dockerfile" - } -] + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 5, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 8, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 12, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 2, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 5, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 8, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 12, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Apt Get Install Lists Were Not Deleted", + "severity": "INFO", + "line": 2, + "fileName": "positive3.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/query.rego b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/query.rego index f1637cf3309..9c8d8e73543 100644 --- a/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/query.rego +++ b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/query.rego @@ -18,9 +18,11 @@ CxPolicy[result] { packageName := packages[j] analyzePackages(j, packageName, packages, length) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, commands]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, commands]), "searchValue": packageName, "issueType": "MissingAttribute", "keyExpectedValue": sprintf("Package '%s' has version defined", [packageName]), @@ -44,9 +46,11 @@ CxPolicy[result] { regex.match("^[a-zA-Z]", packageName) == true not dockerLib.withVersion(packageName) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "searchValue": packageName, "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Package '%s' has version defined", [packageName]), diff --git a/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/negative4.dockerfile b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/negative4.dockerfile new file mode 100644 index 00000000000..6935edccbec --- /dev/null +++ b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/negative4.dockerfile @@ -0,0 +1,2 @@ +from busybox +run apt-get install python=2.7 \ No newline at end of file diff --git a/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/positive3.dockerfile b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/positive3.dockerfile new file mode 100644 index 00000000000..eea397c247c --- /dev/null +++ b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/positive3.dockerfile @@ -0,0 +1,14 @@ +from busybox +run apt-get install python +run ["apt-get", "install", "python"] + +from busybox2 +run apt-get install -y -t python + +from busybox3 +run apt-get update && apt-get install -y \ + python-qt4 \ + python-pyside \ + python-pip \ + python3-pip \ + python3-pyqt5 diff --git a/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/positive_expected_result.json b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/positive_expected_result.json index f2afe4b4ae2..e726c0c30ec 100644 --- a/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/positive_expected_result.json +++ b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/test/positive_expected_result.json @@ -94,5 +94,53 @@ "severity": "MEDIUM", "line": 9, "fileName": "positive2.dockerfile" + }, + { + "queryName": "Apt Get Install Pin Version Not Defined", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Apt Get Install Pin Version Not Defined", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Apt Get Install Pin Version Not Defined", + "severity": "MEDIUM", + "line": 6, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Apt Get Install Pin Version Not Defined", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Apt Get Install Pin Version Not Defined", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Apt Get Install Pin Version Not Defined", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Apt Get Install Pin Version Not Defined", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Apt Get Install Pin Version Not Defined", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive3.dockerfile" } ] diff --git a/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/query.rego b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/query.rego index 251c8de4840..e7755c63964 100644 --- a/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/query.rego +++ b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/query.rego @@ -15,9 +15,11 @@ CxPolicy[result] { not avoidManualInput(command) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should avoid manual input", [resource.Original]), "keyActualValue": sprintf("{{%s}} doesn't avoid manual input", [resource.Original]), @@ -36,7 +38,7 @@ CxPolicy[result] { result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should avoid manual input", [resource.Original]), "keyActualValue": sprintf("{{%s}} doesn't avoid manual input", [resource.Original]), diff --git a/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/negative9.dockerfile b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/negative9.dockerfile new file mode 100644 index 00000000000..6e921a95752 --- /dev/null +++ b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/negative9.dockerfile @@ -0,0 +1,4 @@ +from node:12 +run apt-get -y install apt-utils +run apt-get -qy install git gcc +run ["apt-get", "-y", "install", "apt-utils"] diff --git a/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/positive8.dockerfile b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/positive8.dockerfile new file mode 100644 index 00000000000..1bf13042873 --- /dev/null +++ b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/positive8.dockerfile @@ -0,0 +1,4 @@ +from node:12 +run apt-get install python=2.7 +run apt-get install apt-utils +run ["apt-get", "install", "apt-utils"] diff --git a/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/positive_expected_result.json b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/positive_expected_result.json index eb501cf7739..07ff384695a 100644 --- a/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/positive_expected_result.json +++ b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/test/positive_expected_result.json @@ -1,92 +1,110 @@ [ - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 2, - "filename": "positive1.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 3, - "filename": "positive1.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 4, - "filename": "positive1.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 2, - "filename": "positive2.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 3, - "filename": "positive2.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 4, - "filename": "positive2.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 2, - "filename": "positive3.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 2, - "filename": "positive4.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 3, - "filename": "positive4.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 3, - "filename": "positive5.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 2, - "filename": "positive5.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 3, - "filename": "positive6.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 2, - "filename": "positive6.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 3, - "filename": "positive7.dockerfile" - }, - { - "queryName": "APT-GET Missing Flags To Avoid Manual Input", - "severity": "LOW", - "line": 2, - "filename": "positive7.dockerfile" - } + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 2, + "filename": "positive1.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 3, + "filename": "positive1.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 4, + "filename": "positive1.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 2, + "filename": "positive2.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 3, + "filename": "positive2.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 4, + "filename": "positive2.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 2, + "filename": "positive3.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 2, + "filename": "positive4.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 3, + "filename": "positive4.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 3, + "filename": "positive5.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 2, + "filename": "positive5.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 3, + "filename": "positive6.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 2, + "filename": "positive6.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 3, + "filename": "positive7.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 2, + "filename": "positive7.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 2, + "filename": "positive8.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 3, + "filename": "positive8.dockerfile" + }, + { + "queryName": "APT-GET Missing Flags To Avoid Manual Input", + "severity": "LOW", + "line": 4, + "filename": "positive8.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/query.rego b/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/query.rego index c405fd7f93c..826186998df 100644 --- a/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/query.rego +++ b/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/query.rego @@ -15,9 +15,11 @@ CxPolicy[result] { regex.match("apt-get (-(-)?[a-zA-Z]+ *)*install", commandsSplit[j]) == true not avoidAdditionalPackages(commandsSplit[j]) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("'%s' uses '--no-install-recommends' flag to avoid installing additional packages", [resource.Original]), "keyActualValue": sprintf("'%s' does not use '--no-install-recommends' flag to avoid installing additional packages", [resource.Original]), @@ -37,9 +39,11 @@ CxPolicy[result] { not avoidAdditionalPackages(commands) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("'%s' uses '--no-install-recommends' flag to avoid installing additional packages", [resource.Original]), "keyActualValue": sprintf("'%s' does not use '--no-install-recommends' flag to avoid installing additional packages", [resource.Original]), diff --git a/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/negative2.dockerfile b/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/negative2.dockerfile new file mode 100644 index 00000000000..f9aafcc4b01 --- /dev/null +++ b/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/negative2.dockerfile @@ -0,0 +1,4 @@ +from node:12 +run apt-get --no-install-recommends install apt-utils +run ["apt-get", "apt::install-recommends=false", "install", "apt-utils"] + diff --git a/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/positive2.dockerfile b/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/positive2.dockerfile new file mode 100644 index 00000000000..216835726a1 --- /dev/null +++ b/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/positive2.dockerfile @@ -0,0 +1,3 @@ +from node:12 +run apt-get install apt-utils +run ["apt-get", "install", "apt-utils"] \ No newline at end of file diff --git a/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/positive_expected_result.json b/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/positive_expected_result.json index 224923adbc5..d8e2514a366 100644 --- a/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/positive_expected_result.json +++ b/assets/queries/dockerfile/apt_get_not_avoiding_additional_packages/test/positive_expected_result.json @@ -2,11 +2,25 @@ { "queryName": "APT-GET Not Avoiding Additional Packages", "severity": "INFO", - "line": 2 + "line": 2, + "fileName": "positive.dockerfile" }, { "queryName": "APT-GET Not Avoiding Additional Packages", "severity": "INFO", - "line": 3 + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "APT-GET Not Avoiding Additional Packages", + "severity": "INFO", + "line": 2, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "APT-GET Not Avoiding Additional Packages", + "severity": "INFO", + "line": 3, + "fileName": "positive2.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/changing_default_shell_using_run_command/query.rego b/assets/queries/dockerfile/changing_default_shell_using_run_command/query.rego index 9e602aec2cd..f34397f90ca 100644 --- a/assets/queries/dockerfile/changing_default_shell_using_run_command/query.rego +++ b/assets/queries/dockerfile/changing_default_shell_using_run_command/query.rego @@ -1,6 +1,7 @@ package Cx import data.generic.common as common_lib +import data.generic.dockerfile as dockerLib shell_possibilities := { "/bin/bash", @@ -28,10 +29,12 @@ CxPolicy[result] { command_possibilities := {"mv", "chsh", "usermod", "ln"} command == command_possibilities[cp] + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "debug": sprintf("%s", [value[v]]), "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should use the SHELL command to change the default shell", [resource.Original]), "keyActualValue": sprintf("{{%s}} uses the RUN command to change the default shell", [resource.Original]), @@ -46,9 +49,11 @@ CxPolicy[result] { command := run_values[0] contains(command, "powershell") + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should use the SHELL command to change the default shell", [resource.Original]), "keyActualValue": sprintf("{{%s}} uses the RUN command to change the default shell", [resource.Original]), diff --git a/assets/queries/dockerfile/changing_default_shell_using_run_command/test/negative5.dockerfile b/assets/queries/dockerfile/changing_default_shell_using_run_command/test/negative5.dockerfile new file mode 100644 index 00000000000..ea91f7d74d7 --- /dev/null +++ b/assets/queries/dockerfile/changing_default_shell_using_run_command/test/negative5.dockerfile @@ -0,0 +1,11 @@ +from alpine:3.5 +run apk add --update py2-pip +run sudo yum install -y bundler +run yum install +shell ["/bin/bash", "-c"] +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/changing_default_shell_using_run_command/test/positive3.dockerfile b/assets/queries/dockerfile/changing_default_shell_using_run_command/test/positive3.dockerfile new file mode 100644 index 00000000000..d3ce857b5f9 --- /dev/null +++ b/assets/queries/dockerfile/changing_default_shell_using_run_command/test/positive3.dockerfile @@ -0,0 +1,11 @@ +from alpine:3.5 +run apk add --update py2-pip +run sudo yum install -y bundler +run yum install +run ln -sfv /bin/bash /bin/sh +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/changing_default_shell_using_run_command/test/positive_expected_result.json b/assets/queries/dockerfile/changing_default_shell_using_run_command/test/positive_expected_result.json index c9854941220..fc1d3dcbf58 100644 --- a/assets/queries/dockerfile/changing_default_shell_using_run_command/test/positive_expected_result.json +++ b/assets/queries/dockerfile/changing_default_shell_using_run_command/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "MEDIUM", "line": 5, "filename": "positive2.dockerfile" + }, + { + "queryName": "Changing Default Shell Using RUN Command", + "severity": "MEDIUM", + "line": 5, + "filename": "positive3.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/chown_flag_exists/query.rego b/assets/queries/dockerfile/chown_flag_exists/query.rego index 622837f5237..f6083662984 100644 --- a/assets/queries/dockerfile/chown_flag_exists/query.rego +++ b/assets/queries/dockerfile/chown_flag_exists/query.rego @@ -1,13 +1,16 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name] contains(resource[j].Flags[f], "--chown") + from_command := dockerLib.get_original_from_command(resource) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource[j].Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource[j].Original]), "category": "Best Practices", "issueType": "IncorrectValue", "keyExpectedValue": "The 'Dockerfile' shouldn´t contain the 'chown' flag", diff --git a/assets/queries/dockerfile/chown_flag_exists/test/negative2.dockerfile b/assets/queries/dockerfile/chown_flag_exists/test/negative2.dockerfile new file mode 100644 index 00000000000..4edd7678daa --- /dev/null +++ b/assets/queries/dockerfile/chown_flag_exists/test/negative2.dockerfile @@ -0,0 +1,7 @@ +from python:3.7 +run pip install Flask==0.11.1 +run useradd -ms /bin/bash patrick +copy app /app +workdir /app +user patrick +cmd ["python", "app.py"] diff --git a/assets/queries/dockerfile/chown_flag_exists/test/positive2.dockerfile b/assets/queries/dockerfile/chown_flag_exists/test/positive2.dockerfile new file mode 100644 index 00000000000..7da67f57278 --- /dev/null +++ b/assets/queries/dockerfile/chown_flag_exists/test/positive2.dockerfile @@ -0,0 +1,7 @@ +from python:3.7 +run pip install Flask==0.11.1 +run useradd -ms /bin/bash patrick +copy --chown=patrick:patrick app /app +workdir /app +user patrick +cmd ["python", "app.py"] diff --git a/assets/queries/dockerfile/chown_flag_exists/test/positive_expected_result.json b/assets/queries/dockerfile/chown_flag_exists/test/positive_expected_result.json index 41cc05a4a3d..fa9e309eba9 100644 --- a/assets/queries/dockerfile/chown_flag_exists/test/positive_expected_result.json +++ b/assets/queries/dockerfile/chown_flag_exists/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Chown Flag Exists", - "severity": "LOW", - "line": 4 - } -] + { + "queryName": "Chown Flag Exists", + "severity": "LOW", + "line": 4, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Chown Flag Exists", + "severity": "LOW", + "line": 4, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/copy_from_references_current_from_alias/query.rego b/assets/queries/dockerfile/copy_from_references_current_from_alias/query.rego index 533dcc77be4..63fbfc3417b 100644 --- a/assets/queries/dockerfile/copy_from_references_current_from_alias/query.rego +++ b/assets/queries/dockerfile/copy_from_references_current_from_alias/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "copy" @@ -9,9 +11,11 @@ CxPolicy[result] { isAliasCurrentFromAlias(name, aux_split[1]) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "COPY --from should not reference the current FROM alias", "keyActualValue": "COPY --from references the current FROM alias", diff --git a/assets/queries/dockerfile/copy_from_references_current_from_alias/test/negative2.dockerfile b/assets/queries/dockerfile/copy_from_references_current_from_alias/test/negative2.dockerfile new file mode 100644 index 00000000000..c38778c6031 --- /dev/null +++ b/assets/queries/dockerfile/copy_from_references_current_from_alias/test/negative2.dockerfile @@ -0,0 +1,12 @@ +from golang:1.7.3 AS builder +workdir /go/src/github.com/foo/href-counter/ +run go get -d -v golang.org/x/net/html +copy app.go . +run CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . + +# another dockerfile +from alpine:latest +run apk --no-cache add ca-certificates +workdir /root/ +copy --from=builder /go/src/github.com/foo/href-counter/app . +cmd ["./app"] diff --git a/assets/queries/dockerfile/copy_from_references_current_from_alias/test/positive2.dockerfile b/assets/queries/dockerfile/copy_from_references_current_from_alias/test/positive2.dockerfile new file mode 100644 index 00000000000..1ef6617540f --- /dev/null +++ b/assets/queries/dockerfile/copy_from_references_current_from_alias/test/positive2.dockerfile @@ -0,0 +1,3 @@ +from myimage:tag as dep +copy --from=dep /binary / +run dir c:\ \ No newline at end of file diff --git a/assets/queries/dockerfile/copy_from_references_current_from_alias/test/positive_expected_result.json b/assets/queries/dockerfile/copy_from_references_current_from_alias/test/positive_expected_result.json index 0a577a86177..9e540dc9751 100644 --- a/assets/queries/dockerfile/copy_from_references_current_from_alias/test/positive_expected_result.json +++ b/assets/queries/dockerfile/copy_from_references_current_from_alias/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "COPY '--from' References Current FROM Alias", - "severity": "LOW", - "line": 2 - } + { + "queryName": "COPY '--from' References Current FROM Alias", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "COPY '--from' References Current FROM Alias", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/query.rego b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/query.rego index c2ae55008f3..1f8ea2c0157 100644 --- a/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/query.rego +++ b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] @@ -12,9 +14,11 @@ CxPolicy[result] { not endswith(command[minus(numElems, 1)], "/") + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.COPY={{%s}}", [name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.COPY={{%s}}", [from_command, name, resource.Value[0]]), "issueType": "IncorrectValue", #"MissingAttribute" / "RedundantAttribute" "keyExpectedValue": "When COPY command has more than two arguments, the last one should end with a slash", "keyActualValue": "COPY command has more than two arguments and the last one does not end with a slash", diff --git a/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/negative3.dockerfile b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/negative3.dockerfile new file mode 100644 index 00000000000..1ed7dd5795b --- /dev/null +++ b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/negative3.dockerfile @@ -0,0 +1,2 @@ +from node:carbon +copy package.json yarn.lock my_app/ diff --git a/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/positive2.dockerfile b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/positive2.dockerfile new file mode 100644 index 00000000000..560ad97b040 --- /dev/null +++ b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/positive2.dockerfile @@ -0,0 +1,2 @@ +from node:carbon2 +copy package.json yarn.lock my_app diff --git a/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/positive_expected_result.json b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/positive_expected_result.json index 2774ad6013d..3d381bcd233 100644 --- a/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/positive_expected_result.json +++ b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/test/positive_expected_result.json @@ -1,8 +1,14 @@ [ - { - "queryName": "Copy With More Than Two Arguments Not Ending With Slash", - "severity": "LOW", - "fileName": "positive.dockerfile", - "line": 2 - } + { + "queryName": "Copy With More Than Two Arguments Not Ending With Slash", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Copy With More Than Two Arguments Not Ending With Slash", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/curl_or_wget_instead_of_add/query.rego b/assets/queries/dockerfile/curl_or_wget_instead_of_add/query.rego index 7ebf5bccafa..075b290b7c9 100644 --- a/assets/queries/dockerfile/curl_or_wget_instead_of_add/query.rego +++ b/assets/queries/dockerfile/curl_or_wget_instead_of_add/query.rego @@ -1,13 +1,17 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][j] resource.Cmd == "add" httpRequestChecker(resource.Value) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Should use 'curl' or 'wget' to download %s", [resource.Value[0]]), "keyActualValue": sprintf("'ADD' %s", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/negative3.dockerfile b/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/negative3.dockerfile new file mode 100644 index 00000000000..8e78d88d5ae --- /dev/null +++ b/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/negative3.dockerfile @@ -0,0 +1,5 @@ +from openjdk:10-jdk +run mkdir -p /usr/src/things \ + && curl -SL https://example.com/big.tar.xz \ + | tar -xJC /usr/src/things \ + && make -C /usr/src/things all diff --git a/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/positive2.dockerfile b/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/positive2.dockerfile new file mode 100644 index 00000000000..df5300c56c5 --- /dev/null +++ b/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/positive2.dockerfile @@ -0,0 +1,5 @@ +from openjdk:10-jdk +volume /tmp +add https://example.com/big.tar.xz /usr/src/things/ +run tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things +run make -C /usr/src/things all diff --git a/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/positive_expected_result.json b/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/positive_expected_result.json index 914f34a3b1a..1bca3e91498 100644 --- a/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/positive_expected_result.json +++ b/assets/queries/dockerfile/curl_or_wget_instead_of_add/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Curl or Wget Instead of Add", - "severity": "LOW", - "line": 3 - } -] + { + "queryName": "Curl or Wget Instead of Add", + "severity": "LOW", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Curl or Wget Instead of Add", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/exposing_port_22/query.rego b/assets/queries/dockerfile/exposing_port_22/query.rego index c8f8bcd0a95..9f4afdc3037 100644 --- a/assets/queries/dockerfile/exposing_port_22/query.rego +++ b/assets/queries/dockerfile/exposing_port_22/query.rego @@ -1,14 +1,18 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { command := input.document[i].command[name][_] command.Cmd == "expose" to_number(command.Value[_]) == 22 + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, command.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, command.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "'EXPOSE' shouldn't contain the port 22 ", "keyActualValue": "'EXPOSE' contains the port 22 ", diff --git a/assets/queries/dockerfile/exposing_port_22/test/negative2.dockerfile b/assets/queries/dockerfile/exposing_port_22/test/negative2.dockerfile new file mode 100644 index 00000000000..08e4bcb2593 --- /dev/null +++ b/assets/queries/dockerfile/exposing_port_22/test/negative2.dockerfile @@ -0,0 +1,4 @@ +from gliderlabs/alpine:3.3 +run apk --no-cache add nginx +expose 80 +cmd ["nginx", "-g", "daemon off;"] diff --git a/assets/queries/dockerfile/exposing_port_22/test/positive2.dockerfile b/assets/queries/dockerfile/exposing_port_22/test/positive2.dockerfile new file mode 100644 index 00000000000..328ffa1212b --- /dev/null +++ b/assets/queries/dockerfile/exposing_port_22/test/positive2.dockerfile @@ -0,0 +1,4 @@ +from gliderlabs/alpine:3.3 +run apk --no-cache add nginx +expose 3000 80 443 22 +cmd ["nginx", "-g", "daemon off;"] diff --git a/assets/queries/dockerfile/exposing_port_22/test/positive_expected_result.json b/assets/queries/dockerfile/exposing_port_22/test/positive_expected_result.json index 7c697fbb3e4..c5296736119 100644 --- a/assets/queries/dockerfile/exposing_port_22/test/positive_expected_result.json +++ b/assets/queries/dockerfile/exposing_port_22/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Exposing Port 22 (SSH)", - "severity": "LOW", - "line": 3 - } -] + { + "queryName": "Exposing Port 22 (SSH)", + "severity": "LOW", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Exposing Port 22 (SSH)", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/gem_install_without_version/query.rego b/assets/queries/dockerfile/gem_install_without_version/query.rego index c4d76a64232..29f1ae6971e 100644 --- a/assets/queries/dockerfile/gem_install_without_version/query.rego +++ b/assets/queries/dockerfile/gem_install_without_version/query.rego @@ -18,9 +18,11 @@ CxPolicy[result] { some j analyzePackages(j, packages[j], packages, length) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("%s is 'gem install :'", [resource.Original]), "keyActualValue": sprintf("%s is 'gem install ', you should use 'gem install :", [resource.Original]), @@ -40,9 +42,11 @@ CxPolicy[result] { regex.match("^[a-zA-Z]", resource.Value[j]) == true not dockerLib.withVersion(resource.Value[j]) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("%s is 'gem install :'", [resource.Original]), "keyActualValue": sprintf("%s is 'gem install ', you should use 'gem install :", [resource.Original]), diff --git a/assets/queries/dockerfile/gem_install_without_version/test/negative2.dockerfile b/assets/queries/dockerfile/gem_install_without_version/test/negative2.dockerfile new file mode 100644 index 00000000000..a0b8b9cabb9 --- /dev/null +++ b/assets/queries/dockerfile/gem_install_without_version/test/negative2.dockerfile @@ -0,0 +1,13 @@ +from alpine:3.5 +run apk add --update py2-pip +run gem install bundler:2.0.2 +run bundle install +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] +env GRPC_VERSION 1.0.0 +run gem install grpc -v ${GRPC_RUBY_VERSION} +run gem install grpc:${GRPC_VERSION} grpc-tools:${GRPC_VERSION} diff --git a/assets/queries/dockerfile/gem_install_without_version/test/positive2.dockerfile b/assets/queries/dockerfile/gem_install_without_version/test/positive2.dockerfile new file mode 100644 index 00000000000..646f822efdb --- /dev/null +++ b/assets/queries/dockerfile/gem_install_without_version/test/positive2.dockerfile @@ -0,0 +1,12 @@ +from alpine:3.5 +run apk add --update py2-pip +run gem install bundler +run ["gem", "install", "blunder"] +run gem install grpc -v ${GRPC_RUBY_VERSION} blunder +run bundle install +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/gem_install_without_version/test/positive_expected_result.json b/assets/queries/dockerfile/gem_install_without_version/test/positive_expected_result.json index 9e0dc193dc6..d7bd07a860a 100644 --- a/assets/queries/dockerfile/gem_install_without_version/test/positive_expected_result.json +++ b/assets/queries/dockerfile/gem_install_without_version/test/positive_expected_result.json @@ -1,17 +1,38 @@ [ - { - "queryName": "Gem Install Without Version", - "severity": "MEDIUM", - "line": 3 - }, - { - "queryName": "Gem Install Without Version", - "severity": "MEDIUM", - "line": 4 - }, - { - "queryName": "Gem Install Without Version", - "severity": "MEDIUM", - "line": 5 - } -] + { + "queryName": "Gem Install Without Version", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Gem Install Without Version", + "severity": "MEDIUM", + "line": 4, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Gem Install Without Version", + "severity": "MEDIUM", + "line": 5, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Gem Install Without Version", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Gem Install Without Version", + "severity": "MEDIUM", + "line": 4, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Gem Install Without Version", + "severity": "MEDIUM", + "line": 5, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/healthcheck_instruction_missing/query.rego b/assets/queries/dockerfile/healthcheck_instruction_missing/query.rego index 7ac3f3bb857..fb3cc24e8ca 100644 --- a/assets/queries/dockerfile/healthcheck_instruction_missing/query.rego +++ b/assets/queries/dockerfile/healthcheck_instruction_missing/query.rego @@ -8,9 +8,10 @@ CxPolicy[result] { not contains(resource, "healthcheck") + from_command := dockerLib.get_original_from_command(resource) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}", [name]), + "searchKey": sprintf("%s={{%s}}", [from_command, name]), "issueType": "MissingAttribute", "keyExpectedValue": "Dockerfile should contain instruction 'HEALTHCHECK'", "keyActualValue": "Dockerfile doesn't contain instruction 'HEALTHCHECK'", diff --git a/assets/queries/dockerfile/healthcheck_instruction_missing/test/negative3.dockerfile b/assets/queries/dockerfile/healthcheck_instruction_missing/test/negative3.dockerfile new file mode 100644 index 00000000000..0924f1fdf1d --- /dev/null +++ b/assets/queries/dockerfile/healthcheck_instruction_missing/test/negative3.dockerfile @@ -0,0 +1,8 @@ +from node:alpine +workdir /usr/src/app +copy package*.json ./ +run npm install +copy . . +expose 3000 +healthcheck CMD curl --fail http://localhost:3000 || exit 1 +cmd ["node","app.js"] \ No newline at end of file diff --git a/assets/queries/dockerfile/healthcheck_instruction_missing/test/positive3.dockerfile b/assets/queries/dockerfile/healthcheck_instruction_missing/test/positive3.dockerfile new file mode 100644 index 00000000000..ac28ce39a10 --- /dev/null +++ b/assets/queries/dockerfile/healthcheck_instruction_missing/test/positive3.dockerfile @@ -0,0 +1,7 @@ +from node:alpine +workdir /usr/src/app +copy package*.json ./ +run npm install +copy . . +expose 3000 +cmd ["node","app.js"] \ No newline at end of file diff --git a/assets/queries/dockerfile/healthcheck_instruction_missing/test/positive_expected_result.json b/assets/queries/dockerfile/healthcheck_instruction_missing/test/positive_expected_result.json index 3fff0a3f2f4..355b007dd53 100644 --- a/assets/queries/dockerfile/healthcheck_instruction_missing/test/positive_expected_result.json +++ b/assets/queries/dockerfile/healthcheck_instruction_missing/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "LOW", "line": 7, "fileName": "positive2.dockerfile" + }, + { + "queryName": "Healthcheck Instruction Missing", + "severity": "LOW", + "line": 1, + "fileName": "positive3.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/image_version_not_explicit/query.rego b/assets/queries/dockerfile/image_version_not_explicit/query.rego index 46c74eb9e80..662b7e688a1 100644 --- a/assets/queries/dockerfile/image_version_not_explicit/query.rego +++ b/assets/queries/dockerfile/image_version_not_explicit/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "from" @@ -7,9 +9,11 @@ CxPolicy[result] { versionNotExplicit(resource.Value,resource.EndLine) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}", [name]), + "searchKey": sprintf("%s={{%s}}", [from_command, name]), "issueType": "MissingAttribute", "keyExpectedValue": sprintf("FROM %s:'version'", [resource.Value[0]]), "keyActualValue": sprintf("FROM %s'", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/image_version_not_explicit/test/negative5.dockerfile b/assets/queries/dockerfile/image_version_not_explicit/test/negative5.dockerfile new file mode 100644 index 00000000000..3e0bf155135 --- /dev/null +++ b/assets/queries/dockerfile/image_version_not_explicit/test/negative5.dockerfile @@ -0,0 +1,11 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +arg IMAGE=alpine:3.12 +from $IMAGE +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/image_version_not_explicit/test/positive5.dockerfile b/assets/queries/dockerfile/image_version_not_explicit/test/positive5.dockerfile new file mode 100644 index 00000000000..d19a3511d99 --- /dev/null +++ b/assets/queries/dockerfile/image_version_not_explicit/test/positive5.dockerfile @@ -0,0 +1,9 @@ +from alpine +run apk add --update py2-pip +run pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/image_version_not_explicit/test/positive_expected_result.json b/assets/queries/dockerfile/image_version_not_explicit/test/positive_expected_result.json index a5cbb7933e2..2e04d53f46c 100644 --- a/assets/queries/dockerfile/image_version_not_explicit/test/positive_expected_result.json +++ b/assets/queries/dockerfile/image_version_not_explicit/test/positive_expected_result.json @@ -34,5 +34,11 @@ "severity": "MEDIUM", "fileName": "positive4.dockerfile", "line": 10 + }, + { + "queryName": "Image Version Not Explicit", + "severity": "MEDIUM", + "fileName": "positive5.dockerfile", + "line": 1 } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/image_version_using_latest/query.rego b/assets/queries/dockerfile/image_version_using_latest/query.rego index cbce842332f..bb2edce69d7 100644 --- a/assets/queries/dockerfile/image_version_using_latest/query.rego +++ b/assets/queries/dockerfile/image_version_using_latest/query.rego @@ -1,14 +1,18 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "from" not resource.Value[0] == "scratch" contains(resource.Value[0], ":latest") + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}", [name]), + "searchKey": sprintf("%s={{%s}}", [from_command, name]), "issueType": "IncorrectValue", #"MissingAttribute" / "RedundantAttribute" "keyExpectedValue": sprintf("FROM %s:'version' where version should not be 'latest'", [resource.Value[0]]), "keyActualValue": sprintf("FROM %s'", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/image_version_using_latest/test/negative2.dockerfile b/assets/queries/dockerfile/image_version_using_latest/test/negative2.dockerfile new file mode 100644 index 00000000000..e7dbf812104 --- /dev/null +++ b/assets/queries/dockerfile/image_version_using_latest/test/negative2.dockerfile @@ -0,0 +1,9 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/image_version_using_latest/test/positive2.dockerfile b/assets/queries/dockerfile/image_version_using_latest/test/positive2.dockerfile new file mode 100644 index 00000000000..d05cf997998 --- /dev/null +++ b/assets/queries/dockerfile/image_version_using_latest/test/positive2.dockerfile @@ -0,0 +1,9 @@ +from alpine:latest +run apk add --update py2-pip +run pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/image_version_using_latest/test/positive_expected_result.json b/assets/queries/dockerfile/image_version_using_latest/test/positive_expected_result.json index 54fb27a0982..3e6d61beed8 100644 --- a/assets/queries/dockerfile/image_version_using_latest/test/positive_expected_result.json +++ b/assets/queries/dockerfile/image_version_using_latest/test/positive_expected_result.json @@ -2,6 +2,13 @@ { "queryName": "Image Version Using 'latest'", "severity": "MEDIUM", - "line": 1 + "line": 1, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Image Version Using 'latest'", + "severity": "MEDIUM", + "line": 1, + "fileName": "positive2.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/last_user_is_root/query.rego b/assets/queries/dockerfile/last_user_is_root/query.rego index 28e2dca5a04..70e512cf2fb 100644 --- a/assets/queries/dockerfile/last_user_is_root/query.rego +++ b/assets/queries/dockerfile/last_user_is_root/query.rego @@ -9,9 +9,10 @@ CxPolicy[result] { userCmd := [x | resource[j].Cmd == "user"; x := resource[j]] userCmd[minus(count(userCmd), 1)].Value[0] == "root" + from_command := dockerLib.get_original_from_command(resource) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, userCmd[minus(count(userCmd), 1)].Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, userCmd[minus(count(userCmd), 1)].Original]), "issueType": "IncorrectValue", "keyExpectedValue": "Last User shouldn't be root", "keyActualValue": "Last User is root", diff --git a/assets/queries/dockerfile/last_user_is_root/test/negative3.dockerfile b/assets/queries/dockerfile/last_user_is_root/test/negative3.dockerfile new file mode 100644 index 00000000000..b1a391b8d5d --- /dev/null +++ b/assets/queries/dockerfile/last_user_is_root/test/negative3.dockerfile @@ -0,0 +1,4 @@ +from alpine:2.6 +user root +run npm install +user guest \ No newline at end of file diff --git a/assets/queries/dockerfile/last_user_is_root/test/positive2.dockerfile b/assets/queries/dockerfile/last_user_is_root/test/positive2.dockerfile new file mode 100644 index 00000000000..7649a2f1ead --- /dev/null +++ b/assets/queries/dockerfile/last_user_is_root/test/positive2.dockerfile @@ -0,0 +1,3 @@ +from alpine:2.6 +user root +run npm install \ No newline at end of file diff --git a/assets/queries/dockerfile/last_user_is_root/test/positive_expected_result.json b/assets/queries/dockerfile/last_user_is_root/test/positive_expected_result.json index 751442ed373..4c836fb90dc 100644 --- a/assets/queries/dockerfile/last_user_is_root/test/positive_expected_result.json +++ b/assets/queries/dockerfile/last_user_is_root/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Last User Is 'root'", - "severity": "HIGH", - "line": 2 - } + { + "queryName": "Last User Is 'root'", + "severity": "HIGH", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Last User Is 'root'", + "severity": "HIGH", + "line": 2, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/maintainer_instruction_being_used/query.rego b/assets/queries/dockerfile/maintainer_instruction_being_used/query.rego index 98973103c4f..264d322f913 100644 --- a/assets/queries/dockerfile/maintainer_instruction_being_used/query.rego +++ b/assets/queries/dockerfile/maintainer_instruction_being_used/query.rego @@ -1,12 +1,16 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "maintainer" + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.MAINTAINER={{%s}}", [name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.MAINTAINER={{%s}}", [from_command, name, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Maintainer instruction being used in Label 'LABEL maintainer=%s'", [resource.Value[0]]), "keyActualValue": sprintf("Maintainer instruction not being used in Label 'MAINTAINER %s'", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/maintainer_instruction_being_used/test/negative2.dockerfile b/assets/queries/dockerfile/maintainer_instruction_being_used/test/negative2.dockerfile new file mode 100644 index 00000000000..1678a5950ee --- /dev/null +++ b/assets/queries/dockerfile/maintainer_instruction_being_used/test/negative2.dockerfile @@ -0,0 +1,10 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +label maintainer="SvenDowideit@home.org.au" +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/maintainer_instruction_being_used/test/positive2.dockerfile b/assets/queries/dockerfile/maintainer_instruction_being_used/test/positive2.dockerfile new file mode 100644 index 00000000000..6c6bd02cc0f --- /dev/null +++ b/assets/queries/dockerfile/maintainer_instruction_being_used/test/positive2.dockerfile @@ -0,0 +1,10 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +maintainer "SvenDowideit@home.org.au" +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/maintainer_instruction_being_used/test/positive_expected_result.json b/assets/queries/dockerfile/maintainer_instruction_being_used/test/positive_expected_result.json index ae5d0a537f5..ee5d19ab48a 100644 --- a/assets/queries/dockerfile/maintainer_instruction_being_used/test/positive_expected_result.json +++ b/assets/queries/dockerfile/maintainer_instruction_being_used/test/positive_expected_result.json @@ -2,6 +2,13 @@ { "queryName": "MAINTAINER Instruction Being Used", "severity": "LOW", - "line": 4 + "line": 4, + "fileName": "positive.dockerfile" + }, + { + "queryName": "MAINTAINER Instruction Being Used", + "severity": "LOW", + "line": 4, + "fileName": "positive2.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/missing_dnf_clean_all/query.rego b/assets/queries/dockerfile/missing_dnf_clean_all/query.rego index 982d8117170..3f75383088f 100644 --- a/assets/queries/dockerfile/missing_dnf_clean_all/query.rego +++ b/assets/queries/dockerfile/missing_dnf_clean_all/query.rego @@ -13,9 +13,11 @@ CxPolicy[result] { not containsDnfClean(input.document[i].command[name], resource._kics_line) not containsCleanAfterInstall(command) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": "After installing a package with dnf, command 'dnf clean all' should run.", "keyActualValue": "Command `dnf clean all` is not being run after installing packages.", diff --git a/assets/queries/dockerfile/missing_dnf_clean_all/test/negative3.dockerfile b/assets/queries/dockerfile/missing_dnf_clean_all/test/negative3.dockerfile new file mode 100644 index 00000000000..c06cea0f7b1 --- /dev/null +++ b/assets/queries/dockerfile/missing_dnf_clean_all/test/negative3.dockerfile @@ -0,0 +1,7 @@ +from fedora:27 +run set -uex && \ + dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo && \ + sed -i 's/\$releasever/26/g' /etc/yum.repos.d/docker-ce.repo && \ + dnf install -vy docker-ce && \ + dnf clean all +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/missing_dnf_clean_all/test/positive2.dockerfile b/assets/queries/dockerfile/missing_dnf_clean_all/test/positive2.dockerfile new file mode 100644 index 00000000000..49a630da7c2 --- /dev/null +++ b/assets/queries/dockerfile/missing_dnf_clean_all/test/positive2.dockerfile @@ -0,0 +1,6 @@ +from fedora:27 +run set -uex && \ + dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo && \ + sed -i 's/\$releasever/26/g' /etc/yum.repos.d/docker-ce.repo && \ + dnf install -vy docker-ce +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/missing_dnf_clean_all/test/positive_expected_result.json b/assets/queries/dockerfile/missing_dnf_clean_all/test/positive_expected_result.json index 0c521996f67..c6d71e5c92c 100644 --- a/assets/queries/dockerfile/missing_dnf_clean_all/test/positive_expected_result.json +++ b/assets/queries/dockerfile/missing_dnf_clean_all/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Missing Dnf Clean All", - "severity": "LOW", - "line": 2 - } + { + "queryName": "Missing Dnf Clean All", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Missing Dnf Clean All", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/missing_flag_from_dnf_install/query.rego b/assets/queries/dockerfile/missing_flag_from_dnf_install/query.rego index f3f1f143c64..ea3dc692ea0 100644 --- a/assets/queries/dockerfile/missing_flag_from_dnf_install/query.rego +++ b/assets/queries/dockerfile/missing_flag_from_dnf_install/query.rego @@ -14,9 +14,11 @@ CxPolicy[result] { not hasYesFlag(c) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), "searchValue": trim_space(c), "issueType": "IncorrectValue", "keyExpectedValue": "When running `dnf install`, `-y` or `--assumeyes` switch should be set to avoid build failure ", diff --git a/assets/queries/dockerfile/missing_flag_from_dnf_install/test/negative5.dockerfile b/assets/queries/dockerfile/missing_flag_from_dnf_install/test/negative5.dockerfile new file mode 100644 index 00000000000..0446e79007d --- /dev/null +++ b/assets/queries/dockerfile/missing_flag_from_dnf_install/test/negative5.dockerfile @@ -0,0 +1,5 @@ +from fedora:27 +run set -uex && \ + dnf config-manager --set-enabled docker-ce-test && \ + dnf install -y docker-ce && \ + dnf clean all \ No newline at end of file diff --git a/assets/queries/dockerfile/missing_flag_from_dnf_install/test/positive5.dockerfile b/assets/queries/dockerfile/missing_flag_from_dnf_install/test/positive5.dockerfile new file mode 100644 index 00000000000..396ff2998bd --- /dev/null +++ b/assets/queries/dockerfile/missing_flag_from_dnf_install/test/positive5.dockerfile @@ -0,0 +1,11 @@ +from fedora:27 +run set -uex && \ + dnf config-manager --set-enabled docker-ce-test && \ + dnf install docker-ce && \ + dnf clean all + +from fedora:28 +run set -uex +run dnf config-manager --set-enabled docker-ce-test +run dnf in docker-ce +run dnf clean all \ No newline at end of file diff --git a/assets/queries/dockerfile/missing_flag_from_dnf_install/test/positive_expected_result.json b/assets/queries/dockerfile/missing_flag_from_dnf_install/test/positive_expected_result.json index 8ca30d102d6..f94db540134 100644 --- a/assets/queries/dockerfile/missing_flag_from_dnf_install/test/positive_expected_result.json +++ b/assets/queries/dockerfile/missing_flag_from_dnf_install/test/positive_expected_result.json @@ -1,38 +1,50 @@ [ - { - "queryName": "Missing Flag From Dnf Install", - "severity": "LOW", - "line": 2, - "fileName": "positive.dockerfile" - }, - { - "queryName": "Missing Flag From Dnf Install", - "severity": "LOW", - "line": 10, - "fileName": "positive.dockerfile" - }, - { - "queryName": "Missing Flag From Dnf Install", - "severity": "LOW", - "line": 2, - "fileName": "positive2.dockerfile" - }, - { - "queryName": "Missing Flag From Dnf Install", - "severity": "LOW", - "line": 10, - "fileName": "positive2.dockerfile" - }, - { - "queryName": "Missing Flag From Dnf Install", - "severity": "LOW", - "line": 2, - "fileName": "positive3.dockerfile" - }, - { - "queryName": "Missing Flag From Dnf Install", - "severity": "LOW", - "line": 21, - "fileName": "positive4.dockerfile" - } + { + "queryName": "Missing Flag From Dnf Install", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Missing Flag From Dnf Install", + "severity": "LOW", + "line": 10, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Missing Flag From Dnf Install", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Missing Flag From Dnf Install", + "severity": "LOW", + "line": 10, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Missing Flag From Dnf Install", + "severity": "LOW", + "line": 2, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Missing Flag From Dnf Install", + "severity": "LOW", + "line": 21, + "fileName": "positive4.dockerfile" + }, + { + "queryName": "Missing Flag From Dnf Install", + "severity": "LOW", + "line": 2, + "fileName": "positive5.dockerfile" + }, + { + "queryName": "Missing Flag From Dnf Install", + "severity": "LOW", + "line": 10, + "fileName": "positive5.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/missing_user_instruction/test/negative4.dockerfile b/assets/queries/dockerfile/missing_user_instruction/test/negative4.dockerfile new file mode 100644 index 00000000000..d4bc4f7b01a --- /dev/null +++ b/assets/queries/dockerfile/missing_user_instruction/test/negative4.dockerfile @@ -0,0 +1,14 @@ +from python:2.7 +run pip install Flask==0.11.1 +run useradd -ms /bin/bash patrick +copy --chown=patrick:patrick app /app +workdir /app +user patrick +cmd ["python", "app.py"] + +from scratch +run pip install Flask==0.11.1 +run useradd -ms /bin/bash patrick +copy --chown=patrick:patrick app /app +workdir /app +cmd ["python", "app.py"] diff --git a/assets/queries/dockerfile/missing_user_instruction/test/positive3.dockerfile b/assets/queries/dockerfile/missing_user_instruction/test/positive3.dockerfile new file mode 100644 index 00000000000..81af6f6ec65 --- /dev/null +++ b/assets/queries/dockerfile/missing_user_instruction/test/positive3.dockerfile @@ -0,0 +1,6 @@ +from python:2.7 +run pip install Flask==0.11.1 +run useradd -ms /bin/bash patrick +copy --chown=patrick:patrick app /app +workdir /app +cmd ["python", "app.py"] diff --git a/assets/queries/dockerfile/missing_user_instruction/test/positive_expected_result.json b/assets/queries/dockerfile/missing_user_instruction/test/positive_expected_result.json index 8a0833e1de1..70ddd881925 100644 --- a/assets/queries/dockerfile/missing_user_instruction/test/positive_expected_result.json +++ b/assets/queries/dockerfile/missing_user_instruction/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "HIGH", "line": 7, "fileName": "positive2.dockerfile" - } + }, + { + "queryName": "Missing User Instruction", + "severity": "HIGH", + "line": 1, + "fileName": "positive3.dockerfile" + }, ] diff --git a/assets/queries/dockerfile/missing_version_specification_in_dnf_install/query.rego b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/query.rego index 0d50a1ebde0..ddefb97b7b8 100644 --- a/assets/queries/dockerfile/missing_version_specification_in_dnf_install/query.rego +++ b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/query.rego @@ -19,9 +19,11 @@ CxPolicy[result] { some j analyzePackages(j, packages[j], packages, length) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "Package version should be specified when using 'dnf install'", "keyActualValue": "Package version should be pinned when running ´dnf install´", @@ -42,9 +44,11 @@ CxPolicy[result] { regex.match("^[a-zA-Z]", resource.Value[j]) == true not dockerLib.withVersion(resource.Value[j]) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "Package version should be specified when using 'dnf install'", "keyActualValue": "Package version should be pinned when running ´dnf install´", diff --git a/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/negative2.dockerfile b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/negative2.dockerfile new file mode 100644 index 00000000000..2e494c41782 --- /dev/null +++ b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/negative2.dockerfile @@ -0,0 +1,6 @@ +from fedora:latest +run dnf -y update && dnf -y install httpd-2.24.2 && dnf clean all +run ["dnf", "install", "httpd-2.24.2"] +copy index.html /var/www/html/index.html +expose 80 +entrypoint /usr/sbin/httpd -DFOREGROUND diff --git a/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive2.dockerfile b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive2.dockerfile new file mode 100644 index 00000000000..dba9ef1dee2 --- /dev/null +++ b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive2.dockerfile @@ -0,0 +1,6 @@ +from fedora:latest +run dnf -y update && dnf -y install httpd && dnf clean all +run ["dnf", "install", "httpd"] +copy index.html /var/www/html/index.html +expose 80 +entrypoint /usr/sbin/httpd -DFOREGROUND diff --git a/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive_expected_result.json b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive_expected_result.json index 53dca70b9fb..a7f35bc112b 100644 --- a/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive_expected_result.json +++ b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive_expected_result.json @@ -1,12 +1,20 @@ [ - { - "queryName": "Missing Version Specification In dnf install", - "severity": "MEDIUM", - "line": 2 - }, - { - "queryName": "Missing Version Specification In dnf install", - "severity": "MEDIUM", - "line": 3 - } -] + { + "queryName": "Missing Version Specification In dnf install", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Missing Version Specification In dnf install", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Missing Version Specification In dnf install", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/missing_zypper_clean/query.rego b/assets/queries/dockerfile/missing_zypper_clean/query.rego index 9b19c044d0f..6f3e38f215f 100644 --- a/assets/queries/dockerfile/missing_zypper_clean/query.rego +++ b/assets/queries/dockerfile/missing_zypper_clean/query.rego @@ -14,9 +14,10 @@ CxPolicy[result] { commandHasZypperUsage(command) not hasCleanAfterInstall(commands[img], c, j) + from_command := dockerLib.get_original_from_command(commands[img]) result := { "documentId": document.id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [img, commands[img][c].Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, img, commands[img][c].Original]), "issueType": "MissingAttribute", "keyExpectedValue": "There should be a zypper clean after a zypper usage", "keyActualValue": sprintf("The command '%s' does not have a zypper clean after it", [commands[img][c].Value[j]]), diff --git a/assets/queries/dockerfile/missing_zypper_clean/test/negative3.dockerfile b/assets/queries/dockerfile/missing_zypper_clean/test/negative3.dockerfile new file mode 100644 index 00000000000..ba424b3e2bf --- /dev/null +++ b/assets/queries/dockerfile/missing_zypper_clean/test/negative3.dockerfile @@ -0,0 +1,3 @@ +from busybox:1.0 +run zypper install -y httpd=2.4 && zypper clean +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/missing_zypper_clean/test/positive2.dockerfile b/assets/queries/dockerfile/missing_zypper_clean/test/positive2.dockerfile new file mode 100644 index 00000000000..4e774713abf --- /dev/null +++ b/assets/queries/dockerfile/missing_zypper_clean/test/positive2.dockerfile @@ -0,0 +1,3 @@ +from busybox:1.0 +run zypper install +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/missing_zypper_clean/test/positive_expected_result.json b/assets/queries/dockerfile/missing_zypper_clean/test/positive_expected_result.json index 5570f022802..203ee10a67d 100644 --- a/assets/queries/dockerfile/missing_zypper_clean/test/positive_expected_result.json +++ b/assets/queries/dockerfile/missing_zypper_clean/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Missing Zypper Clean", - "severity": "LOW", - "line": 2 - } + { + "queryName": "Missing Zypper Clean", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Missing Zypper Clean", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/missing_zypper_non_interactive_switch/query.rego b/assets/queries/dockerfile/missing_zypper_non_interactive_switch/query.rego index 419ef8597a0..a14545cd452 100644 --- a/assets/queries/dockerfile/missing_zypper_non_interactive_switch/query.rego +++ b/assets/queries/dockerfile/missing_zypper_non_interactive_switch/query.rego @@ -14,9 +14,10 @@ CxPolicy[result] { commandHasZypperUsage(command) not commandHasNonInteractiveSwitch(command) + from_command := dockerLib.get_original_from_command(commands[img]) result := { "documentId": document.id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [img, commands[img][c].Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, img, commands[img][c].Original]), "issueType": "IncorrectValue", "keyExpectedValue": "zypper usages should have the non-interactive switch activated", "keyActualValue": sprintf("The command '%s' does not have the non-interactive switch activated (-y | --no-confirm)", [commands[img][c].Original]), diff --git a/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/negative3.dockerfile b/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/negative3.dockerfile new file mode 100644 index 00000000000..1c4879426a1 --- /dev/null +++ b/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/negative3.dockerfile @@ -0,0 +1,3 @@ +from busybox:1.0 +run zypper install -y httpd=2.4.46 && zypper clean +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/positive2.dockerfile b/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/positive2.dockerfile new file mode 100644 index 00000000000..5f770109502 --- /dev/null +++ b/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/positive2.dockerfile @@ -0,0 +1,3 @@ +from busybox:1.0 +run zypper install httpd && zypper clean +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/positive_expected_result.json b/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/positive_expected_result.json index fa3f05610c9..8a654e77bc9 100644 --- a/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/positive_expected_result.json +++ b/assets/queries/dockerfile/missing_zypper_non_interactive_switch/test/positive_expected_result.json @@ -2,6 +2,13 @@ { "queryName": "Missing Zypper Non-interactive Switch", "severity": "MEDIUM", - "line": 2 + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Missing Zypper Non-interactive Switch", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive2.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/multiple_cmd_instructions_listed/query.rego b/assets/queries/dockerfile/multiple_cmd_instructions_listed/query.rego index 9976a3b449f..e6ee221f7a5 100644 --- a/assets/queries/dockerfile/multiple_cmd_instructions_listed/query.rego +++ b/assets/queries/dockerfile/multiple_cmd_instructions_listed/query.rego @@ -9,9 +9,10 @@ CxPolicy[result] { cmdInst := [x | resource[j].Cmd == "cmd"; x := resource[j]] count(cmdInst) > 1 + from_command := dockerLib.get_original_from_command(resource) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, cmdInst[0].Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, cmdInst[0].Original]), "issueType": "RedundantAttribute", #"MissingAttribute" / "RedundantAttribute" "keyExpectedValue": "There should be only one CMD instruction", "keyActualValue": sprintf("There are %d CMD instructions", [count(cmdInst)]), diff --git a/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/negative3.dockerfile b/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/negative3.dockerfile new file mode 100644 index 00000000000..1db23282c4a --- /dev/null +++ b/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/negative3.dockerfile @@ -0,0 +1,12 @@ +from golang:1.7.3 +workdir /go/src/github.com/foo/href-counter/ +run go get -d -v golang.org/x/net/html +copy app.go . +run CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . +cmd ["./app"] + +from alpine:latest +run apk --no-cache add ca-certificates +workdir /root/ +copy --from=0 /go/src/github.com/foo/href-counter/app . +cmd ["./app"] \ No newline at end of file diff --git a/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/positive2.dockerfile b/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/positive2.dockerfile new file mode 100644 index 00000000000..38eef4b6c1b --- /dev/null +++ b/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/positive2.dockerfile @@ -0,0 +1,12 @@ +from golang:1.7.3 +workdir /go/src/github.com/foo/href-counter/ +run go get -d -v golang.org/x/net/html +copy app.go . +run CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . + +from alpine:latest +run apk --no-cache add ca-certificates +workdir /root/ +copy --from=0 /go/src/github.com/foo/href-counter/app . +cmd ["./app"] +cmd ["./apps"] diff --git a/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/positive_expected_result.json b/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/positive_expected_result.json index 5110e6420af..ea8f2844cd3 100644 --- a/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/positive_expected_result.json +++ b/assets/queries/dockerfile/multiple_cmd_instructions_listed/test/positive_expected_result.json @@ -1,8 +1,14 @@ [ - { - "queryName": "Multiple CMD Instructions Listed", - "severity": "LOW", - "line": 11, - "fileName": "positive.dockerfile" - } + { + "queryName": "Multiple CMD Instructions Listed", + "severity": "LOW", + "line": 11, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Multiple CMD Instructions Listed", + "severity": "LOW", + "line": 11, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/query.rego b/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/query.rego index bc821fe04fa..f7263e21ffc 100644 --- a/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/query.rego +++ b/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/query.rego @@ -9,9 +9,10 @@ CxPolicy[result] { cmdInst := [x | resource[j].Cmd == "entrypoint"; x := resource[j]] count(cmdInst) > 1 + from_command := dockerLib.get_original_from_command(resource) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, cmdInst[0].Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, cmdInst[0].Original]), "issueType": "RedundantAttribute", "keyExpectedValue": "There should be only one ENTRYPOINT instruction", "keyActualValue": sprintf("There are %d ENTRYPOINT instructions", [count(cmdInst)]), diff --git a/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/negative3.dockerfile b/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/negative3.dockerfile new file mode 100644 index 00000000000..87709ec452f --- /dev/null +++ b/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/negative3.dockerfile @@ -0,0 +1,12 @@ +from golang:1.7.3 +workdir /go/src/github.com/foo/href-counter/ +run go get -d -v golang.org/x/net/html +copy app.go . +run CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . +entrypoint [ "/opt/app/run.sh", "--port", "8080" ] + +from alpine:latest +run apk --no-cache add ca-certificates +workdir /root/ +copy --from=0 /go/src/github.com/foo/href-counter/app . +entrypoint [ "/opt/app/run.sh", "--port", "8080" ] \ No newline at end of file diff --git a/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/positive2.dockerfile b/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/positive2.dockerfile new file mode 100644 index 00000000000..2a55b12e841 --- /dev/null +++ b/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/positive2.dockerfile @@ -0,0 +1,12 @@ +from golang:1.7.3 +workdir /go/src/github.com/foo/href-counter/ +run go get -d -v golang.org/x/net/html +copy app.go . +run CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . + +from alpine:latest +run apk --no-cache add ca-certificates +workdir /root/ +copy --from=0 /go/src/github.com/foo/href-counter/app . +entrypoint [ "/opt/app/run.sh", "--port", "8080" ] +entrypoint [ "/opt/app/run.sh", "--port", "8000" ] diff --git a/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/positive_expected_result.json b/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/positive_expected_result.json index c1c67a870ea..8096a6b8ad3 100644 --- a/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/positive_expected_result.json +++ b/assets/queries/dockerfile/multiple_entrypoint_instructions_listed/test/positive_expected_result.json @@ -1,8 +1,14 @@ [ - { - "queryName": "Multiple ENTRYPOINT Instructions Listed", - "severity": "LOW", - "line": 11, - "fileName": "positive.dockerfile" - } + { + "queryName": "Multiple ENTRYPOINT Instructions Listed", + "severity": "LOW", + "line": 11, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Multiple ENTRYPOINT Instructions Listed", + "severity": "LOW", + "line": 11, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/query.rego b/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/query.rego index 4c07f1660e2..675a2e1e5e9 100644 --- a/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/query.rego +++ b/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/query.rego @@ -22,9 +22,10 @@ CxPolicy[result] { countCmdInst := count(lineCounter) countCmdInst > 0 + from_command := dockerLib.get_original_from_command(resource) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, lineCounter[0].Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, lineCounter[0].Original]), "issueType": "RedundantAttribute", "keyExpectedValue": sprintf("There isn´t any %s instruction that could be grouped", [upperName]), "keyActualValue": sprintf("There are %s instructions that could be grouped", [upperName]), diff --git a/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/negative6.dockerfile b/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/negative6.dockerfile new file mode 100644 index 00000000000..5fb5e41e709 --- /dev/null +++ b/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/negative6.dockerfile @@ -0,0 +1,2 @@ +from ubuntu +run apt-get install wget && wget https://…/downloadedfile.tar && tar xvzf downloadedfile.tar && rm downloadedfile.tar && apt-get remove wget diff --git a/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/positive4.dockerfile b/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/positive4.dockerfile new file mode 100644 index 00000000000..8ffdb7017cc --- /dev/null +++ b/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/positive4.dockerfile @@ -0,0 +1,6 @@ +from ubuntu +run apt-get install -y wget +run wget https://…/downloadedfile.tar +run tar xvzf downloadedfile.tar +run rm downloadedfile.tar +run apt-get remove wget diff --git a/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/positive_expected_result.json b/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/positive_expected_result.json index 7474b74c429..0057ce393cc 100644 --- a/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/positive_expected_result.json +++ b/assets/queries/dockerfile/multiple_run_add_copy_instructions_listed/test/positive_expected_result.json @@ -1,20 +1,26 @@ [ - { - "queryName": "Multiple RUN, ADD, COPY, Instructions Listed", - "severity": "LOW", - "line": 2, - "fileName": "positive1.dockerfile" - }, - { - "queryName": "Multiple RUN, ADD, COPY, Instructions Listed", - "severity": "LOW", - "line": 2, - "fileName": "positive2.dockerfile" - }, - { - "queryName": "Multiple RUN, ADD, COPY, Instructions Listed", - "severity": "LOW", - "line": 2, - "fileName": "positive3.dockerfile" - } -] + { + "queryName": "Multiple RUN, ADD, COPY, Instructions Listed", + "severity": "LOW", + "line": 2, + "fileName": "positive1.dockerfile" + }, + { + "queryName": "Multiple RUN, ADD, COPY, Instructions Listed", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Multiple RUN, ADD, COPY, Instructions Listed", + "severity": "LOW", + "line": 2, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Multiple RUN, ADD, COPY, Instructions Listed", + "severity": "LOW", + "line": 2, + "fileName": "positive4.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/query.rego b/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/query.rego index 2ab522b1177..e60290bfcce 100644 --- a/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/query.rego +++ b/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/query.rego @@ -9,9 +9,11 @@ CxPolicy[result] { resource.Cmd == "cmd" resource.JSON == false + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should be in the JSON Notation", [resource.Original]), "keyActualValue": sprintf("{{%s}} isn't in JSON Notation", [resource.Original]), @@ -25,9 +27,11 @@ CxPolicy[result] { resource.Cmd == "entrypoint" resource.JSON == false + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should be in the JSON Notation", [resource.Original]), "keyActualValue": sprintf("{{%s}} isn't in JSON Notation", [resource.Original]), diff --git a/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/negative3.dockerfile b/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/negative3.dockerfile new file mode 100644 index 00000000000..a9084a1cfec --- /dev/null +++ b/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/negative3.dockerfile @@ -0,0 +1,11 @@ +from alpine:3.5 +run apk add --update py2-pip +run sudo yum install bundler +run yum install +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] +entrypoint ["top", "-b"] \ No newline at end of file diff --git a/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/positive2.dockerfile b/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/positive2.dockerfile new file mode 100644 index 00000000000..217643dd8c2 --- /dev/null +++ b/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/positive2.dockerfile @@ -0,0 +1,11 @@ +from alpine:3.5 +run apk add --update py2-pip +run sudo yum install bundler +run yum install +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd [python, /usr/src/app/app.py] +entrypoint [top, -b] \ No newline at end of file diff --git a/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/positive_expected_result.json b/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/positive_expected_result.json index 779bfea3ef6..2a3d11dfd6c 100644 --- a/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/positive_expected_result.json +++ b/assets/queries/dockerfile/not_using_json_in_cmd_and_entrypoint_arguments/test/positive_expected_result.json @@ -2,11 +2,25 @@ { "queryName": "Not Using JSON In CMD And ENTRYPOINT Arguments", "severity": "MEDIUM", - "line": 10 + "line": 10, + "fileName": "positive.dockerfile" }, { "queryName": "Not Using JSON In CMD And ENTRYPOINT Arguments", "severity": "MEDIUM", - "line": 11 + "line": 11, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Not Using JSON In CMD And ENTRYPOINT Arguments", + "severity": "MEDIUM", + "line": 10, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Not Using JSON In CMD And ENTRYPOINT Arguments", + "severity": "MEDIUM", + "line": 11, + "fileName": "positive2.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/npm_install_without_pinned_version/query.rego b/assets/queries/dockerfile/npm_install_without_pinned_version/query.rego index f5d472adda6..4abd6d7cb54 100644 --- a/assets/queries/dockerfile/npm_install_without_pinned_version/query.rego +++ b/assets/queries/dockerfile/npm_install_without_pinned_version/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { runCmd := input.document[i].command[name][_] is_run_cmd(runCmd) @@ -21,9 +23,11 @@ CxPolicy[result] { token != "install" not valid_match(token) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, runCmd.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, runCmd.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("'%s' uses npm install with a pinned version", [runCmd.Original]), "keyActualValue": sprintf("'%s' does not uses npm install with a pinned version", [runCmd.Original]), diff --git a/assets/queries/dockerfile/npm_install_without_pinned_version/test/negative2.dockerfile b/assets/queries/dockerfile/npm_install_without_pinned_version/test/negative2.dockerfile new file mode 100644 index 00000000000..cb59f7ede0e --- /dev/null +++ b/assets/queries/dockerfile/npm_install_without_pinned_version/test/negative2.dockerfile @@ -0,0 +1,11 @@ +from node:12 +run npm install +run npm install sax@latest +run npm install sax@0.1.1 +run npm install sax@0.1.1 | grep fail && npm install sax@latest +run npm install git://github.com/npm/cli.git +run npm install git+ssh://git@github.com:npm/cli#semver:^5.0 +run npm install --production --no-cache +run npm config set registry && \ + npm install && \ + npx vite build --mode $VITE_MODE \ No newline at end of file diff --git a/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive2.dockerfile b/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive2.dockerfile new file mode 100644 index 00000000000..ea0b3b40465 --- /dev/null +++ b/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive2.dockerfile @@ -0,0 +1,8 @@ +from node:12 +run npm install sax +run npm install sax --no-cache +run npm install sax | grep fail && npm install sax@latest +run npm install sax@latest | grep fail && npm install sax +run npm install sax | grep fail && npm install sax +run npm i -g @angular/cli +run ["npm","add","sax"] diff --git a/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive_expected_result.json b/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive_expected_result.json index ec6862cd11b..563d30702a0 100644 --- a/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive_expected_result.json +++ b/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive_expected_result.json @@ -1,44 +1,86 @@ [ - { - "queryName": "NPM Install Command Without Pinned Version", - "severity": "MEDIUM", - "line": 2, - "filename": "positive1.dockerfile" - }, - { - "queryName": "NPM Install Command Without Pinned Version", - "severity": "MEDIUM", - "line": 3, - "filename": "positive1.dockerfile" - }, - { - "queryName": "NPM Install Command Without Pinned Version", - "severity": "MEDIUM", - "line": 4, - "filename": "positive1.dockerfile" - }, - { - "queryName": "NPM Install Command Without Pinned Version", - "severity": "MEDIUM", - "line": 5, - "filename": "positive1.dockerfile" - }, - { - "queryName": "NPM Install Command Without Pinned Version", - "severity": "MEDIUM", - "line": 6, - "filename": "positive1.dockerfile" - }, - { - "queryName": "NPM Install Command Without Pinned Version", - "severity": "MEDIUM", - "line": 7, - "filename": "positive1.dockerfile" - }, - { - "queryName": "NPM Install Command Without Pinned Version", - "severity": "MEDIUM", - "line": 8, - "filename": "positive1.dockerfile" - } + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 2, + "filename": "positive1.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 3, + "filename": "positive1.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 4, + "filename": "positive1.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 5, + "filename": "positive1.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 6, + "filename": "positive1.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 7, + "filename": "positive1.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 8, + "filename": "positive1.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 2, + "filename": "positive2.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 3, + "filename": "positive2.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 4, + "filename": "positive2.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 5, + "filename": "positive2.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 6, + "filename": "positive2.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 7, + "filename": "positive2.dockerfile" + }, + { + "queryName": "NPM Install Command Without Pinned Version", + "severity": "MEDIUM", + "line": 8, + "filename": "positive2.dockerfile" + }, ] \ No newline at end of file diff --git a/assets/queries/dockerfile/pip_install_keeping_cached_packages/query.rego b/assets/queries/dockerfile/pip_install_keeping_cached_packages/query.rego index 50eec9a5c4c..1412a5a176c 100644 --- a/assets/queries/dockerfile/pip_install_keeping_cached_packages/query.rego +++ b/assets/queries/dockerfile/pip_install_keeping_cached_packages/query.rego @@ -11,9 +11,11 @@ CxPolicy[result] { hasCacheFlag(values) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, values]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, values]), "issueType": "IncorrectValue", "keyExpectedValue": "The '--no-cache-dir' flag should be set when running 'pip/pip3 install'", "keyActualValue": "The '--no-cache-dir' flag isn't set when running 'pip/pip3 install'", @@ -30,9 +32,11 @@ CxPolicy[result] { not hasCacheFlagInList(resource.Value) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "The '--no-cache-dir' flag should be set when running 'pip/pip3 install'", "keyActualValue": "The '--no-cache-dir' flag isn't set when running 'pip/pip3 install'", diff --git a/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/negative2.dockerfile b/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/negative2.dockerfile new file mode 100644 index 00000000000..b8fe51dec35 --- /dev/null +++ b/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/negative2.dockerfile @@ -0,0 +1,7 @@ +from python:3 +run pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir nibabel pydicom matplotlib pillow && \ + pip install --no-cache-dir med2image +run pip3 install --no-cache-dir requests=2.7.0 +run ["pip3", "install", "requests=2.7.0", "--no-cache-dir"] +cmd ["cat", "/etc/os-release"] diff --git a/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive2.dockerfile b/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive2.dockerfile new file mode 100644 index 00000000000..116a81d85ad --- /dev/null +++ b/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive2.dockerfile @@ -0,0 +1,12 @@ +from python:3 +run pip install --upgrade pip && \ + pip install nibabel pydicom matplotlib pillow && \ + pip install med2image +cmd ["cat", "/etc/os-release"] + +from python:3.1 +run pip install --upgrade pip +run python -m pip install nibabel pydicom matplotlib pillow +run pip3 install requests=2.7.0 +run ["pip3", "install", "requests=2.7.0"] +cmd ["cat", "/etc/os-release"] diff --git a/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive_expected_result.json b/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive_expected_result.json index 727c06aeff6..ba31acf207f 100644 --- a/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive_expected_result.json +++ b/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive_expected_result.json @@ -1,27 +1,38 @@ [ - { - "queryName": "Pip install Keeping Cached Packages", - "severity": "LOW", - "line": 2 - }, - { - "queryName": "Pip install Keeping Cached Packages", - "severity": "LOW", - "line": 8 - }, - { - "queryName": "Pip install Keeping Cached Packages", - "severity": "LOW", - "line": 9 - }, - { - "queryName": "Pip install Keeping Cached Packages", - "severity": "LOW", - "line": 10 - }, - { - "queryName": "Pip install Keeping Cached Packages", - "severity": "LOW", - "line": 11 - } + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 8, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 9, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 10, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 11, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/query.rego b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/query.rego index 9a75bbd392b..a1d5aa2fce9 100644 --- a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/query.rego +++ b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "run" @@ -10,9 +12,11 @@ CxPolicy[result] { not is_full_path(path) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": "Using WORKDIR to change directory", "keyActualValue": sprintf("RUN %s'", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/negative3.dockerfile b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/negative3.dockerfile new file mode 100644 index 00000000000..cfd63dc6a9b --- /dev/null +++ b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/negative3.dockerfile @@ -0,0 +1,5 @@ +from nginx +env AUTHOR=Docker +workdir /usr/share/nginx/html +copy Hello_docker.html /usr/share/nginx/html +cmd cd /usr/share/nginx/html && sed -e s/Docker/"$AUTHOR"/ Hello_docker.html > index.html ; nginx -g 'daemon off;' \ No newline at end of file diff --git a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive2.dockerfile b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive2.dockerfile new file mode 100644 index 00000000000..8abcf679cba --- /dev/null +++ b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive2.dockerfile @@ -0,0 +1,17 @@ +from nginx +env AUTHOR=Docker +run cd /../share/nginx/html +copy Hello_docker.html /usr/share/nginx/html +cmd cd /usr/share/nginx/html && sed -e s/Docker/"$AUTHOR"/ Hello_docker.html > index.html ; nginx -g 'daemon off;' + +from nginx +env AUTHOR=Docker +run cd ../share/nginx/html +copy Hello_docker.html /usr/share/nginx/html +cmd cd /usr/share/nginx/html && sed -e s/Docker/"$AUTHOR"/ Hello_docker.html > index.html ; nginx -g 'daemon off;' + +from nginx +env AUTHOR=Docker +run cd /usr/../share/nginx/html +copy Hello_docker.html /usr/share/nginx/html +cmd cd /usr/share/nginx/html && sed -e s/Docker/"$AUTHOR"/ Hello_docker.html > index.html ; nginx -g 'daemon off;' diff --git a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive_expected_result.json b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive_expected_result.json index 4cba6c72f3f..6b424f1b2a4 100644 --- a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive_expected_result.json +++ b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive_expected_result.json @@ -1,20 +1,43 @@ [ - { - "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", - "severity": "LOW", - "line": 3, - "fileName": "positive.dockerfile" - }, - { - "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", - "severity": "LOW", - "line": 9, - "fileName": "positive.dockerfile" - }, - { - "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", - "severity": "LOW", - "line": 15, - "fileName": "positive.dockerfile" - } + { + "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", + "severity": "LOW", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", + "severity": "LOW", + "line": 9, + "fileName": "positive.dockerfile" + }, + { + "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", + "severity": "LOW", + "line": 15, + "fileName": "positive.dockerfile" + }, + { + "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", + "severity": "LOW", + "line": 9, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", + "severity": "LOW", + "line": 15, + "fileName": "positive2.dockerfile" + },{ + "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/run_using_apt/query.rego b/assets/queries/dockerfile/run_using_apt/query.rego index b7f210a8805..1976c18bec7 100644 --- a/assets/queries/dockerfile/run_using_apt/query.rego +++ b/assets/queries/dockerfile/run_using_apt/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { document := input.document[i] commands = document.command @@ -9,9 +11,10 @@ CxPolicy[result] { some j contains(commands[img][c].Value[j], "apt ") + from_command := dockerLib.get_original_from_command(commands[img]) result := { "documentId": document.id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [img, commands[img][c].Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, img, commands[img][c].Original]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instructions should not use the 'apt' program", "keyActualValue": "RUN instruction is invoking the 'apt' program", diff --git a/assets/queries/dockerfile/run_using_apt/test/negative2.dockerfile b/assets/queries/dockerfile/run_using_apt/test/negative2.dockerfile new file mode 100644 index 00000000000..0fbb58df873 --- /dev/null +++ b/assets/queries/dockerfile/run_using_apt/test/negative2.dockerfile @@ -0,0 +1,3 @@ +from busybox:1.0 +run apt-get install curl +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/run_using_apt/test/positive2.dockerfile b/assets/queries/dockerfile/run_using_apt/test/positive2.dockerfile new file mode 100644 index 00000000000..2c507976add --- /dev/null +++ b/assets/queries/dockerfile/run_using_apt/test/positive2.dockerfile @@ -0,0 +1,3 @@ +from busybox:1.0 +run apt install curl +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/run_using_apt/test/positive_expected_result.json b/assets/queries/dockerfile/run_using_apt/test/positive_expected_result.json index c6a5e011847..fdf680af097 100644 --- a/assets/queries/dockerfile/run_using_apt/test/positive_expected_result.json +++ b/assets/queries/dockerfile/run_using_apt/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Run Using apt", - "severity": "LOW", - "line": 2 - } + { + "queryName": "Run Using apt", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Run Using apt", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/run_using_sudo/query.rego b/assets/queries/dockerfile/run_using_sudo/query.rego index 224e4913438..a258365d826 100644 --- a/assets/queries/dockerfile/run_using_sudo/query.rego +++ b/assets/queries/dockerfile/run_using_sudo/query.rego @@ -9,9 +9,11 @@ CxPolicy[result] { hasSudo(resource.Value[0]) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction shouldn't contain sudo", "keyActualValue": "RUN instruction contains sudo", @@ -25,9 +27,11 @@ CxPolicy[result] { resource.Value[0] == "sudo" + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction shouldn't contain sudo", "keyActualValue": "RUN instruction contains sudo", diff --git a/assets/queries/dockerfile/run_using_sudo/test/negative2.dockerfile b/assets/queries/dockerfile/run_using_sudo/test/negative2.dockerfile new file mode 100644 index 00000000000..7e5ee45d32a --- /dev/null +++ b/assets/queries/dockerfile/run_using_sudo/test/negative2.dockerfile @@ -0,0 +1,10 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +run apt-get install sudo +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/run_using_sudo/test/positive2.dockerfile b/assets/queries/dockerfile/run_using_sudo/test/positive2.dockerfile new file mode 100644 index 00000000000..650b345cb74 --- /dev/null +++ b/assets/queries/dockerfile/run_using_sudo/test/positive2.dockerfile @@ -0,0 +1,9 @@ +from alpine:3.5 +run apk add --update py2-pip +run sudo pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/run_using_sudo/test/positive_expected_result.json b/assets/queries/dockerfile/run_using_sudo/test/positive_expected_result.json index 581fa52051a..da03ae5536a 100644 --- a/assets/queries/dockerfile/run_using_sudo/test/positive_expected_result.json +++ b/assets/queries/dockerfile/run_using_sudo/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "Run Using Sudo", - "severity": "MEDIUM", - "line": 3 - } + { + "queryName": "Run Using Sudo", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Run Using Sudo", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/run_using_wget_and_curl/query.rego b/assets/queries/dockerfile/run_using_wget_and_curl/query.rego index 617376f946c..9acf1c45407 100644 --- a/assets/queries/dockerfile/run_using_wget_and_curl/query.rego +++ b/assets/queries/dockerfile/run_using_wget_and_curl/query.rego @@ -11,9 +11,10 @@ CxPolicy[result] { count(curl) > 0 count(wget) > 0 + from_command := dockerLib.get_original_from_command(resource) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, curl[0]]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, curl[0]]), "issueType": "RedundantAttribute", "keyExpectedValue": "Exclusively using 'wget' or 'curl'", "keyActualValue": "Using both 'wget' and 'curl'", diff --git a/assets/queries/dockerfile/run_using_wget_and_curl/test/negative2.dockerfile b/assets/queries/dockerfile/run_using_wget_and_curl/test/negative2.dockerfile new file mode 100644 index 00000000000..d48fe91f7c6 --- /dev/null +++ b/assets/queries/dockerfile/run_using_wget_and_curl/test/negative2.dockerfile @@ -0,0 +1,4 @@ +from debian +run curl http://google.com +run curl http://bing.com +run ["curl", "http://bing.com"] diff --git a/assets/queries/dockerfile/run_using_wget_and_curl/test/positive2.dockerfile b/assets/queries/dockerfile/run_using_wget_and_curl/test/positive2.dockerfile new file mode 100644 index 00000000000..a78eab5ff90 --- /dev/null +++ b/assets/queries/dockerfile/run_using_wget_and_curl/test/positive2.dockerfile @@ -0,0 +1,8 @@ +from debian +run wget http://google.com +run curl http://bing.com + +from baseImage +run wget http://test.com +run curl http://bing.com +run ["curl", "http://bing.com"] diff --git a/assets/queries/dockerfile/run_using_wget_and_curl/test/positive_expected_result.json b/assets/queries/dockerfile/run_using_wget_and_curl/test/positive_expected_result.json index 82340b752d6..704421a805d 100644 --- a/assets/queries/dockerfile/run_using_wget_and_curl/test/positive_expected_result.json +++ b/assets/queries/dockerfile/run_using_wget_and_curl/test/positive_expected_result.json @@ -1,17 +1,38 @@ [ - { - "queryName": "Run Using 'wget' and 'curl'", - "severity": "LOW", - "line": 3 - }, - { - "queryName": "Run Using 'wget' and 'curl'", - "severity": "LOW", - "line": 7 - }, - { - "queryName": "Run Using 'wget' and 'curl'", - "severity": "LOW", - "line": 8 - } + { + "queryName": "Run Using 'wget' and 'curl'", + "severity": "LOW", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Run Using 'wget' and 'curl'", + "severity": "LOW", + "line": 7, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Run Using 'wget' and 'curl'", + "severity": "LOW", + "line": 8, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Run Using 'wget' and 'curl'", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Run Using 'wget' and 'curl'", + "severity": "LOW", + "line": 7, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Run Using 'wget' and 'curl'", + "severity": "LOW", + "line": 8, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/run_utilities_and_posix_commands/query.rego b/assets/queries/dockerfile/run_utilities_and_posix_commands/query.rego index 887ccb0aae6..acdf278b2a6 100644 --- a/assets/queries/dockerfile/run_utilities_and_posix_commands/query.rego +++ b/assets/queries/dockerfile/run_utilities_and_posix_commands/query.rego @@ -1,14 +1,18 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "run" containsCommand(resource) == true + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "There should be no dangerous commands or utilities executed", "keyActualValue": sprintf("Run instruction is executing the %s command", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/run_utilities_and_posix_commands/test/negative2.dockerfile b/assets/queries/dockerfile/run_utilities_and_posix_commands/test/negative2.dockerfile new file mode 100644 index 00000000000..d3aa7e141ae --- /dev/null +++ b/assets/queries/dockerfile/run_utilities_and_posix_commands/test/negative2.dockerfile @@ -0,0 +1,8 @@ +from ubuntu +run apt-get update && apt-get install -y x11vnc xvfb firefox +run mkdir ~/.vnc +run x11vnc -storepasswd 1234 ~/.vnc/passwd +run bash -c 'echo "firefox" >> /.bashrc' +run apt-get install nano vim +expose 5900 +cmd ["x11vnc", "-forever", "-usepw", "-create"] diff --git a/assets/queries/dockerfile/run_utilities_and_posix_commands/test/positive2.dockerfile b/assets/queries/dockerfile/run_utilities_and_posix_commands/test/positive2.dockerfile new file mode 100644 index 00000000000..3b72fdee3ee --- /dev/null +++ b/assets/queries/dockerfile/run_utilities_and_posix_commands/test/positive2.dockerfile @@ -0,0 +1,6 @@ +from golang:1.12.0-stretch +workdir /go +copy . /go +run top +run ["ps", "-d"] +cmd ["go", "run", "main.go"] diff --git a/assets/queries/dockerfile/run_utilities_and_posix_commands/test/positive_expected_result.json b/assets/queries/dockerfile/run_utilities_and_posix_commands/test/positive_expected_result.json index 9f366ada36a..1cccbe4fdac 100644 --- a/assets/queries/dockerfile/run_utilities_and_posix_commands/test/positive_expected_result.json +++ b/assets/queries/dockerfile/run_utilities_and_posix_commands/test/positive_expected_result.json @@ -1,12 +1,26 @@ [ - { - "queryName": "Run Utilities And POSIX Commands", - "severity": "INFO", - "line": 4 - }, - { - "queryName": "Run Utilities And POSIX Commands", - "severity": "INFO", - "line": 5 - } -] + { + "queryName": "Run Utilities And POSIX Commands", + "severity": "INFO", + "line": 4, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Run Utilities And POSIX Commands", + "severity": "INFO", + "line": 5, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Run Utilities And POSIX Commands", + "severity": "INFO", + "line": 4, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Run Utilities And POSIX Commands", + "severity": "INFO", + "line": 5, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/same_alias_in_different_froms/query.rego b/assets/queries/dockerfile/same_alias_in_different_froms/query.rego index 933f588f86f..1f3dc599518 100644 --- a/assets/queries/dockerfile/same_alias_in_different_froms/query.rego +++ b/assets/queries/dockerfile/same_alias_in_different_froms/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][com] resource.Cmd == "from" @@ -14,9 +16,10 @@ CxPolicy[result] { idx_2 := getIndex(aliasResource.Value) aliasResource.Value[idx_2] == nameAlias + from_command := dockerLib.get_original_from_command(input.document[i].command[name2]) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}", [aliasResource.Value[idx_2]]), + "searchKey": sprintf("%s={{%s}}", [from_command, aliasResource.Value[idx_2]]), "issueType": "IncorrectValue", "keyExpectedValue": "Different FROM commands don't have the same alias defined", "keyActualValue": sprintf("Different FROM commands with with the same alias '%s' defined", [aliasResource.Value[idx_2]]), diff --git a/assets/queries/dockerfile/same_alias_in_different_froms/test/negative2.dockerfile b/assets/queries/dockerfile/same_alias_in_different_froms/test/negative2.dockerfile new file mode 100644 index 00000000000..735a723879a --- /dev/null +++ b/assets/queries/dockerfile/same_alias_in_different_froms/test/negative2.dockerfile @@ -0,0 +1,5 @@ +from debian:jesse1 as build +run stuff + +from debian:jesse1 as another-alias +run more_stuff diff --git a/assets/queries/dockerfile/same_alias_in_different_froms/test/positive2.dockerfile b/assets/queries/dockerfile/same_alias_in_different_froms/test/positive2.dockerfile new file mode 100644 index 00000000000..1932587dc3d --- /dev/null +++ b/assets/queries/dockerfile/same_alias_in_different_froms/test/positive2.dockerfile @@ -0,0 +1,8 @@ +from baseImage +run Test + +from debian:jesse2 as build +run stuff + +from debian:jesse1 as build +run more_stuff diff --git a/assets/queries/dockerfile/same_alias_in_different_froms/test/positive_expected_result.json b/assets/queries/dockerfile/same_alias_in_different_froms/test/positive_expected_result.json index 9e65369181b..4f0c09802ac 100644 --- a/assets/queries/dockerfile/same_alias_in_different_froms/test/positive_expected_result.json +++ b/assets/queries/dockerfile/same_alias_in_different_froms/test/positive_expected_result.json @@ -1,7 +1,13 @@ [ - { - "queryName": "Same Alias In Different Froms", - "severity": "LOW", - "line": 4 - } + { + "queryName": "Same Alias In Different Froms", + "severity": "LOW", + "line": 4 + }, + { + "queryName": "Same Alias In Different Froms", + "severity": "LOW", + "line": 4, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/query.rego b/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/query.rego index 0f0ceedb0a7..5ba93023521 100644 --- a/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/query.rego +++ b/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/query.rego @@ -1,6 +1,7 @@ package Cx import data.generic.common as common_lib +import data.generic.dockerfile as dockerLib CxPolicy[result] { commands := input.document[i].command[name] @@ -19,9 +20,10 @@ CxPolicy[result] { not hasPipefail(commands, match.shell, j) + from_command := dockerLib.get_original_from_command(commands) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, runCmd.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, runCmd.Original]), "searchValue": match.shell, "issueType": "MissingAttribute", "keyExpectedValue": sprintf("'%s' has pipefail option set for pipe command with shell %s.", [runCmd.Original, match.shell]), @@ -47,9 +49,10 @@ CxPolicy[result] { cmdFormatted := replace(runCmd.Original, "\"", "'") + from_command := dockerLib.get_original_from_command(commands) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, runCmd.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, runCmd.Original]), "searchValue": match.shell, "issueType": "MissingAttribute", "keyExpectedValue": sprintf("'%s' has pipefail option set for pipe command with shell %s.", [cmdFormatted, match.shell]), diff --git a/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/negative2.dockerfile b/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/negative2.dockerfile new file mode 100644 index 00000000000..6a8d174d98d --- /dev/null +++ b/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/negative2.dockerfile @@ -0,0 +1,7 @@ +from node:12 +run pwsh SOME_CMD | SOME_OTHER_CMD +shell [ "zsh", "-o","pipefail" ] +run zsh ./some_output | ./some_script +shell [ "/bin/bash", "-o","pipefail" ] +run [ "/bin/bash", "./some_output", "./some_script" ] + diff --git a/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/positive2.dockerfile b/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/positive2.dockerfile new file mode 100644 index 00000000000..de691928f03 --- /dev/null +++ b/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/positive2.dockerfile @@ -0,0 +1,3 @@ +from node:12 +run zsh ./some_output | ./some_script +run [ "/bin/bash", "./some_output", "|", "./some_script" ] \ No newline at end of file diff --git a/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/positive_expected_result.json b/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/positive_expected_result.json index 66769b07386..5f7aab1d611 100644 --- a/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/positive_expected_result.json +++ b/assets/queries/dockerfile/shell_running_a_pipe_without_pipefail_flag/test/positive_expected_result.json @@ -1,12 +1,26 @@ [ - { - "queryName": "Shell Running A Pipe Without Pipefail Flag", - "severity": "LOW", - "line": 2 - }, - { - "queryName": "Shell Running A Pipe Without Pipefail Flag", - "severity": "LOW", - "line": 3 - } + { + "queryName": "Shell Running A Pipe Without Pipefail Flag", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Shell Running A Pipe Without Pipefail Flag", + "severity": "LOW", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Shell Running A Pipe Without Pipefail Flag", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Shell Running A Pipe Without Pipefail Flag", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/unix_ports_out_of_range/query.rego b/assets/queries/dockerfile/unix_ports_out_of_range/query.rego index 5278813156e..c4eca8ccc45 100644 --- a/assets/queries/dockerfile/unix_ports_out_of_range/query.rego +++ b/assets/queries/dockerfile/unix_ports_out_of_range/query.rego @@ -1,14 +1,18 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { command := input.document[i].command[name][_] command.Cmd == "expose" containsPortOutOfRange(command.Value) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, command.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, command.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "'EXPOSE' should not contain ports out of range [0, 65535]", "keyActualValue": "'EXPOSE' contains ports out of range [0, 65535]", diff --git a/assets/queries/dockerfile/unix_ports_out_of_range/test/negative2.dockerfile b/assets/queries/dockerfile/unix_ports_out_of_range/test/negative2.dockerfile new file mode 100644 index 00000000000..a1d39b6ed5c --- /dev/null +++ b/assets/queries/dockerfile/unix_ports_out_of_range/test/negative2.dockerfile @@ -0,0 +1,4 @@ +from gliderlabs/alpine:3.3 +run apk --no-cache add nginx +expose 3000 80 443 22 +cmd ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/unix_ports_out_of_range/test/positive2.dockerfile b/assets/queries/dockerfile/unix_ports_out_of_range/test/positive2.dockerfile new file mode 100644 index 00000000000..0f1e9c0f7db --- /dev/null +++ b/assets/queries/dockerfile/unix_ports_out_of_range/test/positive2.dockerfile @@ -0,0 +1,4 @@ +from gliderlabs/alpine:3.3 +run apk --no-cache add nginx +expose 65536/tcp 80 443 22 +cmd ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/unix_ports_out_of_range/test/positive_expected_result.json b/assets/queries/dockerfile/unix_ports_out_of_range/test/positive_expected_result.json index 5d57ac73d0c..45a3ec6dce2 100644 --- a/assets/queries/dockerfile/unix_ports_out_of_range/test/positive_expected_result.json +++ b/assets/queries/dockerfile/unix_ports_out_of_range/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "UNIX Ports Out Of Range", - "severity": "INFO", - "line": 3 - } + { + "queryName": "UNIX Ports Out Of Range", + "severity": "INFO", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "UNIX Ports Out Of Range", + "severity": "INFO", + "line": 3, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/unpinned_package_version_in_apk_add/query.rego b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/query.rego index eed1cad8afc..77212be60e1 100644 --- a/assets/queries/dockerfile/unpinned_package_version_in_apk_add/query.rego +++ b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/query.rego @@ -22,9 +22,11 @@ CxPolicy[result] { some j analyzePackages(j, packages[j], packages, length) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction with 'apk add ' should use package pinning form 'apk add ='", "keyActualValue": sprintf("RUN instruction %s does not use package pinning form", [resource.Value[0]]), @@ -51,9 +53,11 @@ CxPolicy[result] { some j analyzePackages(j, packages[j], packages, length) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction with 'apk add ' should use package pinning form 'apk add ='", "keyActualValue": sprintf("RUN instruction %s does not use package pinning form", [resource.Value[0]]), @@ -79,9 +83,11 @@ CxPolicy[result] { some j analyzePackages(j, packages[j], packages, length) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction with 'apk add ' should use package pinning form 'apk add ='", "keyActualValue": sprintf("RUN instruction %s does not use package pinning form", [resource.Value[0]]), @@ -103,9 +109,11 @@ CxPolicy[result] { regex.match("^[a-zA-Z]", resource.Value[j]) not docker_lib.withVersion(resource.Value[j]) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "searchValue": resource.Value[j], "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction with 'apk add ' should use package pinning form 'apk add ='", diff --git a/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/negative3.dockerfile b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/negative3.dockerfile new file mode 100644 index 00000000000..7e7f239eea8 --- /dev/null +++ b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/negative3.dockerfile @@ -0,0 +1,20 @@ +from alpine:3.4 +run apk add --update py-pip=7.1.2-r0 +run sudo pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] + +from alpine:3.1 +run apk add py-pip=7.1.2-r0 +run ["apk", "add", "py-pip=7.1.2-r0"] +run sudo pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive2.dockerfile b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive2.dockerfile new file mode 100644 index 00000000000..d0356a93875 --- /dev/null +++ b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive2.dockerfile @@ -0,0 +1,25 @@ +from alpine:3.9 +run apk add --update py-pip +run sudo pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +env TEST="test" +cmd ["python", "/usr/src/app/app.py"] + +from alpine:3.7 +run apk add py-pip && apk add tea +run apk add py-pip \ + && rm -rf /tmp/* +run apk add --dir /dir libimagequant \ + && minidlna +run ["apk", "add", "py-pip"] +run sudo pip install --upgrade pip +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python"] diff --git a/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive_expected_result.json b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive_expected_result.json index 9f377d63c28..12d14d397df 100644 --- a/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive_expected_result.json +++ b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive_expected_result.json @@ -1,27 +1,62 @@ [ - { - "queryName": "Unpinned Package Version in Apk Add", - "severity": "MEDIUM", - "line": 2 - }, - { - "queryName": "Unpinned Package Version in Apk Add", - "severity": "MEDIUM", - "line": 13 - }, - { - "queryName": "Unpinned Package Version in Apk Add", - "severity": "MEDIUM", - "line": 14 - }, - { - "queryName": "Unpinned Package Version in Apk Add", - "severity": "MEDIUM", - "line": 16 - }, - { - "queryName": "Unpinned Package Version in Apk Add", - "severity": "MEDIUM", - "line": 18 - } -] + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 13, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 14, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 16, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 18, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 13, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 14, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 16, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Apk Add", + "severity": "MEDIUM", + "line": 18, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/unpinned_package_version_in_pip_install/query.rego b/assets/queries/dockerfile/unpinned_package_version_in_pip_install/query.rego index 268199179fb..2a07790d9a0 100644 --- a/assets/queries/dockerfile/unpinned_package_version_in_pip_install/query.rego +++ b/assets/queries/dockerfile/unpinned_package_version_in_pip_install/query.rego @@ -23,9 +23,11 @@ CxPolicy[result] { some j analyzePackages(j, refactorPackages[j], packages, length) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction with 'pip/pip3 install ' should use package pinning form 'pip/pip3 install ='", "keyActualValue": sprintf("RUN instruction %s does not use package pinning form", [commands]), @@ -47,9 +49,11 @@ CxPolicy[result] { regex.match("^[a-zA-Z]", resource.Value[j]) == true not dockerLib.withVersion(resource.Value[j]) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction with 'pip/pip3 install ' should use package pinning form 'pip/pip3 install ='", "keyActualValue": sprintf("RUN instruction %s does not use package pinning form", [resource.Value[j]]), diff --git a/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/negative4.dockerfile b/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/negative4.dockerfile new file mode 100644 index 00000000000..0ab18ef4643 --- /dev/null +++ b/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/negative4.dockerfile @@ -0,0 +1,20 @@ +from alpine:3.4 +run apk add --update py-pip=7.1.2-r0 +run sudo pip install --upgrade pip=20.3 connexion=2.7.0 +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] + +from alpine:3.1 +run apk add py-pip=7.1.2-r0 +run sudo pip install --upgrade pip=20.3 connexion=2.7.0 +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +run pip3 install requests=2.7.0 +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/positive2.dockerfile b/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/positive2.dockerfile new file mode 100644 index 00000000000..d60c4c736af --- /dev/null +++ b/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/positive2.dockerfile @@ -0,0 +1,22 @@ +from alpine:3.9 +run apk add --update py-pip=7.1.2-r0 +run pip install --user pip +run ["pip", "install", "connexion"] +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +env TEST="test" +cmd ["python", "/usr/src/app/app.py"] + +from alpine:3.7 +run apk add --update py-pip=7.1.2-r0 +run pip install connexion +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +run pip3 install requests +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python"] diff --git a/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/positive_expected_result.json b/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/positive_expected_result.json index 4ffe50570bf..9c3e92bb647 100644 --- a/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/positive_expected_result.json +++ b/assets/queries/dockerfile/unpinned_package_version_in_pip_install/test/positive_expected_result.json @@ -1,26 +1,50 @@ [ - { - "queryName": "Unpinned Package Version in Pip Install", - "severity": "MEDIUM", - "line": 3, - "filename": "positive1.dockerfile" - }, - { - "queryName": "Unpinned Package Version in Pip Install", - "severity": "MEDIUM", - "line": 4, - "filename": "positive1.dockerfile" - }, - { - "queryName": "Unpinned Package Version in Pip Install", - "severity": "MEDIUM", - "line": 15, - "filename": "positive1.dockerfile" - }, - { - "queryName": "Unpinned Package Version in Pip Install", - "severity": "MEDIUM", - "line": 18, - "filename": "positive1.dockerfile" - } -] + { + "queryName": "Unpinned Package Version in Pip Install", + "severity": "MEDIUM", + "line": 3, + "filename": "positive1.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Pip Install", + "severity": "MEDIUM", + "line": 4, + "filename": "positive1.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Pip Install", + "severity": "MEDIUM", + "line": 15, + "filename": "positive1.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Pip Install", + "severity": "MEDIUM", + "line": 18, + "filename": "positive1.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Pip Install", + "severity": "MEDIUM", + "line": 3, + "filename": "positive2.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Pip Install", + "severity": "MEDIUM", + "line": 4, + "filename": "positive2.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Pip Install", + "severity": "MEDIUM", + "line": 15, + "filename": "positive2.dockerfile" + }, + { + "queryName": "Unpinned Package Version in Pip Install", + "severity": "MEDIUM", + "line": 18, + "filename": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/query.rego b/assets/queries/dockerfile/update_instruction_alone/query.rego index 9bf0c5837c4..391e7a712db 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { # Check if there is a command that runs install before update resource := input.document[i].command[name][_] @@ -20,9 +22,11 @@ CxPolicy[result] { not checkFollowedBy(update, install) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be followed by 'RUN %s %s' in the same 'RUN' statement", [packageManager, pkg_installer[packageManager], packageManager, pkg_updater[packageManager]]), "keyActualValue": sprintf("Instruction 'RUN %s %s' isn't followed by 'RUN %s %s in the same 'RUN' statement", [packageManager, pkg_installer[packageManager], packageManager, pkg_updater[packageManager]]), @@ -60,7 +64,7 @@ CxPolicy[result] { result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, nextResource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, nextResource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be combined with 'RUN %s %s' in the same 'RUN' statement", [nextPackageManager, pkg_installer[nextPackageManager], nextPackageManager, pkg_updater[nextPackageManager]]), "keyActualValue": sprintf("Instruction 'RUN %s %s' isn't combined with 'RUN %s %s in the same 'RUN' statement", [nextPackageManager, pkg_installer[nextPackageManager], nextPackageManager, pkg_updater[nextPackageManager]]), diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative12.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative12.dockerfile new file mode 100644 index 00000000000..ad75faf9819 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative12.dockerfile @@ -0,0 +1,8 @@ +from ubuntu:18.04 +run apt-get update \ + && apt-get install -y --no-install-recommends mysql-client \ + && rm -rf /var/lib/apt/lists/* +run apk update \ + && apk add --no-cache git ca-certificates +run apk --update add easy-rsa +entrypoint ["mysql"] diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive8.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive8.dockerfile new file mode 100644 index 00000000000..4b49de8c58a --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive8.dockerfile @@ -0,0 +1,5 @@ +from alpine:latest +run apk update +run apk add nginx + +cmd ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive_expected_result.json b/assets/queries/dockerfile/update_instruction_alone/test/positive_expected_result.json index 64b7e65cd1f..568f9337486 100644 --- a/assets/queries/dockerfile/update_instruction_alone/test/positive_expected_result.json +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive_expected_result.json @@ -1,44 +1,50 @@ [ - { - "queryName": "Update Instruction Alone", - "severity": "LOW", - "line": 3, - "fileName": "positive1.dockerfile" - }, - { - "queryName": "Update Instruction Alone", - "severity": "LOW", - "line": 3, - "fileName": "positive2.dockerfile" - }, - { - "queryName": "Update Instruction Alone", - "severity": "LOW", - "line": 3, - "fileName": "positive3.dockerfile" - }, - { - "queryName": "Update Instruction Alone", - "severity": "LOW", - "line": 3, - "fileName": "positive4.dockerfile" - }, - { - "queryName": "Update Instruction Alone", - "severity": "LOW", - "line": 3, - "fileName": "positive5.dockerfile" - }, - { - "queryName": "Update Instruction Alone", - "severity": "LOW", - "line": 3, - "fileName": "positive6.dockerfile" - }, - { - "queryName": "Update Instruction Alone", - "severity": "LOW", - "line": 3, - "fileName": "positive7.dockerfile" - } + { + "queryName": "Update Instruction Alone", + "severity": "LOW", + "line": 3, + "fileName": "positive1.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "LOW", + "line": 3, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "LOW", + "line": 3, + "fileName": "positive4.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "LOW", + "line": 3, + "fileName": "positive5.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "LOW", + "line": 3, + "fileName": "positive6.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "LOW", + "line": 3, + "fileName": "positive7.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "LOW", + "line": 3, + "fileName": "positive8.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/using_platform_with_from/query.rego b/assets/queries/dockerfile/using_platform_with_from/query.rego index 8e133aece1e..2496fb1baba 100644 --- a/assets/queries/dockerfile/using_platform_with_from/query.rego +++ b/assets/queries/dockerfile/using_platform_with_from/query.rego @@ -1,6 +1,7 @@ package Cx import data.generic.common as common_lib +import data.generic.dockerfile as dockerLib CxPolicy[result] { resource := input.document[i].command[name][_] @@ -8,11 +9,13 @@ CxPolicy[result] { contains(resource.Flags[j], "--platform") contains(resource.Cmd, "from") + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("FROM={{%s}}.{{%s}} should not use the '--platform' flag", [name, resource.Original]), - "keyActualValue": sprintf("FROM={{%s}}.{{%s}} is using the '--platform' flag", [name, resource.Original]), + "keyExpectedValue": sprintf("%s={{%s}}.{{%s}} should not use the '--platform' flag", [from_command, name, resource.Original]), + "keyActualValue": sprintf("%s={{%s}}.{{%s}} is using the '--platform' flag", [from_command, name, resource.Original]), } } diff --git a/assets/queries/dockerfile/using_platform_with_from/test/negative2.dockerfile b/assets/queries/dockerfile/using_platform_with_from/test/negative2.dockerfile new file mode 100644 index 00000000000..04dc547bc08 --- /dev/null +++ b/assets/queries/dockerfile/using_platform_with_from/test/negative2.dockerfile @@ -0,0 +1,6 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +label maintainer="SvenDowideit@home.org.au" +copy requirements.txt /usr/src/app/ +from baseimage as baseimage-build diff --git a/assets/queries/dockerfile/using_platform_with_from/test/positive2.dockerfile b/assets/queries/dockerfile/using_platform_with_from/test/positive2.dockerfile new file mode 100644 index 00000000000..c0529ec2a65 --- /dev/null +++ b/assets/queries/dockerfile/using_platform_with_from/test/positive2.dockerfile @@ -0,0 +1,6 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +label maintainer="SvenDowideit@home.org.au" +copy requirements.txt /usr/src/app/ +from --platform=arm64 baseimage as baseimage-build diff --git a/assets/queries/dockerfile/using_platform_with_from/test/positive_expected_result.json b/assets/queries/dockerfile/using_platform_with_from/test/positive_expected_result.json index 17bce5638c8..21a2a3f1b72 100644 --- a/assets/queries/dockerfile/using_platform_with_from/test/positive_expected_result.json +++ b/assets/queries/dockerfile/using_platform_with_from/test/positive_expected_result.json @@ -1,8 +1,14 @@ [ - { - "queryName": "Using Platform Flag with FROM Command", - "severity": "INFO", - "line": 6, - "fileName": "positive1.dockerfile" - } + { + "queryName": "Using Platform Flag with FROM Command", + "severity": "INFO", + "line": 6, + "fileName": "positive1.dockerfile" + }, + { + "queryName": "Using Platform Flag with FROM Command", + "severity": "INFO", + "line": 6, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/using_unnamed_build_stages/query.rego b/assets/queries/dockerfile/using_unnamed_build_stages/query.rego index ff621dc15f8..df91819abb7 100644 --- a/assets/queries/dockerfile/using_unnamed_build_stages/query.rego +++ b/assets/queries/dockerfile/using_unnamed_build_stages/query.rego @@ -1,5 +1,7 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { commands := input.document[i].command[name][_] @@ -11,9 +13,11 @@ CxPolicy[result] { to_number(flag_split[1]) > -1 + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, commands.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, commands.Original]), "issueType": "IncorrectValue", "keyExpectedValue": "COPY '--from' should reference a previously defined FROM alias", "keyActualValue": "COPY '--from' does not reference a previously defined FROM alias", diff --git a/assets/queries/dockerfile/using_unnamed_build_stages/test/negative2.dockerfile b/assets/queries/dockerfile/using_unnamed_build_stages/test/negative2.dockerfile new file mode 100644 index 00000000000..c38778c6031 --- /dev/null +++ b/assets/queries/dockerfile/using_unnamed_build_stages/test/negative2.dockerfile @@ -0,0 +1,12 @@ +from golang:1.7.3 AS builder +workdir /go/src/github.com/foo/href-counter/ +run go get -d -v golang.org/x/net/html +copy app.go . +run CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . + +# another dockerfile +from alpine:latest +run apk --no-cache add ca-certificates +workdir /root/ +copy --from=builder /go/src/github.com/foo/href-counter/app . +cmd ["./app"] diff --git a/assets/queries/dockerfile/using_unnamed_build_stages/test/positive2.dockerfile b/assets/queries/dockerfile/using_unnamed_build_stages/test/positive2.dockerfile new file mode 100644 index 00000000000..b96bdaac1c7 --- /dev/null +++ b/assets/queries/dockerfile/using_unnamed_build_stages/test/positive2.dockerfile @@ -0,0 +1,11 @@ +from golang:1.16 +workdir /go/src/github.com/foo/href-counter/ +run go get -d -v golang.org/x/net/html +copy app.go ./ +run CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . + +from alpine:latest +run apk --no-cache add ca-certificates +workdir /root/ +copy --from=0 /go/src/github.com/foo/href-counter/app ./ +cmd ["./app"] diff --git a/assets/queries/dockerfile/using_unnamed_build_stages/test/positive_expected_result.json b/assets/queries/dockerfile/using_unnamed_build_stages/test/positive_expected_result.json index d0e9eb1f3db..72b72f46fb2 100644 --- a/assets/queries/dockerfile/using_unnamed_build_stages/test/positive_expected_result.json +++ b/assets/queries/dockerfile/using_unnamed_build_stages/test/positive_expected_result.json @@ -4,5 +4,11 @@ "severity": "LOW", "line": 10, "filename": "positive1.dockerfile" + }, + { + "queryName": "Using Unnamed Build Stages", + "severity": "LOW", + "line": 10, + "filename": "positive2.dockerfile" } -] +] \ No newline at end of file diff --git a/assets/queries/dockerfile/workdir_path_not_absolute/query.rego b/assets/queries/dockerfile/workdir_path_not_absolute/query.rego index a6d8fbeabf3..f6505433c57 100644 --- a/assets/queries/dockerfile/workdir_path_not_absolute/query.rego +++ b/assets/queries/dockerfile/workdir_path_not_absolute/query.rego @@ -1,13 +1,17 @@ package Cx +import data.generic.dockerfile as dockerLib + CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "workdir" not regex.match("(^\"?/[A-z0-9-_+]*)|(^\"?[A-z0-9-_+]:\\\\.*)|(^\"?\\$[{}A-z0-9-_+].*)", resource.Value[0]) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.WORKDIR={{%s}}", [name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.WORKDIR={{%s}}", [from_command, name, resource.Value[0]]), "issueType": "IncorrectValue", #"MissingAttribute" / "RedundantAttribute" "keyExpectedValue": "'WORKDIR' Command has absolute path", "keyActualValue": "'WORKDIR' Command doesn't have absolute path", diff --git a/assets/queries/dockerfile/workdir_path_not_absolute/test/negative2.dockerfile b/assets/queries/dockerfile/workdir_path_not_absolute/test/negative2.dockerfile new file mode 100644 index 00000000000..aa660c1b737 --- /dev/null +++ b/assets/queries/dockerfile/workdir_path_not_absolute/test/negative2.dockerfile @@ -0,0 +1,17 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +workdir /path/to/workdir +workdir "/path/to/workdir" +workdir / +workdir c:\\windows +env DIRPATH=/path +env GLASSFISH_ARCHIVE glassfish5 +workdir $DIRPATH/$DIRNAME +workdir ${GLASSFISH_HOME}/bin +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/workdir_path_not_absolute/test/positive2.dockerfile b/assets/queries/dockerfile/workdir_path_not_absolute/test/positive2.dockerfile new file mode 100644 index 00000000000..bc3c52343fc --- /dev/null +++ b/assets/queries/dockerfile/workdir_path_not_absolute/test/positive2.dockerfile @@ -0,0 +1,11 @@ +from alpine:3.5 +run apk add --update py2-pip +run pip install --upgrade pip +workdir /path/to/workdir +workdir workdir +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/workdir_path_not_absolute/test/positive_expected_result.json b/assets/queries/dockerfile/workdir_path_not_absolute/test/positive_expected_result.json index ece07faaf7f..bd94ad4b78f 100644 --- a/assets/queries/dockerfile/workdir_path_not_absolute/test/positive_expected_result.json +++ b/assets/queries/dockerfile/workdir_path_not_absolute/test/positive_expected_result.json @@ -1,7 +1,14 @@ [ - { - "queryName": "WORKDIR Path Not Absolute", - "severity": "LOW", - "line": 5 - } + { + "queryName": "WORKDIR Path Not Absolute", + "severity": "LOW", + "line": 5, + "fileName": "positive.dockerfile" + }, + { + "queryName": "WORKDIR Path Not Absolute", + "severity": "LOW", + "line": 5, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/yum_clean_all_missing/query.rego b/assets/queries/dockerfile/yum_clean_all_missing/query.rego index 556f93f16b5..2cea845cf5c 100644 --- a/assets/queries/dockerfile/yum_clean_all_missing/query.rego +++ b/assets/queries/dockerfile/yum_clean_all_missing/query.rego @@ -15,9 +15,11 @@ CxPolicy[result] { not containsCleanAfterYum(command) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should have 'yum clean all' after 'yum install' command", [resource.Original]), "keyActualValue": sprintf("{{%s}} doesn't have 'yum clean all' after 'yum install' command", [resource.Original]), diff --git a/assets/queries/dockerfile/yum_clean_all_missing/test/negative3.dockerfile b/assets/queries/dockerfile/yum_clean_all_missing/test/negative3.dockerfile new file mode 100644 index 00000000000..a3fcb3e7a29 --- /dev/null +++ b/assets/queries/dockerfile/yum_clean_all_missing/test/negative3.dockerfile @@ -0,0 +1,14 @@ +from alpine:3.5 +run apk add --update py2-pip +run yum install \ + yum clean all +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] + +from alpine:3.4 +run yum -y install \ + yum clean all diff --git a/assets/queries/dockerfile/yum_clean_all_missing/test/positive2.dockerfile b/assets/queries/dockerfile/yum_clean_all_missing/test/positive2.dockerfile new file mode 100644 index 00000000000..a38c8a8f68b --- /dev/null +++ b/assets/queries/dockerfile/yum_clean_all_missing/test/positive2.dockerfile @@ -0,0 +1,13 @@ +from alpine:3.5 +run apk add --update py2-pip +run yum install +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] + +from alpine:3.4 +run yum clean all \ + yum -y install diff --git a/assets/queries/dockerfile/yum_clean_all_missing/test/positive_expected_result.json b/assets/queries/dockerfile/yum_clean_all_missing/test/positive_expected_result.json index f4e28bb33cf..100dd704469 100644 --- a/assets/queries/dockerfile/yum_clean_all_missing/test/positive_expected_result.json +++ b/assets/queries/dockerfile/yum_clean_all_missing/test/positive_expected_result.json @@ -1,8 +1,14 @@ [ - { - "queryName": "Yum Clean All Missing", - "severity": "LOW", - "line": 12, - "fileName": "positive.dockerfile" - } + { + "queryName": "Yum Clean All Missing", + "severity": "LOW", + "line": 12, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Yum Clean All Missing", + "severity": "LOW", + "line": 12, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/yum_install_allows_manual_input/query.rego b/assets/queries/dockerfile/yum_install_allows_manual_input/query.rego index 1c7fb4f21b6..b5b3a6a9e70 100644 --- a/assets/queries/dockerfile/yum_install_allows_manual_input/query.rego +++ b/assets/queries/dockerfile/yum_install_allows_manual_input/query.rego @@ -12,9 +12,11 @@ CxPolicy[result] { not avoidManualInput(command) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should avoid manual input", [resource.Original]), "keyActualValue": sprintf("{{%s}} doesn't avoid manual input", [resource.Original]), @@ -30,9 +32,11 @@ CxPolicy[result] { not avoidManualInputInList(resource.Value) + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("{{%s}} should avoid manual input", [resource.Original]), "keyActualValue": sprintf("{{%s}} doesn't avoid manual input", [resource.Original]), diff --git a/assets/queries/dockerfile/yum_install_allows_manual_input/test/negative2.dockerfile b/assets/queries/dockerfile/yum_install_allows_manual_input/test/negative2.dockerfile new file mode 100644 index 00000000000..6cb32a326e6 --- /dev/null +++ b/assets/queries/dockerfile/yum_install_allows_manual_input/test/negative2.dockerfile @@ -0,0 +1,9 @@ +from alpine:3.5 +run apk add --update py2-pip +run sudo yum install -y bundler +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] \ No newline at end of file diff --git a/assets/queries/dockerfile/yum_install_allows_manual_input/test/positive2.dockerfile b/assets/queries/dockerfile/yum_install_allows_manual_input/test/positive2.dockerfile new file mode 100644 index 00000000000..6fe942813de --- /dev/null +++ b/assets/queries/dockerfile/yum_install_allows_manual_input/test/positive2.dockerfile @@ -0,0 +1,10 @@ +from alpine:3.5 +run apk add --update py2-pip +run sudo yum install bundler +run ["sudo yum", "install", "bundler"] +copy requirements.txt /usr/src/app/ +run pip install --no-cache-dir -r /usr/src/app/requirements.txt +copy app.py /usr/src/app/ +copy templates/index.html /usr/src/app/templates/ +expose 5000 +cmd ["python", "/usr/src/app/app.py"] diff --git a/assets/queries/dockerfile/yum_install_allows_manual_input/test/positive_expected_result.json b/assets/queries/dockerfile/yum_install_allows_manual_input/test/positive_expected_result.json index c6fa582d3aa..ed762eee0d3 100644 --- a/assets/queries/dockerfile/yum_install_allows_manual_input/test/positive_expected_result.json +++ b/assets/queries/dockerfile/yum_install_allows_manual_input/test/positive_expected_result.json @@ -1,12 +1,26 @@ [ - { - "queryName": "Yum Install Allows Manual Input", - "severity": "LOW", - "line": 3 - }, - { - "queryName": "Yum Install Allows Manual Input", - "severity": "LOW", - "line": 4 - } + { + "queryName": "Yum Install Allows Manual Input", + "severity": "LOW", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Yum Install Allows Manual Input", + "severity": "LOW", + "line": 4, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Yum Install Allows Manual Input", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Yum Install Allows Manual Input", + "severity": "LOW", + "line": 4, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/yum_install_without_version/query.rego b/assets/queries/dockerfile/yum_install_without_version/query.rego index fbc9c0bf295..1e51dc24f57 100644 --- a/assets/queries/dockerfile/yum_install_without_version/query.rego +++ b/assets/queries/dockerfile/yum_install_without_version/query.rego @@ -19,9 +19,11 @@ CxPolicy[result] { some j analyzePackages(j, packages[j], packages, length) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "searchValue": packages[j], "issueType": "IncorrectValue", "keyExpectedValue": "The package version should always be specified when using yum install", @@ -43,9 +45,11 @@ CxPolicy[result] { regex.match("^[a-zA-Z]", resource.Value[j]) == true not docker_lib.withVersion(resource.Value[j]) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "searchValue": resource.Value[j], "issueType": "IncorrectValue", "keyExpectedValue": "The package version should always be specified when using yum install", diff --git a/assets/queries/dockerfile/yum_install_without_version/test/negative2.dockerfile b/assets/queries/dockerfile/yum_install_without_version/test/negative2.dockerfile new file mode 100644 index 00000000000..ba8e3557b85 --- /dev/null +++ b/assets/queries/dockerfile/yum_install_without_version/test/negative2.dockerfile @@ -0,0 +1,8 @@ +from opensuse/leap:15.2 +run yum install -y httpd-2.24.2 && yum clean all +healthcheck CMD curl --fail http://localhost:3000 || exit 1 + + +from opensuse/leap:15.3 +env RETHINKDB_PACKAGE_VERSION 2.4.0~0trusty +run yum install -y rethinkdb-$RETHINKDB_PACKAGE_VERSION && yum clean all diff --git a/assets/queries/dockerfile/yum_install_without_version/test/positive2.dockerfile b/assets/queries/dockerfile/yum_install_without_version/test/positive2.dockerfile new file mode 100644 index 00000000000..7cc1025defd --- /dev/null +++ b/assets/queries/dockerfile/yum_install_without_version/test/positive2.dockerfile @@ -0,0 +1,4 @@ +from opensuse/leap:15.2 +run yum install -y httpd && yum clean all +run ["yum", "install", "httpd"] +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/yum_install_without_version/test/positive_expected_result.json b/assets/queries/dockerfile/yum_install_without_version/test/positive_expected_result.json index 2ed431a5849..b7670737f6c 100644 --- a/assets/queries/dockerfile/yum_install_without_version/test/positive_expected_result.json +++ b/assets/queries/dockerfile/yum_install_without_version/test/positive_expected_result.json @@ -1,12 +1,26 @@ [ - { - "queryName": "Yum install Without Version", - "severity": "MEDIUM", - "line": 2 - }, - { - "queryName": "Yum install Without Version", - "severity": "MEDIUM", - "line": 3 - } -] + { + "queryName": "Yum install Without Version", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Yum install Without Version", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Yum install Without Version", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Yum install Without Version", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive2.dockerfile" + } +] \ No newline at end of file diff --git a/assets/queries/dockerfile/zypper_install_without_version/query.rego b/assets/queries/dockerfile/zypper_install_without_version/query.rego index 92ed90a266b..95a90e1a05b 100644 --- a/assets/queries/dockerfile/zypper_install_without_version/query.rego +++ b/assets/queries/dockerfile/zypper_install_without_version/query.rego @@ -19,9 +19,11 @@ CxPolicy[result] { some j analyzePackages(j, packages[j], packages, length) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "searchValue": packages[j], "issueType": "IncorrectValue", "keyExpectedValue": "The package version should always be specified when using zypper install", @@ -43,9 +45,11 @@ CxPolicy[result] { regex.match("^[a-zA-Z]", resource.Value[j]) == true not docker_lib.withVersion(resource.Value[j]) + stage := input.document[i].command[name] + from_command := docker_lib.get_original_from_command(stage) result := { "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.{{%s}}", [name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), "searchValue": resource.Value[j], "issueType": "IncorrectValue", "keyExpectedValue": "The package version should always be specified when using zypper install", diff --git a/assets/queries/dockerfile/zypper_install_without_version/test/negative2.dockerfile b/assets/queries/dockerfile/zypper_install_without_version/test/negative2.dockerfile new file mode 100644 index 00000000000..d9fbcfc5dbb --- /dev/null +++ b/assets/queries/dockerfile/zypper_install_without_version/test/negative2.dockerfile @@ -0,0 +1,3 @@ +from opensuse/leap:15.2 +run zypper install -y httpd=2.4.46 && zypper clean +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/zypper_install_without_version/test/positive2.dockerfile b/assets/queries/dockerfile/zypper_install_without_version/test/positive2.dockerfile new file mode 100644 index 00000000000..8a17fc54f81 --- /dev/null +++ b/assets/queries/dockerfile/zypper_install_without_version/test/positive2.dockerfile @@ -0,0 +1,4 @@ +from opensuse/leap:15.2 +run zypper install -y httpd && zypper clean +run ["zypper", "install", "http"] +healthcheck CMD curl --fail http://localhost:3000 || exit 1 diff --git a/assets/queries/dockerfile/zypper_install_without_version/test/positive_expected_result.json b/assets/queries/dockerfile/zypper_install_without_version/test/positive_expected_result.json index 7d64d6a1109..5ffc570d5da 100644 --- a/assets/queries/dockerfile/zypper_install_without_version/test/positive_expected_result.json +++ b/assets/queries/dockerfile/zypper_install_without_version/test/positive_expected_result.json @@ -1,12 +1,26 @@ [ - { - "queryName": "Zypper Install Without Version", - "severity": "LOW", - "line": 2 - }, - { - "queryName": "Zypper Install Without Version", - "severity": "LOW", - "line": 3 - } + { + "queryName": "Zypper Install Without Version", + "severity": "LOW", + "line": 2, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Zypper Install Without Version", + "severity": "LOW", + "line": 3, + "fileName": "positive.dockerfile" + }, + { + "queryName": "Zypper Install Without Version", + "severity": "LOW", + "line": 2, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Zypper Install Without Version", + "severity": "LOW", + "line": 3, + "fileName": "positive2.dockerfile" + } ] \ No newline at end of file From c356b4d4e133884b9d15584074a8d58f490ac8a7 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Tue, 24 Mar 2026 11:34:27 +0000 Subject: [PATCH 3/4] Fixes for queries that require extra commands and some expected results fixed --- assets/libraries/dockerfile.rego | 1 + .../query.rego | 3 ++- .../test/positive_expected_result.json | 14 +++++------ .../query.rego | 3 ++- .../query.rego | 4 +++- .../query.rego | 3 ++- .../query.rego | 3 ++- .../missing_dnf_clean_all/query.rego | 3 ++- .../missing_flag_from_dnf_install/query.rego | 9 +++---- .../missing_user_instruction/query.rego | 1 + .../test/positive_expected_result.json | 2 +- .../test/positive_expected_result.json | 6 +++++ .../test/positive_expected_result.json | 2 +- .../test/positive_expected_result.json | 24 +++++++++++++++++++ .../query.rego | 7 +++--- .../test/positive_expected_result.json | 5 ---- .../dockerfile/run_using_sudo/query.rego | 6 +++-- .../test/positive_expected_result.json | 3 ++- .../test/positive_expected_result.json | 2 +- .../update_instruction_alone/query.rego | 10 +++++--- .../workdir_path_not_absolute/query.rego | 3 ++- 21 files changed, 79 insertions(+), 35 deletions(-) diff --git a/assets/libraries/dockerfile.rego b/assets/libraries/dockerfile.rego index 98990ee5a6e..4cdb0068c6e 100644 --- a/assets/libraries/dockerfile.rego +++ b/assets/libraries/dockerfile.rego @@ -75,3 +75,4 @@ get_original_from_command(commands) = from_command { commands[i].Cmd == "from" from_command := substring(commands[i].Original, 0, 4) } + diff --git a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/query.rego b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/query.rego index 428a344be3f..33b5dcc9797 100644 --- a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/query.rego +++ b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/query.rego @@ -14,9 +14,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, commands]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, commands]), "issueType": "IncorrectValue", #"MissingAttribute" / "RedundantAttribute" "keyExpectedValue": "After using apt-get install, the apt-get lists should be deleted", "keyActualValue": "After using apt-get install, the apt-get lists were not deleted", diff --git a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive_expected_result.json b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive_expected_result.json index 2428b814a66..4c73167b481 100644 --- a/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive_expected_result.json +++ b/assets/queries/dockerfile/apt_get_install_lists_were_not_deleted/test/positive_expected_result.json @@ -32,25 +32,25 @@ { "queryName": "Apt Get Install Lists Were Not Deleted", "severity": "INFO", - "line": 5, - "fileName": "positive2.dockerfile" + "line": 2, + "fileName": "positive3.dockerfile" }, { "queryName": "Apt Get Install Lists Were Not Deleted", "severity": "INFO", - "line": 8, - "fileName": "positive2.dockerfile" + "line": 5, + "fileName": "positive3.dockerfile" }, { "queryName": "Apt Get Install Lists Were Not Deleted", "severity": "INFO", - "line": 12, - "fileName": "positive2.dockerfile" + "line": 8, + "fileName": "positive3.dockerfile" }, { "queryName": "Apt Get Install Lists Were Not Deleted", "severity": "INFO", - "line": 2, + "line": 12, "fileName": "positive3.dockerfile" } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/query.rego b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/query.rego index 9c8d8e73543..df82349be49 100644 --- a/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/query.rego +++ b/assets/queries/dockerfile/apt_get_install_pin_version_not_defined/query.rego @@ -20,9 +20,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, commands]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, commands]), "searchValue": packageName, "issueType": "MissingAttribute", "keyExpectedValue": sprintf("Package '%s' has version defined", [packageName]), diff --git a/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/query.rego b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/query.rego index e7755c63964..17d31483c19 100644 --- a/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/query.rego +++ b/assets/queries/dockerfile/apt_get_missing_flags_to_avoid_manual_input/query.rego @@ -35,7 +35,9 @@ CxPolicy[result] { dockerLib.arrayContains(resource.Value, {"apt-get", "install"}) not avoidManualInputInList(resource.Value) - + + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) result := { "documentId": input.document[i].id, "searchKey": sprintf("%s={{%s}}.{{%s}}", [from_command, name, resource.Original]), diff --git a/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/query.rego b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/query.rego index 1f8ea2c0157..f10c9603314 100644 --- a/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/query.rego +++ b/assets/queries/dockerfile/copy_with_more_than_two_arguments_not_ending_with_slash/query.rego @@ -16,9 +16,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + copy_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.COPY={{%s}}", [from_command, name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, copy_command, resource.Value[0]]), "issueType": "IncorrectValue", #"MissingAttribute" / "RedundantAttribute" "keyExpectedValue": "When COPY command has more than two arguments, the last one should end with a slash", "keyActualValue": "COPY command has more than two arguments and the last one does not end with a slash", diff --git a/assets/queries/dockerfile/maintainer_instruction_being_used/query.rego b/assets/queries/dockerfile/maintainer_instruction_being_used/query.rego index 264d322f913..51b7a11bb7d 100644 --- a/assets/queries/dockerfile/maintainer_instruction_being_used/query.rego +++ b/assets/queries/dockerfile/maintainer_instruction_being_used/query.rego @@ -8,9 +8,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + maintainer_command := substring(resource.Original, 0, 10) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.MAINTAINER={{%s}}", [from_command, name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, maintainer_command, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Maintainer instruction being used in Label 'LABEL maintainer=%s'", [resource.Value[0]]), "keyActualValue": sprintf("Maintainer instruction not being used in Label 'MAINTAINER %s'", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/missing_dnf_clean_all/query.rego b/assets/queries/dockerfile/missing_dnf_clean_all/query.rego index 3f75383088f..dc8a5e0f820 100644 --- a/assets/queries/dockerfile/missing_dnf_clean_all/query.rego +++ b/assets/queries/dockerfile/missing_dnf_clean_all/query.rego @@ -15,9 +15,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": "After installing a package with dnf, command 'dnf clean all' should run.", "keyActualValue": "Command `dnf clean all` is not being run after installing packages.", diff --git a/assets/queries/dockerfile/missing_flag_from_dnf_install/query.rego b/assets/queries/dockerfile/missing_flag_from_dnf_install/query.rego index ea3dc692ea0..22b14366e5f 100644 --- a/assets/queries/dockerfile/missing_flag_from_dnf_install/query.rego +++ b/assets/queries/dockerfile/missing_flag_from_dnf_install/query.rego @@ -1,13 +1,13 @@ package Cx import data.generic.common as common_lib -import data.generic.dockerfile as docker_lib +import data.generic.dockerfile as dockerLib CxPolicy[result] { resource := input.document[i].command[name][cmd] resource.Cmd == "run" values := resource.Value[0] - commands = docker_lib.getCommands(values) + commands = dockerLib.getCommands(values) some k c := hasInstallCommandWithoutFlag(commands[k]) @@ -15,10 +15,11 @@ CxPolicy[result] { not hasYesFlag(c) stage := input.document[i].command[name] - from_command := docker_lib.get_original_from_command(stage) + from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, resource.Value[0]]), "searchValue": trim_space(c), "issueType": "IncorrectValue", "keyExpectedValue": "When running `dnf install`, `-y` or `--assumeyes` switch should be set to avoid build failure ", diff --git a/assets/queries/dockerfile/missing_user_instruction/query.rego b/assets/queries/dockerfile/missing_user_instruction/query.rego index 19c41a7312d..87e69b12978 100644 --- a/assets/queries/dockerfile/missing_user_instruction/query.rego +++ b/assets/queries/dockerfile/missing_user_instruction/query.rego @@ -21,5 +21,6 @@ CxPolicy[result] { } has_user_instruction(resource) { + resource[_].Cmd == "user" } diff --git a/assets/queries/dockerfile/missing_user_instruction/test/positive_expected_result.json b/assets/queries/dockerfile/missing_user_instruction/test/positive_expected_result.json index 70ddd881925..c6f89f7b14f 100644 --- a/assets/queries/dockerfile/missing_user_instruction/test/positive_expected_result.json +++ b/assets/queries/dockerfile/missing_user_instruction/test/positive_expected_result.json @@ -16,5 +16,5 @@ "severity": "HIGH", "line": 1, "fileName": "positive3.dockerfile" - }, + } ] diff --git a/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive_expected_result.json b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive_expected_result.json index a7f35bc112b..5e939155d07 100644 --- a/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive_expected_result.json +++ b/assets/queries/dockerfile/missing_version_specification_in_dnf_install/test/positive_expected_result.json @@ -16,5 +16,11 @@ "severity": "MEDIUM", "line": 2, "fileName": "positive2.dockerfile" + }, + { + "queryName": "Missing Version Specification In dnf install", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive2.dockerfile" } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive_expected_result.json b/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive_expected_result.json index 563d30702a0..b65937068ba 100644 --- a/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive_expected_result.json +++ b/assets/queries/dockerfile/npm_install_without_pinned_version/test/positive_expected_result.json @@ -82,5 +82,5 @@ "severity": "MEDIUM", "line": 8, "filename": "positive2.dockerfile" - }, + } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive_expected_result.json b/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive_expected_result.json index ba31acf207f..01668bfd73b 100644 --- a/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive_expected_result.json +++ b/assets/queries/dockerfile/pip_install_keeping_cached_packages/test/positive_expected_result.json @@ -34,5 +34,29 @@ "severity": "LOW", "line": 2, "fileName": "positive2.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 8, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 9, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 10, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Pip install Keeping Cached Packages", + "severity": "LOW", + "line": 11, + "fileName": "positive2.dockerfile" } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/query.rego b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/query.rego index a1d5aa2fce9..da557956b2d 100644 --- a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/query.rego +++ b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/query.rego @@ -5,8 +5,8 @@ import data.generic.dockerfile as dockerLib CxPolicy[result] { resource := input.document[i].command[name][_] resource.Cmd == "run" - run_command := resource.Value[_] - values := split(run_command, " ") + run_command_value := resource.Value[_] + values := split(run_command_value, " ") trim_space(values[index]) == "cd" path := trim_space(values[index+1]) not is_full_path(path) @@ -14,9 +14,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": "Using WORKDIR to change directory", "keyActualValue": sprintf("RUN %s'", [resource.Value[0]]), diff --git a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive_expected_result.json b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive_expected_result.json index 6b424f1b2a4..6c533054a7f 100644 --- a/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive_expected_result.json +++ b/assets/queries/dockerfile/run_command_cd_instead_of_workdir/test/positive_expected_result.json @@ -34,10 +34,5 @@ "severity": "LOW", "line": 15, "fileName": "positive2.dockerfile" - },{ - "queryName": "RUN Instruction Using 'cd' Instead of WORKDIR", - "severity": "LOW", - "line": 3, - "fileName": "positive2.dockerfile" } ] \ No newline at end of file diff --git a/assets/queries/dockerfile/run_using_sudo/query.rego b/assets/queries/dockerfile/run_using_sudo/query.rego index a258365d826..94d474711b7 100644 --- a/assets/queries/dockerfile/run_using_sudo/query.rego +++ b/assets/queries/dockerfile/run_using_sudo/query.rego @@ -11,9 +11,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction shouldn't contain sudo", "keyActualValue": "RUN instruction contains sudo", @@ -29,9 +30,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Original]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": "RUN instruction shouldn't contain sudo", "keyActualValue": "RUN instruction contains sudo", diff --git a/assets/queries/dockerfile/same_alias_in_different_froms/test/positive_expected_result.json b/assets/queries/dockerfile/same_alias_in_different_froms/test/positive_expected_result.json index 4f0c09802ac..515f03d0102 100644 --- a/assets/queries/dockerfile/same_alias_in_different_froms/test/positive_expected_result.json +++ b/assets/queries/dockerfile/same_alias_in_different_froms/test/positive_expected_result.json @@ -2,7 +2,8 @@ { "queryName": "Same Alias In Different Froms", "severity": "LOW", - "line": 4 + "line": 4, + "fileName": "positive.dockerfile" }, { "queryName": "Same Alias In Different Froms", diff --git a/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive_expected_result.json b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive_expected_result.json index 12d14d397df..c1e87f5d252 100644 --- a/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive_expected_result.json +++ b/assets/queries/dockerfile/unpinned_package_version_in_apk_add/test/positive_expected_result.json @@ -33,7 +33,7 @@ "queryName": "Unpinned Package Version in Apk Add", "severity": "MEDIUM", "line": 2, - "fileName": "positive.dockerfile" + "fileName": "positive2.dockerfile" }, { "queryName": "Unpinned Package Version in Apk Add", diff --git a/assets/queries/dockerfile/update_instruction_alone/query.rego b/assets/queries/dockerfile/update_instruction_alone/query.rego index 391e7a712db..52f77a0d09b 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -24,9 +24,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be followed by 'RUN %s %s' in the same 'RUN' statement", [packageManager, pkg_installer[packageManager], packageManager, pkg_updater[packageManager]]), "keyActualValue": sprintf("Instruction 'RUN %s %s' isn't followed by 'RUN %s %s in the same 'RUN' statement", [packageManager, pkg_installer[packageManager], packageManager, pkg_updater[packageManager]]), @@ -62,9 +63,12 @@ CxPolicy[result] { nextUpdate := [x | x := getDetail(nextCommandRefactor, pkg_updater[nextPackageManager][_]); count(x) > 0] count(nextUpdate) == 0 - result := { + stage := input.document[i].command[name] + from_command := dockerLib.get_original_from_command(stage) + run_command := substring(resource.Original, 0, 3) + result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.RUN={{%s}}", [from_command, name, nextResource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, resource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be combined with 'RUN %s %s' in the same 'RUN' statement", [nextPackageManager, pkg_installer[nextPackageManager], nextPackageManager, pkg_updater[nextPackageManager]]), "keyActualValue": sprintf("Instruction 'RUN %s %s' isn't combined with 'RUN %s %s in the same 'RUN' statement", [nextPackageManager, pkg_installer[nextPackageManager], nextPackageManager, pkg_updater[nextPackageManager]]), diff --git a/assets/queries/dockerfile/workdir_path_not_absolute/query.rego b/assets/queries/dockerfile/workdir_path_not_absolute/query.rego index f6505433c57..d7d00a8de1d 100644 --- a/assets/queries/dockerfile/workdir_path_not_absolute/query.rego +++ b/assets/queries/dockerfile/workdir_path_not_absolute/query.rego @@ -9,9 +9,10 @@ CxPolicy[result] { stage := input.document[i].command[name] from_command := dockerLib.get_original_from_command(stage) + workdir_command := substring(resource.Original, 0, 7) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.WORKDIR={{%s}}", [from_command, name, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, workdir_command, resource.Value[0]]), "issueType": "IncorrectValue", #"MissingAttribute" / "RedundantAttribute" "keyExpectedValue": "'WORKDIR' Command has absolute path", "keyActualValue": "'WORKDIR' Command doesn't have absolute path", From 1eb54999f83b7574c61257b86834a9dcdc0ef89a Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Tue, 24 Mar 2026 11:56:14 +0000 Subject: [PATCH 4/4] Small fix to update instruction alone query --- assets/queries/dockerfile/update_instruction_alone/query.rego | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/queries/dockerfile/update_instruction_alone/query.rego b/assets/queries/dockerfile/update_instruction_alone/query.rego index 52f77a0d09b..8fc0fd03c64 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -68,7 +68,7 @@ CxPolicy[result] { run_command := substring(resource.Original, 0, 3) result := { "documentId": input.document[i].id, - "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, resource.Value[0]]), + "searchKey": sprintf("%s={{%s}}.%s={{%s}}", [from_command, name, run_command, nextResource.Value[0]]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be combined with 'RUN %s %s' in the same 'RUN' statement", [nextPackageManager, pkg_installer[nextPackageManager], nextPackageManager, pkg_updater[nextPackageManager]]), "keyActualValue": sprintf("Instruction 'RUN %s %s' isn't combined with 'RUN %s %s in the same 'RUN' statement", [nextPackageManager, pkg_installer[nextPackageManager], nextPackageManager, pkg_updater[nextPackageManager]]),