From 2e9d56e85228bcab4fb86436fe664b4cccb3dd3c Mon Sep 17 00:00:00 2001 From: cx-henriqueAlvelos Date: Tue, 25 Jul 2023 11:39:19 +0100 Subject: [PATCH 1/7] fix(query): checkFollowedBy comparision change --- 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 a342b52f1c9..d59cb89bb4f 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -66,5 +66,5 @@ updateFollowedByInstall(command) { } checkFollowedBy(first, after) { - first[_] < after[_][_] + first[_] >= after[_][_] } From a8a8937adedfa519f2b0875e717e954a04fa4351 Mon Sep 17 00:00:00 2001 From: cx-henriqueAlvelos Date: Tue, 25 Jul 2023 19:15:25 +0100 Subject: [PATCH 2/7] Query changed + tests --- .../update_instruction_alone/query.rego | 167 +++++++++++++----- ...gative.dockerfile => negative1.dockerfile} | 0 .../test/negative10.dockerfile | 4 + .../test/negative11.dockerfile | 5 + .../test/negative4.dockerfile | 4 + .../test/negative5.dockerfile | 5 + .../test/negative6.dockerfile | 4 + .../test/negative7.dockerfile | 4 + .../test/negative8.dockerfile | 4 + .../test/negative9.dockerfile | 4 + ...sitive.dockerfile => positive1.dockerfile} | 0 .../test/positive2.dockerfile | 5 + .../test/positive3.dockerfile | 5 + .../test/positive4.dockerfile | 5 + .../test/positive5.dockerfile | 5 + .../test/positive6.dockerfile | 5 + .../test/positive7.dockerfile | 5 + .../test/positive_expected_result.json | 36 +++- 18 files changed, 225 insertions(+), 42 deletions(-) rename assets/queries/dockerfile/update_instruction_alone/test/{negative.dockerfile => negative1.dockerfile} (100%) create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative10.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative11.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative4.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative5.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative6.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative7.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative8.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/negative9.dockerfile rename assets/queries/dockerfile/update_instruction_alone/test/{positive.dockerfile => positive1.dockerfile} (100%) create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive2.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive3.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive4.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive5.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive6.dockerfile create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile diff --git a/assets/queries/dockerfile/update_instruction_alone/query.rego b/assets/queries/dockerfile/update_instruction_alone/query.rego index d59cb89bb4f..f12fc8f8742 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -1,70 +1,157 @@ package Cx CxPolicy[result] { + # Check if there is a command that runs install before update resource := input.document[i].command[name][_] resource.Cmd == "run" count(resource.Value) == 1 command := resource.Value[0] - - isValidUpdate(command) - not phpComposerPhar(command) - not updateFollowedByInstall(command) - + commandList := split(command, " ") + commandRefactor := [x | x := commandList[_]; x != ""] + packages := [l | commandRefactor[0] == pkg[l]] + count(packages) > 0 + packageManager := pkg[packages[0]] + + update := getDetail(commandRefactor, pkg_updater[packageManager]) + count(update) > 0 + install := getDetail(commandRefactor, pkg_installer[packageManager]) + count(install) > 0 + not checkFollowedBy(update, install) + result := { "documentId": input.document[i].id, "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, resource.Value[0]]), "issueType": "IncorrectValue", - "keyExpectedValue": "Instruction 'RUN update' should be followed by 'RUN install' ", - "keyActualValue": "Instruction 'RUN update' isn't followed by 'RUN install in the same 'RUN' statement", + "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be followed by 'RUN %s %s' ", [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]]), } } -isValidUpdate(command) { - contains(command, " update ") +CxPolicy[result] { + #Check if there is Update Command without Install Command + resource := input.document[i].command[name][n] + commandRefactor := getRunCommand(resource) + packages := [l | commandRefactor[0] == pkg[l]] + count(packages) > 0 + packageManager := pkg[packages[0]] + + update := getDetail(commandRefactor, pkg_updater[packageManager]) + count(update) > 0 + install := getDetail(commandRefactor, pkg_installer[packageManager]) + count(install) == 0 + + #Check if any of the next commands is RUN install Command and there is not Update Command + nextResources := array.slice(input.document[i].command[name], n+1, count(input.document[i].command[name])) + nextResource := nextResources[_] + nextCommandRefactor := getRunCommand(nextResource) + nextPackages := [l | nextCommandRefactor[0] == pkg[l]] + count(nextPackages) > 0 + nextPackageManager := pkg[nextPackages[0]] + nextPackageManager == packageManager + + nextInstall = [u | nextCommandRefactor[u] == pkg_installer[nextPackageManager]] + count(nextInstall) > 0 + nextUpdate = getDetail(nextCommandRefactor, pkg_updater[nextPackageManager]) + count(nextUpdate) == 0 + + result := { + "documentId": input.document[i].id, + "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, nextResource.Value[0]]), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be combined with 'RUN %s %s' ", [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]]), + } +} + +CxPolicy[result] { + #Check if there is not any update command and there is some install command + not UpdateCommand(input.document[i].command[name]) + + nextResource := input.document[i].command[name][_] + nextCommandRefactor := getRunCommand(nextResource) + nextPackages := [l | nextCommandRefactor[0] == pkg[l]] + count(nextPackages) > 0 + nextPackageManager := pkg[nextPackages[0]] + + install := getDetail(nextCommandRefactor, pkg_installer[nextPackageManager]) + count(install) > 0 + + not checkException(nextPackageManager, nextCommandRefactor) + + result := { + "documentId": input.document[i].id, + "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, nextResource.Value[0]]), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be combined with 'RUN %s %s' ", [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]]), + } } -isValidUpdate(command) { - contains(command, " --update ") +UpdateCommand(resources) { + resource := resources[_] + commandRefactor := getRunCommand(resource) + packages := [l | commandRefactor[0] == pkg[l]] + count(packages) > 0 + packageManager := pkg[packages[0]] + update := getDetail(commandRefactor, pkg_updater[packageManager]) + count(update) > 0 } -isValidUpdate(command) { - array_split := split(command, " ") +pkg := [ + "apt-get", + "apk", + "yum", + "dnf", + "zypper", + "pacman", + "apt", + "pkg_add" +] - len = count(array_split) +pkg_updater := { + "apt-get": "update", + "apk": "update", + "yum": "update", + "dnf": "update", + "zypper": "refresh", + "pacman": "-Syu", + "apt": "update", +} - update := {"update", "--update"} +pkg_installer := { + "apt-get": "install", + "apk": "add", + "yum": "install", + "dnf": "install", + "zypper": "install", + "pacman": "-S", + "apt": "install", +} - array_split[len - 1] == update[j] +exceptions := { + "apk": "--update" } -phpComposerPhar(command) { - php := {x | x := indexof_n(command, "php"); count(x) != 0} - count(php) > 0 - composer := {x | x := indexof_n(command, "composer"); count(x) != 0} - count(composer) > 0 - checkFollowedBy(php[_],composer) - update := {x | x := indexof_n(command, "update"); count(x) != 0} - count(update) > 0 - checkFollowedBy(composer[_],update) + +getRunCommand(resource) = commandRefactor { + resource.Cmd == "run" + count(resource.Value) == 1 + command := resource.Value[0] + commandList := split(command, " ") + commandRefactor := [x | x := commandList[_]; x != ""] } -commandList := [ - "install", - "source-install", - "reinstall", - "groupinstall", - "localinstall", - "add", -] -updateFollowedByInstall(command) { - update := {x | x := indexof_n(command, "update"); count(x) != 0} - count(update) > 0 - install := {x | x := indexof_n(command, commandList[_]); count(x) != 0} - count(install) > 0 - checkFollowedBy(update[_], install) +getDetail(commandRefactor, value) = list{ + list := [u | commandRefactor[u] == value] } checkFollowedBy(first, after) { - first[_] >= after[_][_] + first[_] < after[_] } + +checkException(nextPackageManager, nextCommandRefactor){ + exp := exceptions[nextPackageManager] + l := getDetail(nextCommandRefactor, exp) + count(l) > 0 +} \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative1.dockerfile similarity index 100% rename from assets/queries/dockerfile/update_instruction_alone/test/negative.dockerfile rename to assets/queries/dockerfile/update_instruction_alone/test/negative1.dockerfile diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative10.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative10.dockerfile new file mode 100644 index 00000000000..2440cdc9f3b --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative10.dockerfile @@ -0,0 +1,4 @@ +FROM alpine:latest +RUN apk update && apk add nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative11.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative11.dockerfile new file mode 100644 index 00000000000..9c05aa3a011 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative11.dockerfile @@ -0,0 +1,5 @@ +FROM alpine:latest +RUN apk --update add nginx +RUN apk add --update nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative4.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative4.dockerfile new file mode 100644 index 00000000000..b01884b80b7 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative4.dockerfile @@ -0,0 +1,4 @@ +FROM archlinux:latest +RUN pacman -Syu && pacman -S nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative5.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative5.dockerfile new file mode 100644 index 00000000000..968d8f12e11 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative5.dockerfile @@ -0,0 +1,5 @@ +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 +ENTRYPOINT ["mysql"] diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative6.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative6.dockerfile new file mode 100644 index 00000000000..a7876ef3345 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative6.dockerfile @@ -0,0 +1,4 @@ +FROM opensuse:latest +RUN zypper refresh && zypper install nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative7.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative7.dockerfile new file mode 100644 index 00000000000..fb56c5d2ee0 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative7.dockerfile @@ -0,0 +1,4 @@ +FROM debian:latest +RUN apt update && install nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative8.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative8.dockerfile new file mode 100644 index 00000000000..35f686265ac --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative8.dockerfile @@ -0,0 +1,4 @@ +FROM centos:latest +RUN yum update && yum install nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative9.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative9.dockerfile new file mode 100644 index 00000000000..b50ebc9498a --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative9.dockerfile @@ -0,0 +1,4 @@ +FROM fedora:latest +RUN dnf update && dnf install nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive1.dockerfile similarity index 100% rename from assets/queries/dockerfile/update_instruction_alone/test/positive.dockerfile rename to assets/queries/dockerfile/update_instruction_alone/test/positive1.dockerfile diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive2.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive2.dockerfile new file mode 100644 index 00000000000..f5894330b8d --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive2.dockerfile @@ -0,0 +1,5 @@ +FROM opensuse:latest +RUN zypper refresh +RUN zypper install nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive3.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive3.dockerfile new file mode 100644 index 00000000000..e15e652ff0c --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive3.dockerfile @@ -0,0 +1,5 @@ +FROM debian:latest +RUN apt update +RUN apt install nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive4.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive4.dockerfile new file mode 100644 index 00000000000..7dfe01f99ed --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive4.dockerfile @@ -0,0 +1,5 @@ +FROM centos:latest +RUN yum update +RUN yum install nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive5.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive5.dockerfile new file mode 100644 index 00000000000..799b69db2a9 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive5.dockerfile @@ -0,0 +1,5 @@ +FROM fedora:latest +RUN dnf update +RUN dnf install nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive6.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive6.dockerfile new file mode 100644 index 00000000000..97a72651cc9 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive6.dockerfile @@ -0,0 +1,5 @@ +FROM archlinux:latest +RUN pacman -Syu +RUN pacman -S nginx + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile new file mode 100644 index 00000000000..df232ec37d9 --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive7.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 f06c9035bfe..0b6c8f27df4 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 @@ -2,11 +2,43 @@ { "queryName": "Update Instruction Alone", "severity": "MEDIUM", - "line": 2 + "line": 3, + "fileName": "positive1.dockerfile" }, { "queryName": "Update Instruction Alone", "severity": "MEDIUM", - "line": 5 + "line": 3, + "fileName": "positive2.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive3.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive4.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive5.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive6.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive7.dockerfile" } ] From 71b0a52af96dfccb010aad17579858a8d4305032 Mon Sep 17 00:00:00 2001 From: cx-henriqueAlvelos Date: Tue, 25 Jul 2023 19:16:54 +0100 Subject: [PATCH 3/7] fix --- 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 f12fc8f8742..43914e02d59 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -49,7 +49,7 @@ CxPolicy[result] { nextPackageManager := pkg[nextPackages[0]] nextPackageManager == packageManager - nextInstall = [u | nextCommandRefactor[u] == pkg_installer[nextPackageManager]] + nextInstall = getDetail(nextCommandRefactor, pkg_installer[nextPackageManager]) count(nextInstall) > 0 nextUpdate = getDetail(nextCommandRefactor, pkg_updater[nextPackageManager]) count(nextUpdate) == 0 From ddc4a14c5ca64d8d3742a05877fe6c75ee8e332a Mon Sep 17 00:00:00 2001 From: cx-henriqueAlvelos Date: Wed, 26 Jul 2023 09:36:00 +0100 Subject: [PATCH 4/7] Updated exceptions and negative test --- assets/queries/dockerfile/update_instruction_alone/query.rego | 4 ++-- .../update_instruction_alone/test/negative10.dockerfile | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/assets/queries/dockerfile/update_instruction_alone/query.rego b/assets/queries/dockerfile/update_instruction_alone/query.rego index 43914e02d59..7821a76a7a5 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -129,7 +129,7 @@ pkg_installer := { } exceptions := { - "apk": "--update" + "apk": ["--update", "--update-cache", "-U"] } @@ -152,6 +152,6 @@ checkFollowedBy(first, after) { checkException(nextPackageManager, nextCommandRefactor){ exp := exceptions[nextPackageManager] - l := getDetail(nextCommandRefactor, exp) + l := [x | x := getDetail(nextCommandRefactor, exp[_]); count(x) > 0] count(l) > 0 } \ No newline at end of file diff --git a/assets/queries/dockerfile/update_instruction_alone/test/negative10.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/negative10.dockerfile index 2440cdc9f3b..c9ae3680374 100644 --- a/assets/queries/dockerfile/update_instruction_alone/test/negative10.dockerfile +++ b/assets/queries/dockerfile/update_instruction_alone/test/negative10.dockerfile @@ -1,4 +1,6 @@ FROM alpine:latest RUN apk update && apk add nginx +RUN apk --update-cache add vim +RUN apk -U add nano CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file From 4b4a14c06c1a7fcb3efc99dceee4bccb86a7a5ef Mon Sep 17 00:00:00 2001 From: cx-henriqueAlvelos Date: Tue, 29 Aug 2023 17:39:40 +0100 Subject: [PATCH 5/7] query splitted --- .../update_instruction_alone/query.rego | 84 ++++++------------- .../test/positive1.dockerfile | 9 +- .../test/positive7.dockerfile | 5 -- .../test/positive_expected_result.json | 6 -- 4 files changed, 31 insertions(+), 73 deletions(-) delete mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile diff --git a/assets/queries/dockerfile/update_instruction_alone/query.rego b/assets/queries/dockerfile/update_instruction_alone/query.rego index 7821a76a7a5..3a10a789729 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -11,18 +11,20 @@ CxPolicy[result] { packages := [l | commandRefactor[0] == pkg[l]] count(packages) > 0 packageManager := pkg[packages[0]] - - update := getDetail(commandRefactor, pkg_updater[packageManager]) + + update := [x | x := getDetail(commandRefactor, pkg_updater[packageManager][_]); count(x) > 0] count(update) > 0 - install := getDetail(commandRefactor, pkg_installer[packageManager]) + + install := [x | x := getDetail(commandRefactor, pkg_installer[packageManager][_]); count(x) > 0] count(install) > 0 + not checkFollowedBy(update, install) result := { "documentId": input.document[i].id, "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, resource.Value[0]]), "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be followed by 'RUN %s %s' ", [packageManager, pkg_installer[packageManager], packageManager, pkg_updater[packageManager]]), + "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]]), } } @@ -35,9 +37,10 @@ CxPolicy[result] { count(packages) > 0 packageManager := pkg[packages[0]] - update := getDetail(commandRefactor, pkg_updater[packageManager]) + update := [x | x := getDetail(commandRefactor, pkg_updater[packageManager][_]); count(x) > 0] count(update) > 0 - install := getDetail(commandRefactor, pkg_installer[packageManager]) + + install := [x | x := getDetail(commandRefactor, pkg_installer[packageManager][_]); count(x) > 0] count(install) == 0 #Check if any of the next commands is RUN install Command and there is not Update Command @@ -49,54 +52,21 @@ CxPolicy[result] { nextPackageManager := pkg[nextPackages[0]] nextPackageManager == packageManager - nextInstall = getDetail(nextCommandRefactor, pkg_installer[nextPackageManager]) + nextInstall := [x | x := getDetail(nextCommandRefactor, pkg_installer[nextPackageManager][_]); count(x) > 0] count(nextInstall) > 0 - nextUpdate = getDetail(nextCommandRefactor, pkg_updater[nextPackageManager]) + + nextUpdate := [x | x := getDetail(nextCommandRefactor, pkg_updater[nextPackageManager][_]); count(x) > 0] count(nextUpdate) == 0 result := { "documentId": input.document[i].id, "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, nextResource.Value[0]]), "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be combined with 'RUN %s %s' ", [nextPackageManager, pkg_installer[nextPackageManager], nextPackageManager, pkg_updater[nextPackageManager]]), + "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]]), } } -CxPolicy[result] { - #Check if there is not any update command and there is some install command - not UpdateCommand(input.document[i].command[name]) - - nextResource := input.document[i].command[name][_] - nextCommandRefactor := getRunCommand(nextResource) - nextPackages := [l | nextCommandRefactor[0] == pkg[l]] - count(nextPackages) > 0 - nextPackageManager := pkg[nextPackages[0]] - - install := getDetail(nextCommandRefactor, pkg_installer[nextPackageManager]) - count(install) > 0 - - not checkException(nextPackageManager, nextCommandRefactor) - - result := { - "documentId": input.document[i].id, - "searchKey": sprintf("FROM={{%s}}.RUN={{%s}}", [name, nextResource.Value[0]]), - "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Instruction 'RUN %s %s' should be combined with 'RUN %s %s' ", [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]]), - } -} - -UpdateCommand(resources) { - resource := resources[_] - commandRefactor := getRunCommand(resource) - packages := [l | commandRefactor[0] == pkg[l]] - count(packages) > 0 - packageManager := pkg[packages[0]] - update := getDetail(commandRefactor, pkg_updater[packageManager]) - count(update) > 0 -} - pkg := [ "apt-get", "apk", @@ -109,23 +79,23 @@ pkg := [ ] pkg_updater := { - "apt-get": "update", - "apk": "update", - "yum": "update", - "dnf": "update", - "zypper": "refresh", - "pacman": "-Syu", - "apt": "update", + "apt-get": ["update"], + "apk": ["update"], + "yum": ["update"], + "dnf": ["update"], + "zypper": ["refresh"], + "pacman": ["-Syu"], + "apt": ["update"], } pkg_installer := { - "apt-get": "install", - "apk": "add", - "yum": "install", - "dnf": "install", - "zypper": "install", - "pacman": "-S", - "apt": "install", + "apt-get": ["install", "source-install", "reinstall"], + "apk": ["add"], + "yum": ["install"], + "dnf": ["install"], + "zypper": ["install"], + "pacman": ["-S"], + "apt": ["install"], } exceptions := { diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive1.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive1.dockerfile index 915a6c1d1cb..df232ec37d9 100644 --- a/assets/queries/dockerfile/update_instruction_alone/test/positive1.dockerfile +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive1.dockerfile @@ -1,6 +1,5 @@ -FROM ubuntu:18.04 -RUN apt-get update -RUN apt-get install -y --no-install-recommends mysql-client \ - && rm -rf /var/lib/apt/lists/* +FROM alpine:latest RUN apk update -ENTRYPOINT ["mysql"] +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/positive7.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile deleted file mode 100644 index df232ec37d9..00000000000 --- a/assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -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 0b6c8f27df4..d0850b08949 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 @@ -34,11 +34,5 @@ "severity": "MEDIUM", "line": 3, "fileName": "positive6.dockerfile" - }, - { - "queryName": "Update Instruction Alone", - "severity": "MEDIUM", - "line": 3, - "fileName": "positive7.dockerfile" } ] From 2a981f17db1459ff18d7f953f92c6cee469fa4e6 Mon Sep 17 00:00:00 2001 From: cx-henriqueAlvelos Date: Wed, 30 Aug 2023 08:48:14 +0100 Subject: [PATCH 6/7] added test --- .../update_instruction_alone/test/positive7.dockerfile | 6 ++++++ .../test/positive_expected_result.json | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile diff --git a/assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile b/assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile new file mode 100644 index 00000000000..c588dda10cb --- /dev/null +++ b/assets/queries/dockerfile/update_instruction_alone/test/positive7.dockerfile @@ -0,0 +1,6 @@ +FROM ubuntu:18.04 +RUN apt-get update +RUN apt-get install -y --no-install-recommends mysql-client \ + && rm -rf /var/lib/apt/lists/* +RUN apk update +ENTRYPOINT ["mysql"] \ 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 d0850b08949..0b6c8f27df4 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 @@ -34,5 +34,11 @@ "severity": "MEDIUM", "line": 3, "fileName": "positive6.dockerfile" + }, + { + "queryName": "Update Instruction Alone", + "severity": "MEDIUM", + "line": 3, + "fileName": "positive7.dockerfile" } ] From ee81ed21d573c98df31180df7c02ac159a1744e1 Mon Sep 17 00:00:00 2001 From: cx-henriqueAlvelos Date: Wed, 30 Aug 2023 08:58:56 +0100 Subject: [PATCH 7/7] removed unused methods --- .../dockerfile/update_instruction_alone/query.rego | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/assets/queries/dockerfile/update_instruction_alone/query.rego b/assets/queries/dockerfile/update_instruction_alone/query.rego index 3a10a789729..9bf0c5837c4 100644 --- a/assets/queries/dockerfile/update_instruction_alone/query.rego +++ b/assets/queries/dockerfile/update_instruction_alone/query.rego @@ -98,10 +98,6 @@ pkg_installer := { "apt": ["install"], } -exceptions := { - "apk": ["--update", "--update-cache", "-U"] -} - getRunCommand(resource) = commandRefactor { resource.Cmd == "run" @@ -111,7 +107,6 @@ getRunCommand(resource) = commandRefactor { commandRefactor := [x | x := commandList[_]; x != ""] } - getDetail(commandRefactor, value) = list{ list := [u | commandRefactor[u] == value] } @@ -119,9 +114,3 @@ getDetail(commandRefactor, value) = list{ checkFollowedBy(first, after) { first[_] < after[_] } - -checkException(nextPackageManager, nextCommandRefactor){ - exp := exceptions[nextPackageManager] - l := [x | x := getDetail(nextCommandRefactor, exp[_]); count(x) > 0] - count(l) > 0 -} \ No newline at end of file