diff --git a/generic/container-privileged.sh b/generic/container-privileged.sh new file mode 100644 index 0000000..7dcfb08 --- /dev/null +++ b/generic/container-privileged.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# ruleid: container-privileged +docker run --privileged hello-world + +# ruleid: container-privileged +podman run --privileged hello-world + +# ok: container-privileged +docker run hello-world + +# ok: container-privileged +podman run hello-world diff --git a/generic/container-privileged.yaml b/generic/container-privileged.yaml new file mode 100644 index 0000000..1f7bd42 --- /dev/null +++ b/generic/container-privileged.yaml @@ -0,0 +1,36 @@ +rules: + - id: container-privileged + message: Found container command with extended privileges + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-250: Execution with Unnecessary Privileges" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://docs.docker.com/engine/reference/commandline/run/ + pattern-either: + - pattern: docker ... --privileged + - pattern: docker ... --cap-add=ALL + - pattern: docker ... --cap-add=SYS_ADMIN + - pattern: docker ... --cap-add=SYS_MODULE + - pattern: docker ... --net=host + - pattern: docker ... --userns=host + - pattern: docker ... --pid=host + - pattern: docker ... --ipc=host + - pattern: docker ... --security-opt seccomp=unconfined + - pattern: docker ... --security-opt apparmor=unconfined + - pattern: podman ... --privileged + - pattern: podman ... --cap-add=ALL + - pattern: podman ... --cap-add=SYS_ADMIN + - pattern: podman ... --cap-add=SYS_MODULE + - pattern: podman ... --net=host + - pattern: podman ... --userns=host + - pattern: podman ... --pid=host + - pattern: podman ... --ipc=host + - pattern: podman ... --security-opt seccomp=unconfined + - pattern: podman ... --security-opt apparmor=unconfined diff --git a/generic/container-user-root.sh b/generic/container-user-root.sh new file mode 100644 index 0000000..2924ec9 --- /dev/null +++ b/generic/container-user-root.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# ruleid: container-user-root +docker run -u root hello-world + +# ruleid: container-user-root +podman run --user root hello-world + +# ok: container-user-root +docker run hello-world + +# ok: container-user-root +podman run hello-world diff --git a/generic/container-user-root.yaml b/generic/container-user-root.yaml new file mode 100644 index 0000000..f6d58f6 --- /dev/null +++ b/generic/container-user-root.yaml @@ -0,0 +1,24 @@ +rules: + - id: container-user-root + message: Found container command running as root + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-250: Execution with Unnecessary Privileges" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://docs.docker.com/engine/reference/commandline/run/ + pattern-either: + - pattern: docker ... -u root + - pattern: docker ... -u 0 + - pattern: docker ... --user root + - pattern: docker ... --user 0 + - pattern: podman ... -u root + - pattern: podman ... --u 0 + - pattern: podman ... --user root + - pattern: podman ... --user 0 diff --git a/generic/curl-insecure.sh b/generic/curl-insecure.sh new file mode 100644 index 0000000..e3fbb13 --- /dev/null +++ b/generic/curl-insecure.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# ruleid: curl-insecure +curl -k https://google.com > /dev/null + +# ruleid: curl-insecure +curl --insecure https://google.com > /dev/null + +# ok: curl-insecure +curl --ksomeotherflag https://google.com > /dev/null + +# ok: curl-insecure +curl https://google.com > /dev/null diff --git a/generic/curl-insecure.yaml b/generic/curl-insecure.yaml new file mode 100644 index 0000000..8cbb875 --- /dev/null +++ b/generic/curl-insecure.yaml @@ -0,0 +1,22 @@ +rules: + - id: curl-insecure + message: Found `curl` command disabling SSL verification + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-295: Improper Certificate Validation" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://curl.se/docs/manpage.html + pattern-either: + # A space character was left at the end of some patterns to help ensure + # that the intended flag was used, and minimize the chance that another, + # longer flag that _starts with_ the intended flag results in a false + # positive + - pattern: "curl ... -k " + - pattern: "curl ... --insecure" diff --git a/generic/curl-unencrypted-url.sh b/generic/curl-unencrypted-url.sh new file mode 100644 index 0000000..eedd396 --- /dev/null +++ b/generic/curl-unencrypted-url.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# ruleid: curl-unencrypted-url +curl http://google.com > /dev/null + +# ruleid: curl-unencrypted-url +curl ftp://google.com > /dev/null + +# ok: curl-unencrypted-url +curl https://google.com > /dev/null diff --git a/generic/curl-unencrypted-url.yaml b/generic/curl-unencrypted-url.yaml new file mode 100644 index 0000000..1019cc8 --- /dev/null +++ b/generic/curl-unencrypted-url.yaml @@ -0,0 +1,18 @@ +rules: + - id: curl-unencrypted-url + message: Found `curl` command with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://curl.se/docs/manpage.html + pattern-either: + - pattern: curl ... http:// + - pattern: curl ... ftp:// diff --git a/generic/gpg-insecure-flags.sh b/generic/gpg-insecure-flags.sh new file mode 100644 index 0000000..ed845e4 --- /dev/null +++ b/generic/gpg-insecure-flags.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# ruleid: gpg-insecure-flags +gpg --skip-verify --output doc --decrypt doc.gpg + +# ok: gpg-insecure-flags +gpg --output doc --decrypt doc.gpg diff --git a/generic/gpg-insecure-flags.yaml b/generic/gpg-insecure-flags.yaml new file mode 100644 index 0000000..904b48e --- /dev/null +++ b/generic/gpg-insecure-flags.yaml @@ -0,0 +1,27 @@ +rules: + - id: gpg-insecure-flags + message: Found `gpg` command using insecure flags + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-295: Improper Certificate Validation" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://www.gnupg.org/gph/de/manual/r1023.html + pattern-either: + - pattern: gpg ... --allow-non-selfsigned-uid + - pattern: gpg ... --allow-freeform-uid + - pattern: gpg ... --allow-old-cipher-algos + - pattern: gpg ... --allow-weak-digest-algos + - pattern: gpg ... --allow-weak-key-signatures + - pattern: gpg ... --ignore-time-conflict + - pattern: gpg ... --ignore-valid-from + - pattern: gpg ... --ignore-crc-error + - pattern: gpg ... --ignore-mdc-error + - pattern: gpg ... --skip-verify + - pattern: gpg ... --no-require-cross-certification diff --git a/generic/installer-allow-untrusted.sh b/generic/installer-allow-untrusted.sh new file mode 100644 index 0000000..cbcc398 --- /dev/null +++ b/generic/installer-allow-untrusted.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# ruleid: installer-allow-untrusted +sudo installer -pkg /path/to/package.pkg -target / -allowUntrusted + +# ok: installer-allow-untrusted +sudo installer -pkg /path/to/package.pkg -target / diff --git a/generic/installer-allow-untrusted.yaml b/generic/installer-allow-untrusted.yaml new file mode 100644 index 0000000..e47f73a --- /dev/null +++ b/generic/installer-allow-untrusted.yaml @@ -0,0 +1,16 @@ +rules: + - id: installer-allow-untrusted + message: Found `installer` command allowing untrusted installations + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-494: Download of Code Without Integrity Check" + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://ss64.com/mac/installer.html + pattern: installer ... -allowUntrusted diff --git a/generic/openssl-insecure-flags.sh b/generic/openssl-insecure-flags.sh new file mode 100644 index 0000000..6e156f9 --- /dev/null +++ b/generic/openssl-insecure-flags.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# ruleid: openssl-insecure-flags +openssl genpkey -algorithm RSA -out private_key.pem -aes-256-cbc -pass pass:mysecretpass + +# ok: openssl-insecure-flags +openssl genpkey -algorithm RSA -out private_key.pem --noencsomeotherflag + +# ok: openssl-insecure-flags +openssl genpkey -algorithm RSA -out private_key.pem -aes-256-cbc -pass env:PASSVAR diff --git a/generic/openssl-insecure-flags.yaml b/generic/openssl-insecure-flags.yaml new file mode 100644 index 0000000..3b04e80 --- /dev/null +++ b/generic/openssl-insecure-flags.yaml @@ -0,0 +1,26 @@ +rules: + - id: openssl-insecure-flags + message: Found `openssl` command using insecure flags + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-295: Improper Certificate Validation" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://www.openssl.org/docs/manmaster/man1/ + pattern-either: + # A space character was left at the end of some patterns to help ensure + # that the intended flag was used, and minimize the chance that another, + # longer flag that _starts with_ the intended flag results in a false + # positive + - pattern: "openssl ... -pass pass:" + - pattern: "openssl ... -passin pass:" + - pattern: "openssl ... -passout pass:" + - pattern: "openssl ... -nodes " + - pattern: "openssl ... -noenc " + - pattern: "openssl ... -sha1 " diff --git a/generic/ssh-disable-host-key-checking.sh b/generic/ssh-disable-host-key-checking.sh new file mode 100644 index 0000000..005eadb --- /dev/null +++ b/generic/ssh-disable-host-key-checking.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# ruleid: ssh-disable-host-key-checking +ssh -o StrictHostKeyChecking=no user@hostname + +# ok: ssh-disable-host-key-checking +ssh user@hostname diff --git a/generic/ssh-disable-host-key-checking.yaml b/generic/ssh-disable-host-key-checking.yaml new file mode 100644 index 0000000..2e8785b --- /dev/null +++ b/generic/ssh-disable-host-key-checking.yaml @@ -0,0 +1,16 @@ +rules: + - id: ssh-disable-host-key-checking + message: Found `ssh` command disabling host key checking + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-295: Improper Certificate Validation" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://man7.org/linux/man-pages/man1/ssh.1.html + pattern: ssh ... StrictHostKeyChecking=no diff --git a/generic/tar-insecure-flags.sh b/generic/tar-insecure-flags.sh new file mode 100644 index 0000000..74972fe --- /dev/null +++ b/generic/tar-insecure-flags.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# ruleid: tar-insecure-flags +tar -xvf --absolute-paths archive.tar + +# ruleid: tar-insecure-flags +tar -xvf -P archive.tar + +# ok: tar-insecure-flags +tar -xvf --Psomeotherflag archive.tar + +# ok: tar-insecure-flags +tar -xvf archive.tar diff --git a/generic/tar-insecure-flags.yaml b/generic/tar-insecure-flags.yaml new file mode 100644 index 0000000..03618ce --- /dev/null +++ b/generic/tar-insecure-flags.yaml @@ -0,0 +1,24 @@ +rules: + - id: tar-insecure-flags + message: Found `tar` command using insecure flags + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-73: External Control of File Name or Path" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://man7.org/linux/man-pages/man1/tar.1.html + pattern-either: + # A space character was left at the end of some patterns to help ensure + # that the intended flag was used, and minimize the chance that another, + # longer flag that _starts with_ the intended flag results in a false + # positive + - pattern: "tar ... -P " + - pattern: "tar ... --absolute-paths" + - pattern: "tar ... --absolute-names" + - pattern: "tar ... --passphrase " diff --git a/generic/wget-no-check-certificate.sh b/generic/wget-no-check-certificate.sh new file mode 100644 index 0000000..b1d256d --- /dev/null +++ b/generic/wget-no-check-certificate.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# ruleid: wget-no-check-certificate +wget --no-check-certificate https://google.com + +# ruleid: wget-no-check-certificate +wget --no-hsts https://google.com + +# ok: wget-no-check-certificate +wget https://google.com diff --git a/generic/wget-no-check-certificate.yaml b/generic/wget-no-check-certificate.yaml new file mode 100644 index 0000000..bf11bc5 --- /dev/null +++ b/generic/wget-no-check-certificate.yaml @@ -0,0 +1,18 @@ +rules: + - id: wget-no-check-certificate + message: Found `wget` command disabling SSL verification + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-295: Improper Certificate Validation" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://linux.die.net/man/1/wget + pattern-either: + - pattern: wget ... --no-check-certificate + - pattern: wget ... --no-hsts diff --git a/generic/wget-unencrypted-url.sh b/generic/wget-unencrypted-url.sh new file mode 100644 index 0000000..9fc1f69 --- /dev/null +++ b/generic/wget-unencrypted-url.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# ruleid: wget-unencrypted-url +wget http://google.com + +# ruleid: wget-unencrypted-url +wget ftp://google.com + +# ok: wget-unencrypted-url +wget https://google.com diff --git a/generic/wget-unencrypted-url.yaml b/generic/wget-unencrypted-url.yaml new file mode 100644 index 0000000..361e861 --- /dev/null +++ b/generic/wget-unencrypted-url.yaml @@ -0,0 +1,18 @@ +rules: + - id: wget-unencrypted-url + message: Found `wget` command with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [generic] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [shell] + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + references: + - https://linux.die.net/man/1/wget + pattern-either: + - pattern: wget ... http:// + - pattern: wget ... ftp:// diff --git a/jvm/gc-call.java b/jvm/gc-call.java new file mode 100644 index 0000000..2b38496 --- /dev/null +++ b/jvm/gc-call.java @@ -0,0 +1,6 @@ +class Test { + public static void main(String[] args) { + // ruleid: gc-call + System.gc(); + } +} diff --git a/jvm/gc-call.kt b/jvm/gc-call.kt new file mode 100644 index 0000000..ba5b2d1 --- /dev/null +++ b/jvm/gc-call.kt @@ -0,0 +1,4 @@ +fun main() { + // ruleid: gc-call + System.gc() +} diff --git a/jvm/gc-call.yaml b/jvm/gc-call.yaml new file mode 100644 index 0000000..601f2d3 --- /dev/null +++ b/jvm/gc-call.yaml @@ -0,0 +1,21 @@ +rules: + - id: gc-call + message: | + Calling `gc` suggests to the JVM that the garbage collector should be + run, and memory should be reclaimed. This is only a suggestion, and there + is no guarantee that anything will happen. Relying on this behavior for + correctness or memory management is an anti-pattern. + languages: [java, kotlin] + severity: WARNING + metadata: + category: best-practice + subcategory: [audit] + technology: [java, kotlin] + confidence: HIGH + likelihood: HIGH + impact: LOW + references: + - https://stackoverflow.com/questions/2414105/why-is-it-bad-practice-to-call-system-gc + pattern-either: + - pattern: System.gc() + - pattern: Runtime.getRuntime().gc() diff --git a/jvm/mongo-hostname-verification-disabled.java b/jvm/mongo-hostname-verification-disabled.java new file mode 100644 index 0000000..22df070 --- /dev/null +++ b/jvm/mongo-hostname-verification-disabled.java @@ -0,0 +1,23 @@ +package test + +import com.mongodb.MongoClientSettings +import com.mongodb.MongoClients + +class HelloWorld { + public static void main(String[] args) { + MongoClientSettings settings = MongoClientSettings.builder() + .applyToSslSettings(builder -> { + builder.enabled(true); + // ruleid: mongo-hostname-verification-disabled + builder.invalidHostNameAllowed(true); + }) + .build(); + + MongoClientSettings settings = MongoClientSettings.builder() + .applyToSslSettings(builder -> { + // ok: mongo-hostname-verification-disabled + builder.enabled(true); + }) + .build(); + } +} diff --git a/jvm/mongo-hostname-verification-disabled.kt b/jvm/mongo-hostname-verification-disabled.kt new file mode 100644 index 0000000..d690034 --- /dev/null +++ b/jvm/mongo-hostname-verification-disabled.kt @@ -0,0 +1,27 @@ +package test + +import com.mongodb.MongoClientSettings +import com.mongodb.MongoClients + +fun main() { + val mongoClient = MongoClient.create( + MongoClientSettings.builder() + .applyConnectionString(ConnectionString("")) + .applyToSslSettings{ builder -> + builder.enabled(true) + // ruleid: mongo-hostname-verification-disabled + builder.invalidHostNameAllowed(true); + } + .build() + ) + + val mongoClient = MongoClient.create( + MongoClientSettings.builder() + .applyConnectionString(ConnectionString("")) + .applyToSslSettings{ builder -> + // ok: mongo-hostname-verification-disabled + builder.enabled(true) + } + .build() + ) +} diff --git a/jvm/mongo-hostname-verification-disabled.yaml b/jvm/mongo-hostname-verification-disabled.yaml new file mode 100644 index 0000000..962e82f --- /dev/null +++ b/jvm/mongo-hostname-verification-disabled.yaml @@ -0,0 +1,16 @@ +rules: + - id: mongo-hostname-verification-disabled + message: Found MongoDB client with SSL hostname verification disabled + languages: [java, kotlin] + severity: WARNING + metadata: + category: security + subcategory: [audit] + technology: [java, kotlin, mongodb] + cwe: "CWE-295: Improper Certificate Validation" + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://www.mongodb.com/docs/drivers/java/sync/current/fundamentals/connection/tls/#disable-hostname-verification + pattern: $SETTINGS.invalidHostNameAllowed(true) diff --git a/yaml/ansible/apt-key-unencrypted-url.test.yaml b/yaml/ansible/apt-key-unencrypted-url.test.yaml new file mode 100644 index 0000000..343f3bc --- /dev/null +++ b/yaml/ansible/apt-key-unencrypted-url.test.yaml @@ -0,0 +1,14 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.apt_key: + # ruleid: apt-key-unencrypted-url + url: http://example.com/example-key.asc + state: present + - name: Negative test + ansible.builtin.apt_key: + # ok: apt-key-unencrypted-url + url: https://example.com/example-key.asc + state: present diff --git a/yaml/ansible/apt-key-unencrypted-url.yaml b/yaml/ansible/apt-key-unencrypted-url.yaml new file mode 100644 index 0000000..c23e66b --- /dev/null +++ b/yaml/ansible/apt-key-unencrypted-url.yaml @@ -0,0 +1,32 @@ +rules: + - id: apt-key-unencrypted-url + message: Found apt key download with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible, apt] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_key_module.html#parameter-url + patterns: + - pattern-inside: | + $APTKEY: + ... + - metavariable-pattern: + metavariable: $APTKEY + pattern-either: + - pattern: apt_key + - pattern: ansible.builtin.apt_key + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: url + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/ansible/apt-key-validate-certs-disabled.test.yaml b/yaml/ansible/apt-key-validate-certs-disabled.test.yaml new file mode 100644 index 0000000..c4c8903 --- /dev/null +++ b/yaml/ansible/apt-key-validate-certs-disabled.test.yaml @@ -0,0 +1,82 @@ +--- +# making sure it goes through all false values mentioned in https://yaml.org/type/bool.html ... +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: off + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: Off + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: OFF + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: false + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: False + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: FALSE + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: N + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: n + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: no + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: No + - name: Positive test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ruleid: apt-key-validate-certs-disabled + validate_certs: NO + - name: Negative test + ansible.builtin.apt_key: + # ok: apt-key-validate-certs-disabled + url: https://example.com/example-key.asc + state: present + - name: Negative test + ansible.builtin.apt_key: + url: https://example.com/example-key.asc + state: present + # ok: apt-key-validate-certs-disabled + validate_certs: true diff --git a/yaml/ansible/apt-key-validate-certs-disabled.yaml b/yaml/ansible/apt-key-validate-certs-disabled.yaml new file mode 100644 index 0000000..2777c06 --- /dev/null +++ b/yaml/ansible/apt-key-validate-certs-disabled.yaml @@ -0,0 +1,35 @@ +rules: + - id: apt-key-validate-certs-disabled + message: Found apt key with SSL verification disabled + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-295: Improper Certificate Validation" + subcategory: [audit] + technology: [ansible, apt] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_key_module.html#parameter-validate_certs + patterns: + - pattern-inside: | + $APTKEY: + ... + url: ... + ... + - metavariable-pattern: + metavariable: $APTKEY + pattern-either: + - pattern: apt_key + - pattern: ansible.builtin.apt_key + - pattern: "$KEY: $VALUE" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: validate_certs + - metavariable-pattern: + metavariable: $VALUE + pattern-either: + - pattern: "false" diff --git a/yaml/ansible/apt-unencrypted-url.test.yaml b/yaml/ansible/apt-unencrypted-url.test.yaml new file mode 100644 index 0000000..87a656f --- /dev/null +++ b/yaml/ansible/apt-unencrypted-url.test.yaml @@ -0,0 +1,12 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.apt: + # ruleid: apt-unencrypted-url + deb: http://example.com/package.deb + - name: Negative test + ansible.builtin.apt: + # ok: apt-unencrypted-url + deb: https://example.com/package.deb diff --git a/yaml/ansible/apt-unencrypted-url.yaml b/yaml/ansible/apt-unencrypted-url.yaml new file mode 100644 index 0000000..b5024bf --- /dev/null +++ b/yaml/ansible/apt-unencrypted-url.yaml @@ -0,0 +1,32 @@ +rules: + - id: apt-unencrypted-url + message: Found apt deb with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible, apt] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html#parameter-deb + patterns: + - pattern-inside: | + $APT: + ... + - metavariable-pattern: + metavariable: $APT + pattern-either: + - pattern: apt + - pattern: ansible.builtin.apt + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: deb + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/ansible/dnf-unencrypted-url.test.yaml b/yaml/ansible/dnf-unencrypted-url.test.yaml new file mode 100644 index 0000000..6fed759 --- /dev/null +++ b/yaml/ansible/dnf-unencrypted-url.test.yaml @@ -0,0 +1,14 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.dnf: + # ruleid: dnf-unencrypted-url + name: http://example.com/example.rpm + state: present + - name: Negative test + ansible.builtin.dnf: + # ok: dnf-unencrypted-url + name: https://example.com/example.rpm + state: present diff --git a/yaml/ansible/dnf-unencrypted-url.yaml b/yaml/ansible/dnf-unencrypted-url.yaml new file mode 100644 index 0000000..63a548f --- /dev/null +++ b/yaml/ansible/dnf-unencrypted-url.yaml @@ -0,0 +1,36 @@ +rules: + - id: dnf-unencrypted-url + message: Found dnf download with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible, dnf] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/dnf_module.html#parameter-name + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/dnf5_module.html#parameter-name + patterns: + - pattern-inside: | + $DNF: + ... + - metavariable-pattern: + metavariable: $DNF + pattern-either: + - pattern: dnf + - pattern: ansible.builtin.dnf + - pattern: dnf5 + - pattern: ansible.builtin.dnf5 + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: name + - pattern: pkg + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/ansible/dnf-validate-certs-disabled.test.yaml b/yaml/ansible/dnf-validate-certs-disabled.test.yaml new file mode 100644 index 0000000..3df7fae --- /dev/null +++ b/yaml/ansible/dnf-validate-certs-disabled.test.yaml @@ -0,0 +1,15 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.dnf: + name: https://example.com/example.rpm + state: present + # ruleid: dnf-validate-certs-disabled + validate_certs: false + - name: Negative test (dnf-unencrypted-url and dnf-validate-certs-disabled) + ansible.builtin.dnf: + # ok: dnf-validate-certs-disabled + name: https://example.com/example.rpm + state: present diff --git a/yaml/ansible/dnf-validate-certs-disabled.yaml b/yaml/ansible/dnf-validate-certs-disabled.yaml new file mode 100644 index 0000000..969ab03 --- /dev/null +++ b/yaml/ansible/dnf-validate-certs-disabled.yaml @@ -0,0 +1,36 @@ +rules: + - id: dnf-validate-certs-disabled + message: Found dnf with SSL verification disabled + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-295: Improper Certificate Validation" + subcategory: [audit] + technology: [ansible, dnf] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/dnf_module.html#parameter-validate_certs + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/dnf5_module.html#parameter-validate_certs + patterns: + - pattern-inside: | + $DNF: + ... + - metavariable-pattern: + metavariable: $DNF + pattern-either: + - pattern: dnf + - pattern: ansible.builtin.dnf + - pattern: dnf5 + - pattern: ansible.builtin.dnf5 + - pattern: "$KEY: $VALUE" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: validate_certs + - metavariable-pattern: + metavariable: $VALUE + pattern-either: + - pattern: "false" diff --git a/yaml/ansible/get-url-unencrypted-url.test.yaml b/yaml/ansible/get-url-unencrypted-url.test.yaml new file mode 100644 index 0000000..1288619 --- /dev/null +++ b/yaml/ansible/get-url-unencrypted-url.test.yaml @@ -0,0 +1,38 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.get_url: + # ruleid: get-url-unencrypted-url + url: http://example.com/file.txt + dest: /etc/file.txt + - name: Positive test + ansible.windows.win_get_url: + # ruleid: get-url-unencrypted-url + url: http://example.com/file.txt + dest: C:\Users\ExampleUser\file.txt + - name: Negative test + ansible.builtin.get_url: + # ok: get-url-unencrypted-url + url: https://example.com/file.txt + dest: /etc/file.txt + - name: Negative test + ansible.windows.win_get_url: + # ok: get-url-unencrypted-url + url: https://example.com/file.txt + dest: C:\Users\ExampleUser\file.txt + - name: Negative test + ansible.builtin.get_url: + # ok: get-url-unencrypted-url + url: http://example.com/file.txt + validate_certs: false + dest: /etc/file.txt + checksum: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: Negative test + ansible.windows.win_get_url: + # ok: get-url-unencrypted-url + url: http://example.com/file.txt + validate_certs: false + dest: C:\Users\ExampleUser\file.txt + checksum: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/yaml/ansible/get-url-unencrypted-url.yaml b/yaml/ansible/get-url-unencrypted-url.yaml new file mode 100644 index 0000000..d7542f1 --- /dev/null +++ b/yaml/ansible/get-url-unencrypted-url.yaml @@ -0,0 +1,42 @@ +rules: + - id: get-url-unencrypted-url + message: Found file download with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/get_url_module.html#parameter-url + - https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_get_url_module.html#parameter-url + patterns: + - pattern-inside: | + $GETURL: + ... + # Assume if they specify a "checksum", then this is a trust-on-first-use + # situation, or they've otherwise pre-validated the download. + - pattern-not-inside: | + $GETURL: + ... + checksum: ... + ... + - metavariable-pattern: + metavariable: $GETURL + pattern-either: + - pattern: get_url + - pattern: win_get_url + - pattern: ansible.builtin.get_url + - pattern: ansible.windows.win_get_url + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: url + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/ansible/get-url-validate-certs-disabled.test.yaml b/yaml/ansible/get-url-validate-certs-disabled.test.yaml new file mode 100644 index 0000000..d553e87 --- /dev/null +++ b/yaml/ansible/get-url-validate-certs-disabled.test.yaml @@ -0,0 +1,40 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.get_url: + url: https://example.com/file.txt + # ruleid: get-url-validate-certs-disabled + validate_certs: false + dest: /etc/file.txt + - name: Positive test + ansible.windows.win_get_url: + url: https://example.com/file.txt + # ruleid: get-url-validate-certs-disabled + validate_certs: false + dest: C:\Users\ExampleUser\file.txt + - name: Negative test + ansible.builtin.get_url: + # ok: get-url-validate-certs-disabled + url: https://example.com/file.txt + dest: /etc/file.txt + - name: Negative test + ansible.windows.win_get_url: + # ok: get-url-validate-certs-disabled + url: https://example.com/file.txt + dest: C:\Users\ExampleUser\file.txt + - name: Negative test + ansible.builtin.get_url: + url: http://example.com/file.txt + # ok: get-url-validate-certs-disabled + validate_certs: false + dest: /etc/file.txt + checksum: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: Negative test + ansible.windows.win_get_url: + url: http://example.com/file.txt + # ok: get-url-validate-certs-disabled + validate_certs: false + dest: C:\Users\ExampleUser\file.txt + checksum: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/yaml/ansible/get-url-validate-certs-disabled.yaml b/yaml/ansible/get-url-validate-certs-disabled.yaml new file mode 100644 index 0000000..822381f --- /dev/null +++ b/yaml/ansible/get-url-validate-certs-disabled.yaml @@ -0,0 +1,45 @@ +rules: + - id: get-url-validate-certs-disabled + message: Found file download with SSL verification disabled + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-295: Improper Certificate Validation" + subcategory: [audit] + technology: [ansible] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/get_url_module.html#parameter-validate_certs + - https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_get_url_module.html#parameter-validate_certs + patterns: + - pattern-inside: | + $GETURL: + ... + url: ... + ... + # Assume if they specify a "checksum", then this is a trust-on-first-use + # situation, or they've otherwise pre-validated the download. + - pattern-not-inside: | + $GETURL: + ... + checksum: ... + ... + - metavariable-pattern: + metavariable: $GETURL + pattern-either: + - pattern: get_url + - pattern: win_get_url + - pattern: ansible.builtin.get_url + - pattern: ansible.windows.win_get_url + - pattern: "$KEY: $VALUE" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: validate_certs + - metavariable-pattern: + metavariable: $VALUE + pattern-either: + - pattern: "false" diff --git a/yaml/ansible/rpm-key-unencrypted-url.test.yaml b/yaml/ansible/rpm-key-unencrypted-url.test.yaml new file mode 100644 index 0000000..9b2e15c --- /dev/null +++ b/yaml/ansible/rpm-key-unencrypted-url.test.yaml @@ -0,0 +1,14 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.rpm_key: + state: present + # ruleid: rpm-key-unencrypted-url + key: http://example.com/RPM-GPG-KEY.dag.txt + - name: Negative test (rpm-key-unencrypted-url and rpm-key-validate-certs-disabled) + ansible.builtin.rpm_key: + state: present + # ok: rpm-key-unencrypted-url + key: https://example.com/RPM-GPG-KEY.dag.txt diff --git a/yaml/ansible/rpm-key-unencrypted-url.yaml b/yaml/ansible/rpm-key-unencrypted-url.yaml new file mode 100644 index 0000000..7465ae0 --- /dev/null +++ b/yaml/ansible/rpm-key-unencrypted-url.yaml @@ -0,0 +1,32 @@ +rules: + - id: rpm-key-unencrypted-url + message: Found RPM key download with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible, rpm] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/rpm_key_module.html#parameter-key + patterns: + - pattern-inside: | + $RPMKEY: + ... + - metavariable-pattern: + metavariable: $RPMKEY + pattern-either: + - pattern: rpm_key + - pattern: ansible.builtin.rpm_key + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: key + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/ansible/rpm-key-validate-certs-disabled.test.yaml b/yaml/ansible/rpm-key-validate-certs-disabled.test.yaml new file mode 100644 index 0000000..c11a932 --- /dev/null +++ b/yaml/ansible/rpm-key-validate-certs-disabled.test.yaml @@ -0,0 +1,15 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test (rpm-key-validate-certs-disabled) + ansible.builtin.rpm_key: + state: present + key: https://example.com/RPM-GPG-KEY.dag.txt + # ruleid: rpm-key-validate-certs-disabled + validate_certs: false + - name: Negative test (rpm-key-unencrypted-url and rpm-key-validate-certs-disabled) + ansible.builtin.rpm_key: + # ok: rpm-key-validate-certs-disabled + state: present + key: https://example.com/RPM-GPG-KEY.dag.txt diff --git a/yaml/ansible/rpm-key-validate-certs-disabled.yaml b/yaml/ansible/rpm-key-validate-certs-disabled.yaml new file mode 100644 index 0000000..a105ae2 --- /dev/null +++ b/yaml/ansible/rpm-key-validate-certs-disabled.yaml @@ -0,0 +1,35 @@ +rules: + - id: rpm-key-validate-certs-disabled + message: Found RPM key with SSL verification disabled + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-295: Improper Certificate Validation" + subcategory: [audit] + technology: [ansible, rpm] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/rpm_key_module.html#parameter-validate_certs + patterns: + - pattern-inside: | + $RPMKEY: + ... + key: ... + ... + - metavariable-pattern: + metavariable: $RPMKEY + pattern-either: + - pattern: rpm_key + - pattern: ansible.builtin.rpm_key + - pattern: "$KEY: $VALUE" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: validate_certs + - metavariable-pattern: + metavariable: $VALUE + pattern-either: + - pattern: "false" diff --git a/yaml/ansible/unarchive-unencrypted-url.test.yaml b/yaml/ansible/unarchive-unencrypted-url.test.yaml new file mode 100644 index 0000000..6b9a041 --- /dev/null +++ b/yaml/ansible/unarchive-unencrypted-url.test.yaml @@ -0,0 +1,16 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.unarchive: + # ruleid: unarchive-unencrypted-url + src: http://example.com/example.zip + dest: /usr/local/bin + remote_src: yes + - name: Negative test + ansible.builtin.unarchive: + # ok: unarchive-unencrypted-url + src: https://example.com/example.zip + dest: /usr/local/bin + remote_src: yes diff --git a/yaml/ansible/unarchive-unencrypted-url.yaml b/yaml/ansible/unarchive-unencrypted-url.yaml new file mode 100644 index 0000000..64e683d --- /dev/null +++ b/yaml/ansible/unarchive-unencrypted-url.yaml @@ -0,0 +1,32 @@ +rules: + - id: unarchive-unencrypted-url + message: Found unarchive download with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/unarchive_module.html#parameter-src + patterns: + - pattern-inside: | + $UNARCHIVE: + ... + - metavariable-pattern: + metavariable: $UNARCHIVE + pattern-either: + - pattern: unarchive + - pattern: ansible.builtin.unarchive + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: src + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/ansible/unarchive-validate-certs-disabled.test.yaml b/yaml/ansible/unarchive-validate-certs-disabled.test.yaml new file mode 100644 index 0000000..7bda792 --- /dev/null +++ b/yaml/ansible/unarchive-validate-certs-disabled.test.yaml @@ -0,0 +1,17 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.unarchive: + src: https://example.com/example.zip + dest: /usr/local/bin + remote_src: yes + # ruleid: unarchive-validate-certs-disabled + validate_certs: false + - name: Negative test (unarchive-unencrypted-url and unarchive-validate-certs-disabled) + ansible.builtin.unarchive: + # ok: unarchive-validate-certs-disabled + src: https://example.com/example.zip + dest: /usr/local/bin + remote_src: yes diff --git a/yaml/ansible/unarchive-validate-certs-disabled.yaml b/yaml/ansible/unarchive-validate-certs-disabled.yaml new file mode 100644 index 0000000..6071d6c --- /dev/null +++ b/yaml/ansible/unarchive-validate-certs-disabled.yaml @@ -0,0 +1,33 @@ +rules: + - id: unarchive-validate-certs-disabled + message: Found unarchive download with SSL verification disabled + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-295: Improper Certificate Validation" + subcategory: [audit] + technology: [ansible] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/unarchive_module.html#parameter-validate_certs + patterns: + - pattern-inside: | + $UNARCHIVE: + ... + - metavariable-pattern: + metavariable: $UNARCHIVE + pattern-either: + - pattern: unarchive + - pattern: ansible.builtin.unarchive + - pattern: "$KEY: $VALUE" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: validate_certs + - metavariable-pattern: + metavariable: $VALUE + pattern-either: + - pattern: "false" diff --git a/yaml/ansible/wrm-cert-validation-ignore.test.yaml b/yaml/ansible/wrm-cert-validation-ignore.test.yaml new file mode 100644 index 0000000..f962f4e --- /dev/null +++ b/yaml/ansible/wrm-cert-validation-ignore.test.yaml @@ -0,0 +1,4 @@ +--- +- name: Positive test + # ruleid: wrm-cert-validation-ignore + ansible_winrm_server_cert_validation: ignore diff --git a/yaml/ansible/wrm-cert-validation-ignore.yaml b/yaml/ansible/wrm-cert-validation-ignore.yaml new file mode 100644 index 0000000..ddca5c7 --- /dev/null +++ b/yaml/ansible/wrm-cert-validation-ignore.yaml @@ -0,0 +1,16 @@ +rules: + - id: wrm-cert-validation-ignore + message: Found Windows Remote Management connection with certificate validation disabled + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-295: Improper Certificate Validation" + subcategory: [audit] + technology: [ansible] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/os_guide/windows_winrm.html#https-certificate-validation + pattern: "ansible_winrm_server_cert_validation: ignore" diff --git a/yaml/ansible/yum-unencrypted-url.test.yaml b/yaml/ansible/yum-unencrypted-url.test.yaml new file mode 100644 index 0000000..4853284 --- /dev/null +++ b/yaml/ansible/yum-unencrypted-url.test.yaml @@ -0,0 +1,14 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + ansible.builtin.yum: + # ruleid: yum-unencrypted-url + name: http://example.com/package.rpm + state: present + - name: Negative test (yum-unencrypted-url and yum-validate-certs-disabled) + ansible.builtin.yum: + # ok: yum-unencrypted-url + name: https://example.com/package.rpm + state: present diff --git a/yaml/ansible/yum-unencrypted-url.yaml b/yaml/ansible/yum-unencrypted-url.yaml new file mode 100644 index 0000000..8eded10 --- /dev/null +++ b/yaml/ansible/yum-unencrypted-url.yaml @@ -0,0 +1,33 @@ +rules: + - id: yum-unencrypted-url + message: Found yum download with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible, yum] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/yum_module.html#parameter-name + patterns: + - pattern-inside: | + $YUM: + ... + - metavariable-pattern: + metavariable: $YUM + pattern-either: + - pattern: yum + - pattern: ansible.builtin.yum + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: name + - pattern: pkg + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/ansible/yum-validate-certs-disabled.test.yaml b/yaml/ansible/yum-validate-certs-disabled.test.yaml new file mode 100644 index 0000000..c8e6818 --- /dev/null +++ b/yaml/ansible/yum-validate-certs-disabled.test.yaml @@ -0,0 +1,15 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test (yum-validate-certs-disabled) + ansible.builtin.yum: + name: https://example.com/package.rpm + state: present + # ruleid: yum-validate-certs-disabled + validate_certs: false + - name: Negative test (yum-unencrypted-url and yum-validate-certs-disabled) + ansible.builtin.yum: + # ok: yum-validate-certs-disabled + name: https://example.com/package.rpm + state: present diff --git a/yaml/ansible/yum-validate-certs-disabled.yaml b/yaml/ansible/yum-validate-certs-disabled.yaml new file mode 100644 index 0000000..bde0c18 --- /dev/null +++ b/yaml/ansible/yum-validate-certs-disabled.yaml @@ -0,0 +1,33 @@ +rules: + - id: yum-validate-certs-disabled + message: Found yum with SSL verification disabled + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-295: Improper Certificate Validation" + subcategory: [audit] + technology: [ansible, yum] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/yum_module.html#parameter-validate_certs + patterns: + - pattern-inside: | + $YUM: + ... + - metavariable-pattern: + metavariable: $YUM + pattern-either: + - pattern: yum + - pattern: ansible.builtin.yum + - pattern: "$KEY: $VALUE" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: validate_certs + - metavariable-pattern: + metavariable: $VALUE + pattern-either: + - pattern: "false" diff --git a/yaml/ansible/zypper-repository-unencrypted-url.test.yaml b/yaml/ansible/zypper-repository-unencrypted-url.test.yaml new file mode 100644 index 0000000..5e3844d --- /dev/null +++ b/yaml/ansible/zypper-repository-unencrypted-url.test.yaml @@ -0,0 +1,14 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + community.general.zypper_repository: + # ruleid: zypper-repository-unencrypted-url + repo: "http://example.com/repo/" + auto_import_keys: true + - name: Negative test + community.general.zypper_repository: + # ok: zypper-repository-unencrypted-url + repo: "https://example.com/repo/" + auto_import_keys: true diff --git a/yaml/ansible/zypper-repository-unencrypted-url.yaml b/yaml/ansible/zypper-repository-unencrypted-url.yaml new file mode 100644 index 0000000..8c69100 --- /dev/null +++ b/yaml/ansible/zypper-repository-unencrypted-url.yaml @@ -0,0 +1,32 @@ +rules: + - id: zypper-repository-unencrypted-url + message: Found Zypper repository with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible, zypper] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/community/general/zypper_module.html#parameter-name + patterns: + - pattern-inside: | + $ZYPPER: + ... + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: repo + - metavariable-pattern: + metavariable: $ZYPPER + pattern-either: + - pattern: zypper_repository + - pattern: community.general.zypper_repository + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/ansible/zypper-unencrypted-url.test.yaml b/yaml/ansible/zypper-unencrypted-url.test.yaml new file mode 100644 index 0000000..0b7d7a8 --- /dev/null +++ b/yaml/ansible/zypper-unencrypted-url.test.yaml @@ -0,0 +1,14 @@ +--- +- name: Semgrep tests + hosts: all + tasks: + - name: Positive test + community.general.zypper: + # ruleid: zypper-unencrypted-url + name: "http://example.com/package.rpm" + state: present + - name: Negative test + community.general.zypper: + # ok: zypper-unencrypted-url + name: "https://example.com/package.rpm" + state: present diff --git a/yaml/ansible/zypper-unencrypted-url.yaml b/yaml/ansible/zypper-unencrypted-url.yaml new file mode 100644 index 0000000..e99dcf3 --- /dev/null +++ b/yaml/ansible/zypper-unencrypted-url.yaml @@ -0,0 +1,33 @@ +rules: + - id: zypper-unencrypted-url + message: Found Zypper package with unencrypted URL (e.g. HTTP, FTP, etc.) + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-319: Cleartext Transmission of Sensitive Information" + subcategory: [audit] + technology: [ansible, zypper] + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://docs.ansible.com/ansible/latest/collections/community/general/zypper_module.html#parameter-name + patterns: + - pattern-inside: | + $ZYPPER: + ... + - pattern: "$KEY: '$VALUE'" + - metavariable-pattern: + metavariable: $KEY + pattern-either: + - pattern: name + - pattern: pkg + - metavariable-pattern: + metavariable: $ZYPPER + pattern-either: + - pattern: zypper + - pattern: community.general.zypper + - metavariable-regex: + metavariable: $VALUE + regex: "(?i)^(http|ftp):\/\/.*" diff --git a/yaml/docker-compose/port-all-interfaces.test.yaml b/yaml/docker-compose/port-all-interfaces.test.yaml new file mode 100644 index 0000000..8fe67e6 --- /dev/null +++ b/yaml/docker-compose/port-all-interfaces.test.yaml @@ -0,0 +1,29 @@ +--- +services: + web: + build: . + ports: + # ruleid: port-all-interfaces + - "3000" + # ruleid: port-all-interfaces + - "3000-3005" + # ruleid: port-all-interfaces + - "8000:8000" + # ruleid: port-all-interfaces + - "9090-9091:8080-8081" + # ruleid: port-all-interfaces + - "49100:22" + # ruleid: port-all-interfaces + - "8000-9000:80" + # ruleid: port-all-interfaces + - "6060:6060/udp" + # ok: port-all-interfaces + - "127.0.0.1:8001:8001" + # ok: port-all-interfaces + - "127.0.0.2:8001:8001" + # ok: port-all-interfaces + - "127.255.255.255:8001:8001" + # ok: port-all-interfaces + - "127.0.0.1:5000-5010:5000-5010" + redis: + image: "redis:alpine" diff --git a/yaml/docker-compose/port-all-interfaces.yaml b/yaml/docker-compose/port-all-interfaces.yaml new file mode 100644 index 0000000..efbe77f --- /dev/null +++ b/yaml/docker-compose/port-all-interfaces.yaml @@ -0,0 +1,28 @@ +rules: + - id: port-all-interfaces + message: Service port is exposed on all interfaces + languages: [yaml] + severity: WARNING + metadata: + category: security + cwe: "CWE-1327: Binding to an Unrestricted IP Address" + subcategory: [audit] + technology: [docker, compose] + confidence: LOW + likelihood: LOW + impact: LOW + references: + - https://docs.docker.com/compose/compose-file/compose-file-v3/#ports + patterns: + - pattern-inside: | + services: + ... + - pattern: | + ports: + - ... + - "$PORT" + - ... + - focus-metavariable: $PORT + - metavariable-regex: + metavariable: $PORT + regex: '^(?!127.\d{1,3}.\d{1,3}.\d{1,3}:).+'