From 54f3843e973de09415bbce6aaa373bedb250b99b Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Tue, 28 Oct 2025 10:08:56 -0700 Subject: [PATCH 1/2] Updated rulesets to reduce false positives --- .gitignore | 4 +- .gitmodules | 6 + README.md | 10 +- app_tests/govwa | 1 + app_tests/play-webgoat | 1 + docs/github-action.md | 38 +- docs/local-install-docker.md | 70 +- docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- socket_basics/connectors.yaml | 28 +- socket_basics/rules/c_cpp.yml | 18 +- socket_basics/rules/dotnet.yml | 113 +- socket_basics/rules/elixir.yml | 12 +- socket_basics/rules/erlang.yml | 30 +- socket_basics/rules/go.yml | 157 +-- socket_basics/rules/java.yml | 244 +++- socket_basics/rules/javascript_typescript.yml | 578 +++++--- socket_basics/rules/kotlin.yml | 25 +- socket_basics/rules/objective-c.yml | 20 +- socket_basics/rules/php.yml | 295 ++-- socket_basics/rules/python.yml | 1231 +++++++++++++++-- socket_basics/rules/ruby.yml | 208 ++- socket_basics/rules/rust.yml | 94 +- socket_basics/rules/scala.yml | 75 +- socket_basics/rules/swift.yml | 66 +- socket_basics/version.py | 2 +- 26 files changed, 2536 insertions(+), 794 deletions(-) create mode 160000 app_tests/govwa create mode 160000 app_tests/play-webgoat diff --git a/.gitignore b/.gitignore index 2272eac..66ccb20 100644 --- a/.gitignore +++ b/.gitignore @@ -101,4 +101,6 @@ logs/ *.log .python-version -.socket.fact.json \ No newline at end of file +.socket.fact.json + +custom_rules/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 94e0276..ca0bf8a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,9 @@ [submodule "app_tests/scala-woof"] path = app_tests/scala-woof url = https://github.com/snyk/scala-woof.git +[submodule "app_tests/govwa"] + path = app_tests/govwa + url = https://github.com/0c34/govwa +[submodule "app_tests/play-webgoat"] + path = app_tests/play-webgoat + url = https://github.com/playframework/play-webgoat diff --git a/README.md b/README.md index 37a8735..5953e44 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.21 + uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.21 . +docker build -t socketdev/socket-basics:1.0.22 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.21 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.22 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/app_tests/govwa b/app_tests/govwa new file mode 160000 index 0000000..4058f79 --- /dev/null +++ b/app_tests/govwa @@ -0,0 +1 @@ +Subproject commit 4058f79f31eeb4a36d8f1e64bba1f0c899646e6f diff --git a/app_tests/play-webgoat b/app_tests/play-webgoat new file mode 160000 index 0000000..ac935d8 --- /dev/null +++ b/app_tests/play-webgoat @@ -0,0 +1 @@ +Subproject commit ac935d8746cf48a1a557e51798e53c4e7e411996 diff --git a/docs/github-action.md b/docs/github-action.md index 8d7b019..03b9f37 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.21 + uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.21 +> - uses: SocketDev/socket-basics@1.0.22 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.21 +- uses: SocketDev/socket-basics@1.0.22 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.21 + uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.21 + uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.21:${{ github.sha }} . + run: docker build -t myapp:1.0.22:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.21 + uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.21 + uses: SocketDev/socket-basics@1.0.22 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.21 + - uses: SocketDev/socket-basics@1.0.22 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index bb1f3e8..d247963 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.21 . +docker build -t socket-basics:1.0.22 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.21 . +docker build -t socket-basics:1.0.22 . # Or build with latest tag -docker build -t socket-basics:1.0.21:latest . +docker build -t socket-basics:1.0.22:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.21 . +docker build -t myorg/security-scanner:1.0.22 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.21 . +docker build --platform linux/amd64 -t socket-basics:1.0.22 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.21 socket-basics --version -docker run --rm socket-basics:1.0.21 socket --version -docker run --rm socket-basics:1.0.21 trivy --version -docker run --rm socket-basics:1.0.21 semgrep --version -docker run --rm socket-basics:1.0.21 trufflehog --version +docker run --rm socket-basics:1.0.22 socket-basics --version +docker run --rm socket-basics:1.0.22 socket --version +docker run --rm socket-basics:1.0.22 trivy --version +docker run --rm socket-basics:1.0.22 semgrep --version +docker run --rm socket-basics:1.0.22 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.21 + socket-basics:1.0.22 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.21').inside( + docker.image('socket-basics:1.0.22').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.21 + image: socket-basics:1.0.22 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.21 + socket-basics:1.0.22 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.21 + socket-basics:1.0.22 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.21 \ + socket-basics:1.0.22 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.21 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.22 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.21 .' +alias sb-build='docker build -t socket-basics:1.0.22 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.21" +IMAGE_NAME="socket-basics:1.0.22" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index fc2971d..07a586f 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.21 . +docker build -t socket-basics:1.0.22 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index e30b011..86484e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.21" +version = "1.0.22" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/connectors.yaml b/socket_basics/connectors.yaml index bbb7202..815a85e 100644 --- a/socket_basics/connectors.yaml +++ b/socket_basics/connectors.yaml @@ -170,7 +170,7 @@ connectors: description: "Comma-separated list of Python SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_PYTHON_ENABLED_RULES type: str - default: "python-exec-used,python-bad-file-permissions,python-hardcoded-password-string,python-eval-usage,python-request-without-cert-validation,python-ssl-bad-version,python-subprocess-shell-true,python-start-process-with-shell,python-sql-injection-format,python-flask-debug-true,python-jinja2-autoescape-false" + default: "python-path-traversal-open,python-open-redirect,python-weak-hash-md5,python-weak-hash-sha1,python-weak-cipher-des,python-ssl-verify-disabled,python-insecure-tls-version,python-code-injection-eval,python-sql-injection,python-nosql-injection,python-command-injection,python-ldap-injection,python-xss-template,python-template-injection,python-yaml-load-unsafe,python-debug-mode-enabled,python-weak-session-config,python-insecure-file-permissions,python-jwt-no-verify,python-weak-jwt-algorithm,python-plain-text-password,python-unsafe-deserialization,python-ssrf-vulnerability,python-bare-except,python-dangerous-eval-exec,python-sql-format-string,python-insecure-temp-file" - name: python_disabled_rules option: --python-disabled-rules description: "Comma-separated list of Python SAST rules to disable" @@ -198,7 +198,7 @@ connectors: description: "Comma-separated list of Go SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_GO_ENABLED_RULES type: str - default: "go-hardcoded-credentials,go-bind-all-interfaces,go-unsafe-usage,go-ssh-insecure-ignore-host-key,go-profiling-endpoint-exposed,go-decompression-bomb,go-sql-format-string" + default: "go-hardcoded-credentials,go-ssh-insecure-ignore-host-key,go-sql-format-string,go-sql-string-concat,go-command-execution,go-file-path-traversal,go-zip-traversal,go-bad-tls-connection,go-import-des,go-import-rc4,go-empty-password,go-sql-direct-concat" - name: go_disabled_rules option: --go-disabled-rules description: "Comma-separated list of Go SAST rules to disable" @@ -212,7 +212,7 @@ connectors: description: "Comma-separated list of Java SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_JAVA_ENABLED_RULES type: str - default: "java-sql-injection,java-unsafe-deserialization,java-command-injection,java-ldap-injection,java-hardcoded-credentials,java-weak-crypto-md5,java-weak-crypto-sha1,java-xxe-vulnerability,java-ssl-bypass,java-weak-ssl-version,java-jndi-injection,java-el-injection" + default: "java-reflection-injection,java-sql-injection,java-unsafe-deserialization,java-command-injection,java-ldap-injection,java-hardcoded-credentials,java-weak-crypto-md5,java-weak-crypto-sha1,java-insecure-random,java-xxe-vulnerability,java-path-traversal,java-ssl-bypass,java-spring-security-bypass,java-jpa-sql-injection,java-struts-ognl-injection,java-jndi-injection,java-el-injection,java-template-injection,java-file-upload-no-validation" - name: java_disabled_rules option: --java-disabled-rules description: "Comma-separated list of Java SAST rules to disable" @@ -226,7 +226,7 @@ connectors: description: "Comma-separated list of PHP SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_PHP_ENABLED_RULES type: str - default: "php-code-injection,php-sql-injection,php-command-injection,php-unsafe-deserialization,php-ldap-injection,php-file-inclusion,php-xxe-vulnerability,php-hardcoded-secrets,php-path-traversal" + default: "php-code-injection,php-sql-injection,php-command-injection,php-unsafe-deserialization,php-ldap-injection,php-file-inclusion,php-xss,php-hardcoded-secrets,php-path-traversal,php-open-redirect,php-xxe-vulnerability,php-laravel-security,php-wordpress-security,php-codeigniter-security,php-file-upload-vulnerability,php-insecure-direct-object-reference,php-prepared-statement-injection" - name: php_disabled_rules option: --php-disabled-rules description: "Comma-separated list of PHP SAST rules to disable" @@ -240,7 +240,7 @@ connectors: description: "Comma-separated list of Ruby SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_RUBY_ENABLED_RULES type: str - default: "ruby-eval-injection,ruby-command-injection,ruby-sql-injection,ruby-unsafe-deserialization,ruby-hardcoded-secrets,ruby-ssl-verification-bypass,ruby-rails-find-by-sql-injection,ruby-rails-unsafe-constantize,ruby-xxe-vulnerability" + default: "ruby-eval-injection,ruby-command-injection,ruby-sql-injection,ruby-unsafe-deserialization,ruby-dynamic-method-definition,ruby-hardcoded-secrets,ruby-path-traversal,ruby-open-redirect,ruby-xss-raw-output,ruby-ssl-verification-bypass,ruby-weak-crypto,ruby-rails-find-by-sql-injection,ruby-rails-where-injection,ruby-template-injection" - name: ruby_disabled_rules option: --ruby-disabled-rules description: "Comma-separated list of Ruby SAST rules to disable" @@ -254,7 +254,7 @@ connectors: description: "Comma-separated list of C# SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_CSHARP_ENABLED_RULES type: str - default: "dotnet-sql-injection,dotnet-command-injection,dotnet-code-injection,dotnet-unsafe-deserialization,dotnet-ldap-injection,dotnet-hardcoded-credentials,dotnet-ssl-bypass,dotnet-xxe-vulnerability,dotnet-xpath-injection" + default: "dotnet-sql-injection,dotnet-command-injection,dotnet-code-injection,dotnet-unsafe-deserialization,dotnet-ldap-injection,dotnet-hardcoded-credentials,dotnet-weak-crypto-md5,dotnet-weak-crypto-sha1,dotnet-ssl-bypass,dotnet-xss-response-write,dotnet-path-traversal,dotnet-insecure-random,dotnet-xxe-vulnerability,dotnet-aspnet-validaterequest-false,dotnet-aspnet-viewstate-mac-disabled,dotnet-aspnetcore-auth-bypass,dotnet-ef-sql-injection,dotnet-broken-access-control,dotnet-crypto-failures,dotnet-xpath-injection,dotnet-auth-failures,dotnet-integrity-failures,dotnet-ssrf,dotnet-unsafe-code" - name: csharp_disabled_rules option: --csharp-disabled-rules description: "Comma-separated list of C# SAST rules to disable" @@ -268,7 +268,7 @@ connectors: description: "Comma-separated list of .NET SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_DOTNET_ENABLED_RULES type: str - default: "dotnet-sql-injection,dotnet-command-injection,dotnet-code-injection,dotnet-unsafe-deserialization,dotnet-ldap-injection,dotnet-hardcoded-credentials,dotnet-ssl-bypass,dotnet-xxe-vulnerability,dotnet-xpath-injection" + default: "dotnet-sql-injection,dotnet-command-injection,dotnet-code-injection,dotnet-unsafe-deserialization,dotnet-ldap-injection,dotnet-hardcoded-credentials,dotnet-weak-crypto-md5,dotnet-weak-crypto-sha1,dotnet-ssl-bypass,dotnet-xss-response-write,dotnet-path-traversal,dotnet-insecure-random,dotnet-xxe-vulnerability,dotnet-aspnet-validaterequest-false,dotnet-aspnet-viewstate-mac-disabled,dotnet-aspnetcore-auth-bypass,dotnet-ef-sql-injection,dotnet-broken-access-control,dotnet-crypto-failures,dotnet-xpath-injection,dotnet-auth-failures,dotnet-integrity-failures,dotnet-ssrf,dotnet-unsafe-code" - name: dotnet_disabled_rules option: --dotnet-disabled-rules description: "Comma-separated list of .NET SAST rules to disable" @@ -282,7 +282,7 @@ connectors: description: "Comma-separated list of C SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_C_ENABLED_RULES type: str - default: "c-buffer-overflow,c-format-string-vulnerability,c-command-injection,c-sql-injection,c-use-after-free,c-hardcoded-secrets,c-weak-crypto,c-ssl-issues" + default: "c-buffer-overflow,c-format-string-vulnerability,c-command-injection,c-sql-injection,c-memory-management,c-use-after-free,c-integer-overflow,c-null-pointer-dereference,c-hardcoded-secrets,c-race-condition,cpp-unsafe-cast,cpp-memory-management,c-weak-crypto,c-ssl-issues,c-input-validation" - name: c_disabled_rules option: --c-disabled-rules description: "Comma-separated list of C SAST rules to disable" @@ -296,7 +296,7 @@ connectors: description: "Comma-separated list of C++ SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_CPP_ENABLED_RULES type: str - default: "c-buffer-overflow,c-format-string-vulnerability,c-command-injection,c-sql-injection,c-use-after-free,c-hardcoded-secrets,c-weak-crypto,c-ssl-issues,cpp-unsafe-cast,cpp-memory-management" + default: "c-buffer-overflow,c-format-string-vulnerability,c-command-injection,c-sql-injection,c-memory-management,c-use-after-free,c-integer-overflow,c-null-pointer-dereference,c-hardcoded-secrets,c-race-condition,cpp-unsafe-cast,cpp-memory-management,c-weak-crypto,c-ssl-issues,c-input-validation" - name: cpp_disabled_rules option: --cpp-disabled-rules description: "Comma-separated list of C++ SAST rules to disable" @@ -310,7 +310,7 @@ connectors: description: "Comma-separated list of Kotlin SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_KOTLIN_ENABLED_RULES type: str - default: "kotlin-sql-injection,kotlin-command-injection,kotlin-code-injection,kotlin-unsafe-deserialization,kotlin-hardcoded-secrets,kotlin-ssl-bypass,kotlin-xxe-vulnerability,kotlin-ldap-injection" + default: "kotlin-sql-injection,kotlin-command-injection,kotlin-code-injection,kotlin-unsafe-deserialization,kotlin-hardcoded-secrets,kotlin-weak-crypto-md5,kotlin-weak-crypto-sha1,kotlin-ssl-bypass,kotlin-path-traversal,kotlin-xss,kotlin-android-intent-user-input,kotlin-spring-security-bypass,kotlin-jpa-query-injection,kotlin-template-injection,kotlin-ldap-injection,kotlin-file-upload-no-validation,kotlin-xxe-vulnerability" - name: kotlin_disabled_rules option: --kotlin-disabled-rules description: "Comma-separated list of Kotlin SAST rules to disable" @@ -324,7 +324,7 @@ connectors: description: "Comma-separated list of Scala SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_SCALA_ENABLED_RULES type: str - default: "scala-sql-injection,scala-code-injection,scala-command-injection,scala-unsafe-deserialization,scala-hardcoded-secrets,scala-ssl-bypass,scala-slick-sql-injection" + default: "scala-sql-injection,scala-code-injection,scala-command-injection,scala-unsafe-deserialization,scala-hardcoded-secrets,scala-weak-crypto-md5,scala-weak-crypto-sha1,scala-ssl-bypass,scala-path-traversal,scala-xss-template,scala-slick-sql-injection,scala-json-injection,scala-file-upload-no-validation" - name: scala_disabled_rules option: --scala-disabled-rules description: "Comma-separated list of Scala SAST rules to disable" @@ -338,7 +338,7 @@ connectors: description: "Comma-separated list of Swift SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_SWIFT_ENABLED_RULES type: str - default: "swift-sql-injection,swift-command-injection,swift-unsafe-deserialization,swift-hardcoded-secrets,swift-ssl-bypass,swift-insecure-urlsession,swift-certificate-pinning-bypass" + default: "swift-sql-injection,swift-command-injection,swift-unsafe-deserialization,swift-hardcoded-secrets,swift-weak-crypto-md5,swift-weak-crypto-sha1,swift-ssl-bypass,swift-path-traversal,swift-webview-xss,swift-ios-insecure-storage,swift-macos-privilege-escalation,swift-macos-code-signing,swift-certificate-pinning-bypass,swift-core-data-injection" - name: swift_disabled_rules option: --swift-disabled-rules description: "Comma-separated list of Swift SAST rules to disable" @@ -352,7 +352,7 @@ connectors: description: "Comma-separated list of Rust SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_RUST_ENABLED_RULES type: str - default: "rust-command-injection,rust-unsafe-deserialization,rust-sql-injection,rust-hardcoded-secrets,rust-insecure-tls,rust-buffer-overflow-potential" + default: "rust-unsafe-usage,rust-command-injection,rust-unsafe-deserialization,rust-sql-injection,rust-hardcoded-secrets,rust-weak-crypto-md5,rust-weak-crypto-sha1,rust-insecure-tls,rust-path-traversal,rust-buffer-overflow-potential,rust-diesel-injection,rust-serde-security,rust-memory-safety" - name: rust_disabled_rules option: --rust-disabled-rules description: "Comma-separated list of Rust SAST rules to disable" @@ -366,7 +366,7 @@ connectors: description: "Comma-separated list of Elixir SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_ELIXIR_ENABLED_RULES type: str - default: "elixir-code-injection,elixir-sql-injection,elixir-command-injection,elixir-unsafe-deserialization,elixir-hardcoded-secrets,elixir-phoenix-ecto-injection" + default: "elixir-code-injection,elixir-sql-injection,elixir-command-injection,elixir-unsafe-deserialization,elixir-hardcoded-secrets,elixir-weak-crypto,elixir-path-traversal,elixir-xss,elixir-open-redirect,elixir-phoenix-xss,elixir-phoenix-ecto-injection,elixir-phoenix-file-upload" - name: elixir_disabled_rules option: --elixir-disabled-rules description: "Comma-separated list of Elixir SAST rules to disable" diff --git a/socket_basics/rules/c_cpp.yml b/socket_basics/rules/c_cpp.yml index c3cfb0d..8221205 100644 --- a/socket_basics/rules/c_cpp.yml +++ b/socket_basics/rules/c_cpp.yml @@ -110,11 +110,11 @@ rules: message: "Integer overflow vulnerability detected" severity: HIGH languages: [c, cpp] - pattern-either: - - pattern: malloc($SIZE * $COUNT) - - pattern: calloc($SIZE, $COUNT) - - pattern: $BUF[$INDEX + $OFFSET] - where: + patterns: + - pattern-either: + - pattern: malloc($SIZE * $COUNT) + - pattern: calloc($SIZE, $COUNT) + - pattern: $BUF[$INDEX + $OFFSET] - metavariable-pattern: metavariable: $SIZE pattern: $VAR @@ -432,10 +432,10 @@ rules: message: "Socket security issue detected" severity: MEDIUM languages: [c, cpp] - pattern-either: - - pattern: bind($SOCK, $ADDR, sizeof($ADDR)) - - pattern: connect($SOCK, $ADDR, sizeof($ADDR)) - where: + patterns: + - pattern-either: + - pattern: bind($SOCK, $ADDR, sizeof($ADDR)) + - pattern: connect($SOCK, $ADDR, sizeof($ADDR)) - metavariable-pattern: metavariable: $ADDR pattern: $VAR diff --git a/socket_basics/rules/dotnet.yml b/socket_basics/rules/dotnet.yml index 3d52b58..773d145 100644 --- a/socket_basics/rules/dotnet.yml +++ b/socket_basics/rules/dotnet.yml @@ -1,21 +1,62 @@ rules: # === Critical Severity Rules === - # SQL injection + # SQL injection - using taint mode for accurate detection - id: dotnet-sql-injection - message: "SQL injection vulnerability detected" + message: "SQL injection vulnerability detected. User-controlled data flows into SQL command without proper sanitization. Use parameterized queries with Parameters.Add() or Parameters.AddWithValue() to prevent SQL injection." severity: CRITICAL languages: [csharp] - pattern-either: - # C# - - pattern: $CMD.CommandText = $QUERY + $USER_INPUT - - pattern: new SqlCommand($QUERY + $USER_INPUT, ...) - - pattern: $CMD.ExecuteQuery($QUERY + $USER_INPUT) - - pattern: string.Format($SQL, $USER_INPUT) - - pattern: $"...{$USER_INPUT}..." + mode: taint + pattern-sources: + - patterns: + - pattern: | + (string $X) + - pattern-not: | + "..." + pattern-propagators: + # StringBuilder propagation + - pattern: (StringBuilder $B).$ANY(...,(string $X),...) + from: $X + to: $B + # String.Format propagation + - pattern: String.Format($FMT, ..., (string $X), ...) + from: $X + to: $FMT + # String concatenation + - pattern: (string $A) + (string $B) + from: $B + to: $A + pattern-sinks: + - patterns: + - pattern-either: + # Command object instantiation + - patterns: + - pattern: | + new $PATTERN($CMD,...) + - focus-metavariable: $CMD + # CommandText property assignment + - patterns: + - pattern: | + $OBJ.$PATTERN = $VALUE; + - focus-metavariable: $VALUE + - metavariable-regex: + metavariable: $PATTERN + regex: ^(SqlCommand|CommandText|OleDbCommand|OdbcCommand|OracleCommand|MySqlCommand|NpgsqlCommand|SQLiteCommand|SqlCeCommand)$ + pattern-sanitizers: + # Parameterized query usage + - pattern-either: + - pattern: | + $CMD.Parameters.Add(...) + - pattern: | + $CMD.Parameters.AddWithValue(...) + - pattern: | + $CMD.Parameters[$IDX] = ... + by-side-effect: true metadata: category: security cwe: CWE-89 + owasp: + - A03:2021 - Injection confidence: high # Command injection @@ -86,15 +127,15 @@ rules: message: "Hardcoded credentials detected" severity: HIGH languages: [csharp] - pattern-either: - # C# - - pattern: | - private const string $VAR = "..."; - - pattern: | - public const string $VAR = "..."; - - pattern: | - string $VAR = "..."; - where: + patterns: + - pattern-either: + # C# + - pattern: | + private const string $VAR = "..."; + - pattern: | + public const string $VAR = "..."; + - pattern: | + string $VAR = "..."; - metavariable-regex: metavariable: $VAR regex: (?i).*(password|passwd|pwd|secret|token|key|api_key|connection_string).* @@ -252,14 +293,14 @@ rules: message: "Weak cryptographic key size detected" severity: MEDIUM languages: [csharp] - pattern-either: - - pattern: RSACryptoServiceProvider($SIZE) - - pattern: RSA.Create($SIZE) - - pattern: DSACryptoServiceProvider($SIZE) - where: - - metavariable-comparison: - metavariable: $SIZE - comparison: int($SIZE) < 2048 + patterns: + - pattern-either: + - pattern: RSACryptoServiceProvider(512) + - pattern: RSACryptoServiceProvider(1024) + - pattern: RSA.Create(512) + - pattern: RSA.Create(1024) + - pattern: DSACryptoServiceProvider(512) + - pattern: DSACryptoServiceProvider(1024) metadata: category: security cwe: CWE-310 @@ -312,12 +353,12 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [csharp] - pattern-either: - - pattern: Console.WriteLine($USER_INPUT) - - pattern: Debug.WriteLine($USER_INPUT) - - pattern: Trace.WriteLine($USER_INPUT) - - pattern: System.Diagnostics.Debug.Write($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: Console.WriteLine($USER_INPUT) + - pattern: Debug.WriteLine($USER_INPUT) + - pattern: Trace.WriteLine($USER_INPUT) + - pattern: System.Diagnostics.Debug.Write($USER_INPUT) - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* @@ -512,10 +553,10 @@ rules: message: "Insecure session management design" severity: MEDIUM languages: [csharp] - pattern-either: - - pattern: Session[$KEY] = $SENSITIVE_DATA - - pattern: HttpContext.Session.SetString($KEY, $SENSITIVE_DATA) - where: + patterns: + - pattern-either: + - pattern: Session[$KEY] = $SENSITIVE_DATA + - pattern: HttpContext.Session.SetString($KEY, $SENSITIVE_DATA) - metavariable-regex: metavariable: $SENSITIVE_DATA regex: (?i).*(password|credit_card|ssn|social_security).* diff --git a/socket_basics/rules/elixir.yml b/socket_basics/rules/elixir.yml index 10e807e..a669d52 100644 --- a/socket_basics/rules/elixir.yml +++ b/socket_basics/rules/elixir.yml @@ -212,12 +212,12 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [elixir] - pattern-either: - - pattern: IO.puts($USER_INPUT) - - pattern: IO.inspect($USER_INPUT) - - pattern: Logger.debug($USER_INPUT) - - pattern: Logger.info($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: IO.puts($USER_INPUT) + - pattern: IO.inspect($USER_INPUT) + - pattern: Logger.debug($USER_INPUT) + - pattern: Logger.info($USER_INPUT) - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* diff --git a/socket_basics/rules/erlang.yml b/socket_basics/rules/erlang.yml index dc83f91..9351ddf 100644 --- a/socket_basics/rules/erlang.yml +++ b/socket_basics/rules/erlang.yml @@ -218,12 +218,12 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [elixir] - pattern-either: - - pattern: IO.puts($USER_INPUT) - - pattern: IO.inspect($USER_INPUT) - - pattern: Logger.debug($USER_INPUT) - - pattern: Logger.info($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: IO.puts($USER_INPUT) + - pattern: IO.inspect($USER_INPUT) + - pattern: Logger.debug($USER_INPUT) + - pattern: Logger.info($USER_INPUT) - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* @@ -478,11 +478,11 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [erlang] - pattern-either: - - pattern: io:format("~p~n", [$USER_INPUT]) - - pattern: "error_logger:info_msg($USER_INPUT)" - - pattern: "lager:debug($USER_INPUT)" - where: + patterns: + - pattern-either: + - pattern: io:format("~p~n", [$USER_INPUT]) + - pattern: "error_logger:info_msg($USER_INPUT)" + - pattern: "lager:debug($USER_INPUT)" - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* @@ -644,10 +644,10 @@ rules: message: "Potential atom table exhaustion" severity: MEDIUM languages: [erlang] - pattern-either: - - pattern: list_to_atom($USER_INPUT) - - pattern: binary_to_atom($USER_INPUT, utf8) - where: + patterns: + - pattern-either: + - pattern: list_to_atom($USER_INPUT) + - pattern: binary_to_atom($USER_INPUT, utf8) - metavariable-pattern: metavariable: $USER_INPUT pattern: $VAR diff --git a/socket_basics/rules/go.yml b/socket_basics/rules/go.yml index 34d4b8a..cb46f98 100644 --- a/socket_basics/rules/go.yml +++ b/socket_basics/rules/go.yml @@ -2,16 +2,16 @@ rules: # === Gosec G101: Hardcoded credentials === - id: go-hardcoded-credentials message: "Potential hardcoded credentials detected" - severity: ERROR + severity: HIGH languages: [go] - pattern-either: - - pattern: | - const $VAR = "..." - - pattern: | - var $VAR = "..." - - pattern: | - $VAR := "..." - where: + patterns: + - pattern-either: + - pattern: | + const $VAR = "..." + - pattern: | + var $VAR = "..." + - pattern: | + $VAR := "..." - metavariable-regex: metavariable: $VAR regex: (?i).*(password|passwd|pwd|secret|token|key|api_key|auth).* @@ -24,7 +24,7 @@ rules: # === Gosec G102: Bind to all interfaces === - id: go-bind-all-interfaces message: "Binding to all network interfaces. Consider binding to localhost" - severity: WARNING + severity: LOW languages: [go] pattern-either: - pattern: net.Listen("tcp", "0.0.0.0:$PORT") @@ -39,7 +39,7 @@ rules: # === Gosec G103: Unsafe block usage === - id: go-unsafe-usage message: "Use of unsafe package detected" - severity: WARNING + severity: LOW languages: [go] pattern-either: - pattern: unsafe.Pointer($EXPR) @@ -54,7 +54,7 @@ rules: # === Gosec G104: Errors not checked === - id: go-error-not-checked message: "Error return value not checked" - severity: WARNING + severity: LOW languages: [go] patterns: - pattern-either: @@ -71,7 +71,6 @@ rules: if $VAR, $ERR := $FUNC(...); $ERR != nil { ... } - where: # Common functions that return errors - metavariable-regex: metavariable: $FUNC @@ -85,7 +84,7 @@ rules: # === Gosec G106: SSH InsecureIgnoreHostKey === - id: go-ssh-insecure-ignore-host-key message: "Use of ssh.InsecureIgnoreHostKey detected" - severity: ERROR + severity: HIGH languages: [go] pattern: ssh.InsecureIgnoreHostKey() metadata: @@ -96,14 +95,14 @@ rules: # === Gosec G107: URL taint input === - id: go-url-taint-input message: "URL provided as taint input to HTTP request" - severity: WARNING + severity: LOW languages: [go] - pattern-either: - - pattern: http.Get($URL) - - pattern: http.Post($URL, ...) - - pattern: http.Head($URL) - - pattern: http.PostForm($URL, ...) - where: + patterns: + - pattern-either: + - pattern: http.Get($URL) + - pattern: http.Post($URL, ...) + - pattern: http.Head($URL) + - pattern: http.PostForm($URL, ...) - metavariable-pattern: metavariable: $URL pattern: $VAR @@ -115,7 +114,7 @@ rules: # === Gosec G108: Profiling endpoint exposed === - id: go-profiling-endpoint-exposed message: "Profiling endpoint automatically exposed on /debug/pprof" - severity: WARNING + severity: MEDIUM languages: [go] pattern: | import _ "net/http/pprof" @@ -127,7 +126,7 @@ rules: # === Gosec G109: Integer overflow === - id: go-integer-overflow-strconv message: "Potential integer overflow from strconv.Atoi result" - severity: WARNING + severity: MEDIUM languages: [go] pattern-either: - pattern: int16(strconv.Atoi($STR)) @@ -140,7 +139,7 @@ rules: # === Gosec G110: Decompression bomb === - id: go-decompression-bomb message: "Potential DoS vulnerability via decompression bomb" - severity: WARNING + severity: MEDIUM languages: [go] pattern-either: - pattern: gzip.NewReader($READER) @@ -154,7 +153,7 @@ rules: # === Gosec G201: SQL query format string === - id: go-sql-format-string message: "SQL query construction using format string" - severity: ERROR + severity: CRITICAL languages: [go] pattern-either: - pattern: $DB.Query(fmt.Sprintf($QUERY, ...)) @@ -168,7 +167,7 @@ rules: # === Gosec G202: SQL query string concatenation === - id: go-sql-string-concat message: "SQL query construction using string concatenation" - severity: ERROR + severity: CRITICAL languages: [go] pattern-either: - pattern: $DB.Query($QUERY + $VAR) @@ -182,7 +181,7 @@ rules: # === Gosec G203: HTML template without escaping === - id: go-html-template-no-escape message: "Use of unescaped data in HTML templates" - severity: WARNING + severity: MEDIUM languages: [go] pattern-either: - pattern: template.HTML($DATA) @@ -197,12 +196,12 @@ rules: # === Gosec G204: Command execution === - id: go-command-execution message: "Audit use of command execution" - severity: ERROR + severity: CRITICAL languages: [go] - pattern-either: - - pattern: exec.Command($CMD, ...) - - pattern: exec.CommandContext($CTX, $CMD, ...) - where: + patterns: + - pattern-either: + - pattern: exec.Command($CMD, ...) + - pattern: exec.CommandContext($CTX, $CMD, ...) - metavariable-pattern: metavariable: $CMD pattern: $VAR @@ -214,22 +213,13 @@ rules: # === Gosec G301: Poor file permissions (mkdir) === - id: go-poor-mkdir-permissions message: "Poor file permissions used when creating a directory" - severity: WARNING + severity: MEDIUM languages: [go] pattern-either: - - pattern: os.Mkdir($PATH, $PERM) - - pattern: os.MkdirAll($PATH, $PERM) - where: - - metavariable-comparison: - metavariable: $PERM - comparison: | - import re - # Check for overly permissive permissions - perm_str = str($PERM) - if re.match(r'0o?7[7-9][7-9]', perm_str) or perm_str in ['0777', '511']: - True - else: - False + - pattern: os.Mkdir($PATH, 0777) + - pattern: os.MkdirAll($PATH, 0777) + - pattern: os.Mkdir($PATH, 0o777) + - pattern: os.MkdirAll($PATH, 0o777) metadata: category: security gosec_equivalent: G301 @@ -237,20 +227,12 @@ rules: # === Gosec G302: Poor file permissions (chmod) === - id: go-poor-chmod-permissions - message: "Poor file permissions used with chmod" - severity: WARNING + message: "Poor file permissions used in chmod" + severity: MEDIUM languages: [go] - pattern: os.Chmod($PATH, $PERM) - where: - - metavariable-comparison: - metavariable: $PERM - comparison: | - import re - perm_str = str($PERM) - if re.match(r'0o?7[7-9][7-9]', perm_str) or perm_str in ['0777', '511']: - True - else: - False + pattern-either: + - pattern: os.Chmod($PATH, 0777) + - pattern: os.Chmod($PATH, 0o777) metadata: category: security gosec_equivalent: G302 @@ -259,7 +241,7 @@ rules: # === Gosec G303: Predictable temp file === - id: go-predictable-temp-file message: "Creating tempfile using a predictable path" - severity: WARNING + severity: LOW languages: [go] pattern-either: - pattern: ioutil.TempFile("/tmp", ...) @@ -273,14 +255,14 @@ rules: # === Gosec G304: File path traversal === - id: go-file-path-traversal message: "File path provided as taint input" - severity: ERROR + severity: CRITICAL languages: [go] - pattern-either: - - pattern: os.Open($PATH) - - pattern: ioutil.ReadFile($PATH) - - pattern: os.ReadFile($PATH) - - pattern: os.OpenFile($PATH, ...) - where: + patterns: + - pattern-either: + - pattern: os.Open($PATH) + - pattern: ioutil.ReadFile($PATH) + - pattern: os.ReadFile($PATH) + - pattern: os.OpenFile($PATH, ...) - metavariable-pattern: metavariable: $PATH pattern: $VAR @@ -292,7 +274,7 @@ rules: # === Gosec G305: Zip archive traversal === - id: go-zip-traversal message: "File path traversal when extracting zip archive" - severity: ERROR + severity: CRITICAL languages: [go] pattern: | for _, $FILE := range $READER.File { @@ -316,7 +298,7 @@ rules: # === Gosec G401: Weak cryptography (MD5/SHA1) === - id: go-weak-crypto-hash message: "Detect the usage of MD5 or SHA1" - severity: WARNING + severity: MEDIUM languages: [go] pattern-either: - pattern: md5.New() @@ -333,7 +315,7 @@ rules: # === Gosec G402: Bad TLS connection === - id: go-bad-tls-connection message: "TLS connection with InsecureSkipVerify set to true" - severity: ERROR + severity: HIGH languages: [go] pattern-either: - pattern: | @@ -356,13 +338,12 @@ rules: # === Gosec G403: Weak RSA key === - id: go-weak-rsa-key message: "RSA key length should be at least 2048 bits" - severity: WARNING + severity: MEDIUM languages: [go] - pattern: rsa.GenerateKey($RAND, $BITS) - where: - - metavariable-comparison: - metavariable: $BITS - comparison: int($BITS) < 2048 + pattern-either: + - pattern: rsa.GenerateKey($RAND, 1024) + - pattern: rsa.GenerateKey($RAND, 512) + - pattern: rsa.GenerateKey($RAND, 256) metadata: category: security gosec_equivalent: G403 @@ -371,7 +352,7 @@ rules: # === Gosec G404: Weak random === - id: go-weak-random message: "Insecure random number source (rand)" - severity: WARNING + severity: MEDIUM languages: [go] pattern-either: - pattern: rand.Int() @@ -387,7 +368,7 @@ rules: # === Gosec G501: Import of MD5 === - id: go-import-md5 message: "Blocklisted import: crypto/md5" - severity: WARNING + severity: MEDIUM languages: [go] pattern: | import "crypto/md5" @@ -399,7 +380,7 @@ rules: # === Gosec G502: Import of DES === - id: go-import-des message: "Blocklisted import: crypto/des" - severity: ERROR + severity: HIGH languages: [go] pattern: | import "crypto/des" @@ -411,7 +392,7 @@ rules: # === Gosec G503: Import of RC4 === - id: go-import-rc4 message: "Blocklisted import: crypto/rc4" - severity: ERROR + severity: HIGH languages: [go] pattern: | import "crypto/rc4" @@ -423,7 +404,7 @@ rules: # === Gosec G504: Import of CGI === - id: go-import-cgi message: "Blocklisted import: net/http/cgi" - severity: WARNING + severity: MEDIUM languages: [go] pattern: | import "net/http/cgi" @@ -435,7 +416,7 @@ rules: # === Gosec G505: Import of SHA1 === - id: go-import-sha1 message: "Blocklisted import: crypto/sha1" - severity: WARNING + severity: MEDIUM languages: [go] pattern: | import "crypto/sha1" @@ -447,7 +428,7 @@ rules: # === Additional Go security patterns === - id: go-empty-password message: "Empty password detected" - severity: ERROR + severity: HIGH languages: [go] pattern-either: - pattern: | @@ -463,7 +444,7 @@ rules: # === SQL injection via direct concatenation === - id: go-sql-direct-concat message: "SQL injection via direct string concatenation" - severity: ERROR + severity: CRITICAL languages: [go] pattern-either: - pattern: | @@ -477,12 +458,12 @@ rules: cwe: CWE-89 # === Path traversal via filepath.Join === - - id: go-path-traversal-join + - id: go-path-traversal-filepath-join message: "Potential path traversal via filepath.Join with user input" - severity: WARNING + severity: LOW languages: [go] - pattern: filepath.Join($BASE, $USER_INPUT) - where: + patterns: + - pattern: filepath.Join($BASE, $USER_INPUT) - metavariable-pattern: metavariable: $USER_INPUT pattern: $VAR diff --git a/socket_basics/rules/java.yml b/socket_basics/rules/java.yml index f631ece..d1f2c17 100644 --- a/socket_basics/rules/java.yml +++ b/socket_basics/rules/java.yml @@ -16,19 +16,93 @@ rules: cwe: CWE-94 confidence: medium - # SQL injection + # SQL injection - using taint mode for accurate detection - id: java-sql-injection - message: "SQL injection vulnerability detected" + message: "SQL injection vulnerability detected. User-controlled data flows into SQL execution without proper sanitization. Use PreparedStatement with parameter binding to prevent SQL injection." severity: CRITICAL languages: [java] - pattern-either: - - pattern: $STMT.executeQuery($QUERY + $USER_INPUT) - - pattern: $STMT.execute($QUERY + $USER_INPUT) - - pattern: $STMT.executeUpdate($QUERY + $USER_INPUT) - - pattern: String.format($SQL, $USER_INPUT) + mode: taint + pattern-sources: + # Servlet request sources + - pattern: $REQ.getParameter(...) + - pattern: $REQ.getParameterValues(...) + - pattern: $REQ.getHeader(...) + - pattern: $REQ.getQueryString() + - pattern: $REQ.getRequestURI() + - pattern: $REQ.getCookies() + - pattern: $REQ.getInputStream() + - pattern: $REQ.getReader() + # User object getters that typically return user input + - pattern: $OBJ.getUsername() + - pattern: $OBJ.getName() + - pattern: $OBJ.getEmail() + - pattern: $OBJ.getPassword() + - pattern: $OBJ.getValue() + - pattern: $OBJ.getData() + - pattern: $OBJ.getInput() + - pattern: $OBJ.getContent() + - pattern: $OBJ.getText() + pattern-propagators: + # StringBuilder/StringBuffer propagation + - pattern: $B.append(...) + from: $B + to: $B + - pattern: $B.append($X) + from: $X + to: $B + - pattern: (StringBuilder $B).toString() + from: $B + to: (StringBuilder $B).toString() + - pattern: (StringBuffer $B).toString() + from: $B + to: (StringBuffer $B).toString() + # String.format propagation + - pattern: String.format($FMT, ..., $X, ...) + from: $X + to: String.format + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + - pattern: (String $A).concat($B) + from: $B + to: $A + pattern-sinks: + # JDBC statement execution + - pattern: $STMT.executeQuery(...) + - pattern: $STMT.execute(...) + - pattern: $STMT.executeUpdate(...) + - pattern: $STMT.executeLargeUpdate(...) + # JPA/Hibernate query creation + - pattern: $EM.createQuery(...) + - pattern: $EM.createNativeQuery(...) + - pattern: $SESSION.createQuery(...) + - pattern: $SESSION.createSQLQuery(...) + # JDBC template methods + - pattern: $TEMPLATE.query(...) + - pattern: $TEMPLATE.queryForObject(...) + - pattern: $TEMPLATE.queryForList(...) + - pattern: $TEMPLATE.execute(...) + - pattern: $TEMPLATE.update(...) + pattern-sanitizers: + # PreparedStatement parameter binding + - pattern: $STMT.setString(...) + by-side-effect: true + - pattern: $STMT.setInt(...) + by-side-effect: true + - pattern: $STMT.setObject(...) + by-side-effect: true + # JPA parameter binding + - pattern: $QUERY.setParameter(...) + by-side-effect: true + # Spring named parameter binding + - pattern: $SOURCE.addValue(...) + by-side-effect: true metadata: category: security cwe: CWE-89 + owasp: + - A03:2021 - Injection confidence: high # Deserialization vulnerabilities @@ -46,15 +120,56 @@ rules: cwe: CWE-502 confidence: high - # Command injection + # Command injection - using taint mode for accurate detection - id: java-command-injection - message: "Command injection vulnerability detected" + message: "Command injection vulnerability detected. User-controlled data flows into system command execution without proper validation. Avoid command execution with user input; if necessary, use strict allowlisting." severity: CRITICAL languages: [java] - pattern-either: - - pattern: Runtime.getRuntime().exec($CMD + $USER_INPUT) - - pattern: ProcessBuilder($CMD + $USER_INPUT) - - pattern: new ProcessBuilder($CMD, $USER_INPUT) + mode: taint + pattern-sources: + # Servlet request sources + - pattern: $REQ.getParameter(...) + - pattern: $REQ.getParameterValues(...) + - pattern: $REQ.getHeader(...) + - pattern: $REQ.getQueryString() + - pattern: $REQ.getRequestURI() + # User object getters + - pattern: $OBJ.getCommand() + - pattern: $OBJ.getFilename() + - pattern: $OBJ.getName() + - pattern: $OBJ.getValue() + - pattern: $OBJ.getData() + - pattern: $OBJ.getInput() + pattern-propagators: + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + - pattern: (String $A).concat($B) + from: $B + to: $A + # StringBuilder/StringBuffer + - pattern: $B.append($X) + from: $X + to: $B + # String.format + - pattern: String.format($FMT, ..., $X, ...) + from: $X + to: String.format + # Array creation with tainted elements + - pattern: new String[] {..., $X, ...} + from: $X + to: new String[] + pattern-sinks: + # Runtime exec + - pattern: Runtime.getRuntime().exec(...) + - pattern: $RUNTIME.exec(...) + # ProcessBuilder + - pattern: new ProcessBuilder(...) + - pattern: $BUILDER.command(...) + - pattern: ProcessBuilder.start() + # Legacy Process API + - pattern: Process.start(...) metadata: category: security cwe: CWE-78 @@ -81,14 +196,14 @@ rules: message: "Hardcoded credentials detected" severity: HIGH languages: [java] - pattern-either: - - pattern: | - private static final String $VAR = "..."; - - pattern: | - public static final String $VAR = "..."; - - pattern: | - String $VAR = "..."; - where: + patterns: + - pattern-either: + - pattern: | + private static final String $VAR = "..."; + - pattern: | + public static final String $VAR = "..."; + - pattern: | + String $VAR = "..."; - metavariable-regex: metavariable: $VAR regex: (?i).*(password|passwd|pwd|secret|token|key|api_key).* @@ -164,21 +279,77 @@ rules: cwe: CWE-611 confidence: medium - # Path traversal + # Path traversal - using taint mode for accurate detection - id: java-path-traversal - message: "Path traversal vulnerability detected" + message: "Path traversal vulnerability detected. User-controlled data flows into file operations without proper validation. Use Path.normalize() and validate the result is within allowed directory." severity: HIGH languages: [java] - pattern-either: - - pattern: new File($PATH + $USER_INPUT) - - pattern: new FileInputStream($PATH + $USER_INPUT) - - pattern: new FileOutputStream($PATH + $USER_INPUT) - - pattern: Files.readAllBytes(Paths.get($PATH + $USER_INPUT)) - - pattern: Paths.get($PATH + $USER_INPUT) + mode: taint + pattern-sources: + # Servlet request sources + - pattern: $REQ.getParameter(...) + - pattern: $REQ.getParameterValues(...) + - pattern: $REQ.getHeader(...) + - pattern: $REQ.getQueryString() + - pattern: $REQ.getRequestURI() + - pattern: $REQ.getPathInfo() + # User object getters that typically return user input + - pattern: $OBJ.getFilename() + - pattern: $OBJ.getName() + - pattern: $OBJ.getPath() + - pattern: $OBJ.getValue() + - pattern: $OBJ.getData() + pattern-propagators: + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + - pattern: (String $A).concat($B) + from: $B + to: $A + # Path operations that propagate taint + - pattern: Paths.get(..., $X, ...) + from: $X + to: Paths.get + - pattern: Path.resolve($X) + from: $X + to: Path.resolve + # File path operations + - pattern: new File($X) + from: $X + to: new File + - pattern: new File($DIR, $X) + from: $X + to: new File + pattern-sinks: + # File operations + - pattern: new File(...) + - pattern: new FileInputStream(...) + - pattern: new FileOutputStream(...) + - pattern: new FileReader(...) + - pattern: new FileWriter(...) + - pattern: new RandomAccessFile(...) + - pattern: Files.readAllBytes(...) + - pattern: Files.readAllLines(...) + - pattern: Files.write(...) + - pattern: Files.copy(...) + - pattern: Files.move(...) + - pattern: Files.delete(...) + - pattern: Files.deleteIfExists(...) + - pattern: Paths.get(...) + # Legacy IO operations + - pattern: $FILE.createNewFile(...) + - pattern: $FILE.delete() + - pattern: $FILE.renameTo(...) + pattern-sanitizers: + # Path validation + - pattern: $PATH.normalize() + - pattern: $PATH.toRealPath(...) + - pattern: FilenameUtils.normalize(...) metadata: category: security cwe: CWE-22 - confidence: medium + confidence: high # SSL/TLS bypass - id: java-ssl-bypass @@ -259,13 +430,12 @@ rules: message: "Weak key generation detected" severity: MEDIUM languages: [java] - pattern-either: - - pattern: KeyPairGenerator.getInstance("RSA").initialize($SIZE) - - pattern: KeyGenerator.getInstance(...).init($SIZE) - where: - - metavariable-comparison: - metavariable: $SIZE - comparison: int($SIZE) < 2048 + patterns: + - pattern-either: + - pattern: KeyPairGenerator.getInstance("RSA").initialize(512) + - pattern: KeyPairGenerator.getInstance("RSA").initialize(1024) + - pattern: KeyGenerator.getInstance(...).init(512) + - pattern: KeyGenerator.getInstance(...).init(1024) metadata: category: security cwe: CWE-310 diff --git a/socket_basics/rules/javascript_typescript.yml b/socket_basics/rules/javascript_typescript.yml index de01adf..87c5c16 100644 --- a/socket_basics/rules/javascript_typescript.yml +++ b/socket_basics/rules/javascript_typescript.yml @@ -71,54 +71,55 @@ rules: confidence: medium subcategory: access-control - # Path traversal + # Path traversal - using taint mode for accurate detection - id: js-path-traversal - message: "Path traversal vulnerability - user input used in file operations" + message: "Path traversal vulnerability detected. User-controlled data flows into file operations without proper validation. Use path.resolve() and validate that result is within allowed directory." severity: HIGH languages: [javascript, typescript] - pattern-either: - # File system operations with concatenated paths - - pattern: fs.readFile($PATH + $USER_INPUT, ...) - - pattern: fs.readFileSync($PATH + $USER_INPUT) - - pattern: fs.writeFile($PATH + $USER_INPUT, ...) - - pattern: fs.writeFileSync($PATH + $USER_INPUT, ...) - - pattern: fs.createReadStream($PATH + $USER_INPUT) - - pattern: fs.createWriteStream($PATH + $USER_INPUT) - - pattern: fs.readFile(`${$PATH}${$USER_INPUT}`, ...) - - pattern: fs.readFileSync(`${$PATH}${$USER_INPUT}`) - - pattern: fs.writeFile(`${$PATH}${$USER_INPUT}`, ...) - - pattern: fs.writeFileSync(`${$PATH}${$USER_INPUT}`) - # User input directly in file operations (common with req.query/params/body) - - pattern: fs.readFile($REQ.query.$PARAM, ...) - - pattern: fs.readFileSync($REQ.query.$PARAM) - - pattern: fs.writeFile($REQ.query.$PARAM, ...) - - pattern: fs.writeFileSync($REQ.query.$PARAM) - - pattern: fs.readFile($REQ.params.$PARAM, ...) - - pattern: fs.readFileSync($REQ.params.$PARAM) - - pattern: fs.readFile($REQ.body.$PARAM, ...) - - pattern: fs.readFileSync($REQ.body.$PARAM) - - pattern: fs.createReadStream($REQ.query.$PARAM) - - pattern: fs.createReadStream($REQ.params.$PARAM) - - pattern: fs.createWriteStream($REQ.query.$PARAM) - - pattern: fs.createWriteStream($REQ.params.$PARAM) - # Path module with user input - - pattern: path.join($BASE, $REQ.query.$PARAM) - - pattern: path.join($BASE, $REQ.params.$PARAM) - - pattern: path.join($BASE, $REQ.body.$PARAM) - - pattern: path.resolve($BASE, $REQ.query.$PARAM) - - pattern: path.resolve($BASE, $REQ.params.$PARAM) - - pattern: path.resolve($BASE, $REQ.body.$PARAM) - # Dynamic require/import with request parameters (not static strings) - - pattern: require($REQ.query.$PARAM) - - pattern: require($REQ.params.$PARAM) - - pattern: require($REQ.body.$PARAM) - - pattern: import($REQ.query.$PARAM) - - pattern: import($REQ.params.$PARAM) - - pattern: import($REQ.body.$PARAM) - # Template literals with user input - - pattern: fs.readFile(`...${$REQ.query.$PARAM}...`, ...) - - pattern: fs.readFile(`...${$REQ.params.$PARAM}...`, ...) - - pattern: fs.readFile(`...${$REQ.body.$PARAM}...`, ...) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: req.cookies + - pattern: ctx.query + - pattern: ctx.params + - pattern: ctx.request.body + - pattern: request.query + - pattern: request.params + - pattern: request.body + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + # Path operations that propagate taint + - pattern: path.join(...) + from: $A + to: $A + - pattern: path.resolve(...) + from: $A + to: $A + pattern-sinks: + # File system operations + - pattern: fs.readFile(...) + - pattern: fs.readFileSync(...) + - pattern: fs.writeFile(...) + - pattern: fs.writeFileSync(...) + - pattern: fs.createReadStream(...) + - pattern: fs.createWriteStream(...) + - pattern: fs.appendFile(...) + - pattern: fs.appendFileSync(...) + - pattern: fs.unlink(...) + - pattern: fs.unlinkSync(...) + # Dynamic imports + - pattern: require(...) + - pattern: import(...) + pattern-sanitizers: + # Validation that checks path is within allowed directory + - pattern: path.normalize(...).startsWith(...) + - pattern: $PATH.indexOf("..") === -1 metadata: category: security owasp: "A01:2021" @@ -126,24 +127,48 @@ rules: confidence: high subcategory: access-control - # Unvalidated redirect + # Unvalidated redirect - using taint mode for accurate detection - id: js-open-redirect - message: "Open redirect vulnerability - user input used in redirect without validation" + message: "Open redirect vulnerability detected. User-controlled data flows into redirect without validation. Validate redirect URLs against allowlist." severity: MEDIUM languages: [javascript, typescript] - pattern-either: - # Server-side redirects with user input - - pattern: res.redirect($REQ.query.$PARAM) - - pattern: res.redirect($REQ.params.$PARAM) - - pattern: res.redirect($REQ.body.$PARAM) - # Client-side redirects with request data (more specific) - - pattern: window.location = $REQ.query.$PARAM - - pattern: window.location.href = $REQ.query.$PARAM - - pattern: document.location = $REQ.query.$PARAM - - pattern: document.location.href = $REQ.query.$PARAM - # URL concatenation with user input - - pattern: res.redirect($BASE + $REQ.query.$PARAM) - - pattern: res.redirect(`${$BASE}${$REQ.query.$PARAM}`) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: ctx.query + - pattern: ctx.params + - pattern: ctx.request.body + - pattern: request.query + - pattern: request.params + - pattern: request.body + # Client-side sources + - pattern: location.search + - pattern: window.location.search + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # Server-side redirects + - pattern: res.redirect(...) + - pattern: res.location(...) + - pattern: ctx.redirect(...) + # Client-side redirects + - pattern: window.location = ... + - pattern: window.location.href = ... + - pattern: document.location = ... + - pattern: document.location.href = ... + - pattern: location.assign(...) + - pattern: location.replace(...) + pattern-sanitizers: + # URL validation + - pattern: $URL.startsWith("http://") + - pattern: $URL.startsWith("https://") + - pattern: new URL(...) metadata: category: security owasp: "A01:2021" @@ -183,7 +208,8 @@ rules: - pattern: crypto.createHash("md5") - pattern: crypto.createHash('md5') - pattern: require('md5') - - pattern: import ... from 'md5' + - pattern: import $X from 'md5' + - pattern: import * as $X from 'md5' metadata: category: security owasp: "A02:2021" @@ -199,7 +225,8 @@ rules: - pattern: crypto.createHash("sha1") - pattern: crypto.createHash('sha1') - pattern: require('sha1') - - pattern: import ... from 'sha1' + - pattern: import $X from 'sha1' + - pattern: import * as $X from 'sha1' metadata: category: security owasp: "A02:2021" @@ -241,10 +268,7 @@ rules: - pattern: var $VAR = "..." - metavariable-regex: metavariable: $VAR - regex: ^(password|passwd|pwd|secret|apiKey|api_key|privateKey|private_key|accessToken|access_token|authToken|auth_token|sessionKey|session_key)$ - - metavariable-comparison: - metavariable: $VAR - comparison: str($VAR).length > 8 + regex: (?i).*(password|passwd|pwd|secret|api[_-]?key|private[_-]?key|access[_-]?token|auth[_-]?token|session[_-]?key).* metadata: category: security owasp: "A02:2021" @@ -355,26 +379,29 @@ rules: message: "Code injection via eval() - can execute arbitrary code" severity: CRITICAL languages: [javascript, typescript] - pattern-either: - # Direct eval usage - - pattern: eval($EXPR) - - pattern: eval($REQ.$PROP) - # Function constructor with user input - - pattern: Function($REQ.$PROP) - - pattern: new Function($REQ.$PROP) - # setTimeout/setInterval with string (not function) - - patterns: - - pattern-either: - - pattern: setTimeout($CODE_STR, ...) - - pattern: setInterval($CODE_STR, ...) - - metavariable-pattern: - metavariable: $CODE_STR - patterns: - - pattern-not: $FUNC - - pattern: "..." - # VM module with user input - - pattern: vm.runInNewContext($REQ.$PROP) - - pattern: vm.runInThisContext($REQ.$PROP) + patterns: + - pattern-either: + # Direct eval usage + - pattern: eval($EXPR) + - pattern: eval($REQ.$PROP) + # Function constructor with user input + - pattern: Function($REQ.$PROP) + - pattern: new Function($REQ.$PROP) + # setTimeout/setInterval with string (not function) + - patterns: + - pattern-either: + - pattern: setTimeout($CODE_STR, ...) + - pattern: setInterval($CODE_STR, ...) + - metavariable-pattern: + metavariable: $CODE_STR + patterns: + - pattern-not: $FUNC + - pattern: "..." + # VM module with user input + - pattern: vm.runInNewContext($REQ.$PROP) + - pattern: vm.runInThisContext($REQ.$PROP) + # Exclude hardcoded strings + - pattern-not: eval("...") metadata: category: security owasp: "A03:2021" @@ -382,22 +409,58 @@ rules: confidence: high subcategory: injection - # SQL injection + # SQL injection - using taint mode for accurate detection - id: js-sql-injection - message: "SQL injection vulnerability - use parameterized queries" + message: "SQL injection vulnerability detected. User-controlled data flows into SQL query without proper sanitization. Use parameterized queries with placeholders (?, $1, etc.) to prevent SQL injection." severity: CRITICAL languages: [javascript, typescript] - pattern-either: - - pattern: $DB.query("..." + $VAR + "...") - - pattern: $DB.query(`...${$VAR}...`) - - pattern: $DB.execute("..." + $VAR + "...") - - pattern: $DB.execute(`...${$VAR}...`) - - pattern: $DB.raw("..." + $VAR + "...") - - pattern: $DB.raw(`...${$VAR}...`) - - pattern: $CONN.query("..." + $REQ.$PROP + "...") - - pattern: $CONN.query(`...${$REQ.$PROP}...`) - - pattern: mysql.query("..." + $VAR + "...") - - pattern: pg.query("..." + $VAR + "...") + mode: taint + pattern-sources: + # User-controlled input sources (Express/Node.js) + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: req.cookies + - pattern: req.headers + # Koa framework + - pattern: ctx.query + - pattern: ctx.params + - pattern: ctx.request.body + # Fastify framework + - pattern: request.query + - pattern: request.params + - pattern: request.body + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + # Template literals are implicitly tracked + pattern-sinks: + # MySQL/PostgreSQL/SQLite query methods + - pattern: $DB.query(...) + - pattern: $DB.execute(...) + - pattern: $DB.raw(...) + - pattern: $CONN.query(...) + - pattern: $CONN.execute(...) + - pattern: mysql.query(...) + - pattern: mysql2.query(...) + - pattern: pg.query(...) + - pattern: sqlite3.run(...) + - pattern: $DB.exec(...) + # Sequelize raw queries + - pattern: sequelize.query(...) + - pattern: $MODEL.sequelize.query(...) + # Knex raw queries + - pattern: knex.raw(...) + - pattern: $KNEX.raw(...) + pattern-sanitizers: + # Parameterized queries with placeholders + - pattern: $DB.query("...", [...]) + - pattern: $DB.execute("...", [...]) + # ORM methods that use parameters + - pattern: $MODEL.findAll(...) + - pattern: $MODEL.findOne(...) metadata: category: security owasp: "A03:2021" @@ -433,20 +496,45 @@ rules: confidence: high subcategory: injection - # Command injection + # Command injection - using taint mode for accurate detection - id: js-command-injection - message: "Command injection vulnerability - avoid shell execution with user input" + message: "Command injection vulnerability detected. User-controlled data flows into system command without proper sanitization. Use child_process.spawn with array arguments or proper escaping." severity: CRITICAL languages: [javascript, typescript] - pattern-either: - - pattern: child_process.exec($CMD + $VAR) - - pattern: child_process.exec(`${$CMD}${$VAR}`) - - pattern: child_process.exec($REQ.$PROP) - - pattern: cp.exec($CMD + $VAR) - - pattern: require('child_process').exec($CMD + $VAR) - - pattern: execSync($CMD + $VAR) - - pattern: child_process.execSync($CMD + $VAR) - - pattern: "child_process.spawn($CMD, ..., { shell: true })" + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: req.cookies + - pattern: req.headers + - pattern: ctx.query + - pattern: ctx.params + - pattern: ctx.request.body + - pattern: request.query + - pattern: request.params + - pattern: request.body + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # Command execution methods + - pattern: child_process.exec(...) + - pattern: child_process.execSync(...) + - pattern: cp.exec(...) + - pattern: exec(...) + - pattern: execSync(...) + - pattern: child_process.execFile(...) + - pattern: execFile(...) + # Shell option enabled - spawn with shell is dangerous + - pattern: child_process.spawn(...) + - pattern: spawn(...) + pattern-sanitizers: + # Array-based spawn without shell is safe (no shell interpretation) + - pattern: child_process.spawnSync($CMD, [...]) metadata: category: security owasp: "A03:2021" @@ -454,16 +542,38 @@ rules: confidence: high subcategory: injection - # LDAP injection + # LDAP injection - using taint mode for accurate detection - id: js-ldap-injection - message: "LDAP injection vulnerability - sanitize user input in LDAP queries" + message: "LDAP injection vulnerability detected. User-controlled data flows into LDAP query without sanitization. Escape LDAP special characters." severity: HIGH languages: [javascript, typescript] - pattern-either: - - pattern: $CLIENT.search($FILTER + $USER_INPUT, ...) - - pattern: $CLIENT.search(`${$FILTER}${$USER_INPUT}`, ...) - - pattern: $CLIENT.bind($DN + $USER_INPUT, ...) - - pattern: $CLIENT.bind(`${$DN}${$USER_INPUT}`, ...) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: req.cookies + - pattern: ctx.query + - pattern: ctx.params + - pattern: request.query + - pattern: request.params + - pattern: request.body + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # LDAP query methods + - pattern: $CLIENT.search(...) + - pattern: $CLIENT.bind(...) + - pattern: $CLIENT.add(...) + - pattern: $CLIENT.modify(...) + pattern-sanitizers: + # LDAP escaping functions + - pattern: ldap.escapeDN(...) + - pattern: ldap.escapeFilter(...) metadata: category: security owasp: "A03:2021" @@ -471,27 +581,51 @@ rules: confidence: high subcategory: injection - # XSS via innerHTML + # XSS via innerHTML - using taint mode for accurate detection - id: js-xss-innerhtml - message: "XSS vulnerability via innerHTML with user input - use textContent or sanitize" + message: "XSS vulnerability detected. User-controlled data flows into innerHTML/outerHTML/document.write without sanitization. Use textContent for plain text or DOMPurify.sanitize() for HTML." severity: HIGH languages: [javascript, typescript] - pattern-either: - # innerHTML with request data - - pattern: $ELEMENT.innerHTML = $REQ.query.$PARAM - - pattern: $ELEMENT.innerHTML = $REQ.body.$PARAM - - pattern: $ELEMENT.innerHTML = $REQ.params.$PARAM - - pattern: $ELEMENT.outerHTML = $REQ.query.$PARAM - - pattern: $ELEMENT.outerHTML = $REQ.body.$PARAM - # insertAdjacentHTML with request data - - pattern: $ELEMENT.insertAdjacentHTML(..., $REQ.query.$PARAM) - - pattern: $ELEMENT.insertAdjacentHTML(..., $REQ.body.$PARAM) - # document.write with request data - - pattern: document.write($REQ.query.$PARAM) - - pattern: document.writeln($REQ.body.$PARAM) - # Template literals with user input in innerHTML - - pattern: $ELEMENT.innerHTML = `...${$REQ.query.$PARAM}...` - - pattern: $ELEMENT.innerHTML = `...${$REQ.body.$PARAM}...` + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: req.cookies + - pattern: ctx.query + - pattern: ctx.params + - pattern: ctx.request.body + - pattern: request.query + - pattern: request.params + - pattern: request.body + # Client-side sources + - pattern: location.search + - pattern: location.hash + - pattern: window.location.search + - pattern: window.location.hash + - pattern: document.URL + - pattern: document.documentURI + - pattern: document.referrer + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # DOM manipulation methods + - pattern: $ELEMENT.innerHTML = ... + - pattern: $ELEMENT.outerHTML = ... + - pattern: $ELEMENT.insertAdjacentHTML(...) + - pattern: document.write(...) + - pattern: document.writeln(...) + pattern-sanitizers: + # Sanitization libraries + - pattern: DOMPurify.sanitize(...) + - pattern: sanitizeHtml(...) + # Safe text-only methods + - pattern: $ELEMENT.textContent = ... + - pattern: $ELEMENT.innerText = ... metadata: category: security owasp: "A03:2021" @@ -499,25 +633,53 @@ rules: confidence: high subcategory: injection - # DOM-based XSS + # DOM-based XSS - using taint mode for accurate detection - id: js-dom-xss - message: "DOM XSS vulnerability - validate and sanitize user input before using in DOM" + message: "DOM XSS vulnerability detected. User-controlled data flows into dangerous DOM property without validation. Validate and sanitize user input before using in DOM." severity: HIGH languages: [javascript, typescript] - pattern-either: - # Setting dangerous attributes with request data - - pattern: $ELEMENT.setAttribute("href", $REQ.query.$PARAM) - - pattern: $ELEMENT.setAttribute("src", $REQ.query.$PARAM) - - pattern: $ELEMENT.setAttribute("action", $REQ.body.$PARAM) - - pattern: $ELEMENT.setAttribute("formaction", $REQ.body.$PARAM) - - pattern: $ELEMENT.src = $REQ.query.$PARAM - - pattern: $ELEMENT.href = $REQ.query.$PARAM - # Location manipulation with user input - - pattern: location = $REQ.query.$PARAM - - pattern: location.href = $REQ.query.$PARAM - - pattern: location.assign($REQ.query.$PARAM) - - pattern: window.location = $REQ.query.$PARAM - - pattern: window.location.href = $REQ.query.$PARAM + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: ctx.query + - pattern: ctx.params + - pattern: request.query + - pattern: request.params + - pattern: request.body + # Client-side sources + - pattern: location.search + - pattern: location.hash + - pattern: window.location.search + - pattern: window.location.hash + - pattern: document.URL + - pattern: document.referrer + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # Dangerous DOM properties + - pattern: $ELEMENT.setAttribute("href", ...) + - pattern: $ELEMENT.setAttribute("src", ...) + - pattern: $ELEMENT.setAttribute("action", ...) + - pattern: $ELEMENT.setAttribute("formaction", ...) + - pattern: $ELEMENT.src = ... + - pattern: $ELEMENT.href = ... + # Location manipulation + - pattern: location = ... + - pattern: location.href = ... + - pattern: location.assign(...) + - pattern: window.location = ... + - pattern: window.location.href = ... + pattern-sanitizers: + # Sanitization functions + - pattern: encodeURIComponent(...) + - pattern: encodeURI(...) + - pattern: DOMPurify.sanitize(...) metadata: category: security owasp: "A03:2021" @@ -547,24 +709,37 @@ rules: confidence: medium subcategory: injection - # Server-side template injection + # Server-side template injection - using taint mode for accurate detection - id: js-template-injection - message: "Template injection vulnerability - sanitize user input in templates" + message: "Template injection vulnerability detected. User-controlled data flows into template compilation/rendering. Use pre-compiled templates or sanitize input." severity: HIGH languages: [javascript, typescript] - pattern-either: - # Eval in template context - - pattern: eval($TEMPLATE_STR) - # Lodash template with user input - - pattern: _.template($REQ.query.$PARAM) - - pattern: _.template($REQ.body.$PARAM) - - pattern: lodash.template($REQ.query.$PARAM) - # Handlebars compile with user input - - pattern: Handlebars.compile($REQ.body.$PARAM) - - pattern: Handlebars.compile($REQ.query.$PARAM) - # Template engines rendering user-controlled template strings - - pattern: $ENGINE.renderString($REQ.body.$PARAM, ...) - - pattern: pug.compile($REQ.body.$PARAM) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: req.cookies + - pattern: ctx.query + - pattern: ctx.params + - pattern: request.query + - pattern: request.params + - pattern: request.body + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # Template compilation and rendering + - pattern: eval(...) + - pattern: _.template(...) + - pattern: lodash.template(...) + - pattern: Handlebars.compile(...) + - pattern: pug.compile(...) + - pattern: $ENGINE.renderString(...) + - pattern: $ENGINE.compile(...) metadata: category: security owasp: "A03:2021" @@ -878,7 +1053,7 @@ rules: - pattern: jwt.sign(..., $SECRET, ...) - metavariable-regex: metavariable: $SECRET - regex: ^["'](secret|test|dev|password|123)["']$ + regex: (?i)^["']?(secret|test|dev|password|123|abc|qwerty|admin|changeme|default)["']?$ metadata: category: security owasp: "A07:2021" @@ -938,7 +1113,7 @@ rules: - id: js-missing-sri message: "External resource loaded without Subresource Integrity (SRI) check" severity: MEDIUM - languages: [javascript, typescript] + languages: [html] patterns: - pattern-either: - pattern: | @@ -1041,20 +1216,47 @@ rules: # A10:2021 - Server-Side Request Forgery (SSRF) # ===================================================================== - # SSRF via user-controlled URL + # SSRF via user-controlled URL - using taint mode for accurate detection - id: js-ssrf-vulnerability - message: "SSRF vulnerability - validate and whitelist URLs before making requests" + message: "SSRF vulnerability detected. User-controlled data flows into HTTP request URL. Validate and whitelist URLs before making requests." severity: HIGH languages: [javascript, typescript] - pattern-either: - - pattern: fetch($REQ.query.$PARAM) - - pattern: fetch($REQ.body.$PARAM) - - pattern: axios.get($REQ.query.$PARAM) - - pattern: axios.post($REQ.body.$PARAM, ...) - - pattern: request($REQ.query.$PARAM) - - pattern: http.get($REQ.query.$PARAM) - - pattern: https.get($REQ.query.$PARAM) - - pattern: got($REQ.body.$PARAM) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: req.query + - pattern: req.params + - pattern: req.body + - pattern: req.headers + - pattern: ctx.query + - pattern: ctx.params + - pattern: request.query + - pattern: request.params + - pattern: request.body + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # HTTP client methods + - pattern: fetch(...) + - pattern: axios.get(...) + - pattern: axios.post(...) + - pattern: axios.request(...) + - pattern: request(...) + - pattern: http.get(...) + - pattern: http.request(...) + - pattern: https.get(...) + - pattern: https.request(...) + - pattern: got(...) + - pattern: superagent.get(...) + - pattern: needle.get(...) + pattern-sanitizers: + # URL validation and whitelisting + - pattern: new URL(...) + - pattern: $URL.startsWith("http://localhost") + - pattern: $URL.startsWith("https://trusted-domain.com") metadata: category: security owasp: "A10:2021" @@ -1118,12 +1320,10 @@ rules: await $ASYNC_CALL - pattern-not: | $PROMISE.then(...).catch(...) - - pattern-not: | + - pattern-not-inside: | try { ... - await $ASYNC_CALL - ... - } catch (...) { + } catch ($E) { ... } metadata: @@ -1182,7 +1382,9 @@ rules: message: "React dangerouslySetInnerHTML can introduce XSS vulnerabilities" severity: HIGH languages: [javascript, typescript] - pattern: "dangerouslySetInnerHTML={{ __html: $HTML }}" + patterns: + - pattern: <$EL dangerouslySetInnerHTML={...} /> + - pattern-not: <$EL dangerouslySetInnerHTML={"..."} /> metadata: category: security framework: react @@ -1271,7 +1473,7 @@ rules: export async function getServerSideProps(...) { try { ... - } catch (...) { + } catch ($E) { ... } } @@ -1363,9 +1565,9 @@ rules: - pattern: | $APP.post($PATH, $UPLOAD.single(...), ...) - pattern-not-inside: | - ... - if ($FILE.mimetype ...) { ... } - ... + if ($FILE.mimetype === "...") { ... } + - pattern-not-inside: | + if ($FILE.size > ...) { ... } metadata: category: security cwe: CWE-434 diff --git a/socket_basics/rules/kotlin.yml b/socket_basics/rules/kotlin.yml index 4f3468a..72d2749 100644 --- a/socket_basics/rules/kotlin.yml +++ b/socket_basics/rules/kotlin.yml @@ -226,12 +226,12 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [kotlin] - pattern-either: - - pattern: println($USER_INPUT) - - pattern: print($USER_INPUT) - - pattern: Log.d($TAG, $USER_INPUT) - - pattern: System.out.println($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: println($USER_INPUT) + - pattern: print($USER_INPUT) + - pattern: Log.d($TAG, $USER_INPUT) + - pattern: System.out.println($USER_INPUT) - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* @@ -245,10 +245,15 @@ rules: message: "Hardcoded IP address detected" severity: LOW languages: [kotlin] - pattern: $IP_ADDRESS - metavariable-regex: - metavariable: $IP_ADDRESS - regex: "(192\\.168\\.\\d{1,3}\\.\\d{1,3})|(10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})|(172\\.16\\.\\d{1,3}\\.\\d{1,3})|127\\.0\\.0\\.1|localhost" + pattern-either: + - pattern: val $VAR = "192.168.$X.$Y" + - pattern: val $VAR = "10.$X.$Y.$Z" + - pattern: val $VAR = "127.0.0.1" + - pattern: val $VAR = "localhost" + - pattern: var $VAR = "192.168.$X.$Y" + - pattern: var $VAR = "10.$X.$Y.$Z" + - pattern: var $VAR = "127.0.0.1" + - pattern: var $VAR = "localhost" metadata: category: security cwe: CWE-798 diff --git a/socket_basics/rules/objective-c.yml b/socket_basics/rules/objective-c.yml index 5881527..cbd769c 100644 --- a/socket_basics/rules/objective-c.yml +++ b/socket_basics/rules/objective-c.yml @@ -243,11 +243,11 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [objective-c] - pattern-either: - - pattern: NSLog(@"%@", $USER_INPUT) - - pattern: printf("%s", [$USER_INPUT UTF8String]) - - pattern: os_log(OS_LOG_DEFAULT, "%@", $USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: NSLog(@"%@", $USER_INPUT) + - pattern: printf("%s", [$USER_INPUT UTF8String]) + - pattern: os_log(OS_LOG_DEFAULT, "%@", $USER_INPUT) - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* @@ -319,11 +319,11 @@ rules: message: "Insecure data storage detected" severity: HIGH languages: [objective-c] - pattern-either: - - pattern: NSUserDefaults.standardUserDefaults setObject:$SENSITIVE_DATA forKey:$KEY - - pattern: '[NSUserDefaults.standardUserDefaults setObject:$SENSITIVE_DATA forKey:$KEY]' - - pattern: '[fileData writeToFile:$PATH atomically:YES]' - where: + patterns: + - pattern-either: + - pattern: NSUserDefaults.standardUserDefaults setObject:$SENSITIVE_DATA forKey:$KEY + - pattern: '[NSUserDefaults.standardUserDefaults setObject:$SENSITIVE_DATA forKey:$KEY]' + - pattern: '[fileData writeToFile:$PATH atomically:YES]' - metavariable-regex: metavariable: $SENSITIVE_DATA regex: (?i).*(password|token|secret|key|credential|credit_card|ssn).* diff --git a/socket_basics/rules/php.yml b/socket_basics/rules/php.yml index e0e6d5a..7827fcc 100644 --- a/socket_basics/rules/php.yml +++ b/socket_basics/rules/php.yml @@ -3,25 +3,44 @@ rules: # Code injection - id: php-code-injection - message: "Code injection vulnerability detected" + message: "Code injection vulnerability detected - user input flows to code execution functions" + severity: CRITICAL + languages: [php] + mode: taint + pattern-sources: + - pattern: $_GET + - pattern: $_POST + - pattern: $_REQUEST + - pattern: $_COOKIE + - pattern: $_SERVER['REQUEST_URI'] + - pattern: $_SERVER['QUERY_STRING'] + - pattern: file_get_contents('php://input') + pattern-sinks: + - pattern: eval($CODE) + - pattern: assert($CODE) + - pattern: assert($CODE, ...) + - pattern: create_function($ARGS, $CODE) + pattern-sanitizers: + - pattern: preg_quote($STR) + - pattern: addslashes($STR) + metadata: + category: security + cwe: CWE-94 + confidence: high + + # preg_replace with /e modifier (separate rule due to specific vulnerability) + - id: php-preg-replace-e-modifier + message: "Dangerous preg_replace with /e modifier detected" severity: CRITICAL languages: [php] pattern-either: - - pattern: eval($USER_INPUT) - - pattern: assert($USER_INPUT) - - pattern: preg_replace($PATTERN, $USER_INPUT, $SUBJECT) - - pattern: create_function($ARGS, $USER_INPUT) - - pattern: $USER_INPUT($ARGS) - where: - - metavariable-pattern: - metavariable: $USER_INPUT - pattern: $_GET[...] - - metavariable-pattern: - metavariable: $USER_INPUT - pattern: $_POST[...] - - metavariable-pattern: - metavariable: $USER_INPUT - pattern: $_REQUEST[...] + - pattern: preg_replace('/.../e', $REPLACEMENT, $SUBJECT) + - pattern: preg_replace("/.../e", $REPLACEMENT, $SUBJECT) + - pattern: preg_replace($PATTERN, $REPLACEMENT, $SUBJECT) + pattern-inside: | + ... + $PATTERN = '/.../e'; + ... metadata: category: security cwe: CWE-94 @@ -29,17 +48,42 @@ rules: # SQL injection - id: php-sql-injection - message: "SQL injection vulnerability detected" + message: "SQL injection vulnerability detected - user input flows to SQL query without parameterization" severity: CRITICAL languages: [php] - pattern-either: - - pattern: mysql_query($QUERY . $USER_INPUT) - - pattern: mysqli_query($CONN, $QUERY . $USER_INPUT) - - pattern: $PDO->query($QUERY . $USER_INPUT) - - pattern: $PDO->exec($QUERY . $USER_INPUT) - - pattern: '"SELECT * FROM users WHERE id = " . $USER_INPUT' - - pattern: | - "SELECT * FROM users WHERE id = '$USER_INPUT'" + mode: taint + pattern-sources: + - pattern: $_GET + - pattern: $_POST + - pattern: $_REQUEST + - pattern: $_COOKIE + - pattern: $_SERVER['REQUEST_URI'] + - pattern: $_SERVER['QUERY_STRING'] + - pattern: file_get_contents('php://input') + pattern-sinks: + - pattern: mysql_query($QUERY) + - pattern: mysqli_query($CONN, $QUERY) + - pattern: mysqli_query(..., $QUERY) + - pattern: $PDO->query($QUERY) + - pattern: $PDO->exec($QUERY) + - pattern: $MYSQLI->query($QUERY) + - pattern: $MYSQLI->multi_query($QUERY) + - pattern: mysqli_multi_query($CONN, $QUERY) + - pattern: $WPDB->query($QUERY) + - pattern: $DB->query($QUERY) + pattern-sanitizers: + - pattern: $PDO->prepare($QUERY) + - pattern: $MYSQLI->prepare($QUERY) + - pattern: mysqli_prepare($CONN, $QUERY) + - pattern: $WPDB->prepare($QUERY, ...) + - pattern: mysqli_real_escape_string($CONN, $STR) + - pattern: mysqli_real_escape_string(..., $STR) + - pattern: mysql_real_escape_string($STR) + - pattern: addslashes($STR) + - pattern: intval($STR) + - pattern: floatval($STR) + - pattern: (int)$STR + - pattern: (float)$STR metadata: category: security cwe: CWE-89 @@ -47,17 +91,32 @@ rules: # Command injection - id: php-command-injection - message: "Command injection vulnerability detected" + message: "Command injection vulnerability detected - user input flows to system command execution" severity: CRITICAL languages: [php] - pattern-either: - - pattern: system($USER_INPUT) - - pattern: exec($USER_INPUT) - - pattern: shell_exec($USER_INPUT) - - pattern: passthru($USER_INPUT) - - pattern: '`$USER_INPUT`' - - pattern: popen($USER_INPUT, $...ARGS) - - pattern: proc_open($USER_INPUT, $...ARGS) + mode: taint + pattern-sources: + - pattern: $_GET + - pattern: $_POST + - pattern: $_REQUEST + - pattern: $_COOKIE + - pattern: $_SERVER['REQUEST_URI'] + - pattern: $_SERVER['QUERY_STRING'] + - pattern: file_get_contents('php://input') + pattern-sinks: + - pattern: system($CMD) + - pattern: exec($CMD) + - pattern: exec($CMD, ...) + - pattern: shell_exec($CMD) + - pattern: passthru($CMD) + - pattern: passthru($CMD, ...) + - pattern: popen($CMD, ...) + - pattern: proc_open($CMD, ...) + - pattern: '`$CMD`' + - pattern: pcntl_exec($CMD, ...) + pattern-sanitizers: + - pattern: escapeshellarg($STR) + - pattern: escapeshellcmd($STR) metadata: category: security cwe: CWE-78 @@ -68,16 +127,16 @@ rules: message: "Unsafe deserialization detected" severity: CRITICAL languages: [php] - pattern-either: - - pattern: unserialize($USER_INPUT) - - pattern: serialize($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: unserialize($USER_INPUT) + - pattern: serialize($USER_INPUT) - metavariable-pattern: metavariable: $USER_INPUT - pattern: $_GET[...] - - metavariable-pattern: - metavariable: $USER_INPUT - pattern: $_POST[...] + patterns: + - pattern-either: + - pattern: $_GET[...] + - pattern: $_POST[...] metadata: category: security cwe: CWE-502 @@ -119,19 +178,57 @@ rules: # XSS vulnerabilities - id: php-xss - message: "XSS vulnerability detected" + message: "XSS vulnerability detected - user input not sanitized before output" severity: HIGH languages: [php] pattern-either: - - pattern: echo $USER_INPUT; - - pattern: print $USER_INPUT; - - pattern: printf($USER_INPUT, $...ARGS); - - pattern: "'
' . $USER_INPUT . '
'" - - pattern: print_r($USER_INPUT) + # Direct superglobal usage in output + - pattern: echo $_GET[$KEY]; + - pattern: echo $_POST[$KEY]; + - pattern: echo $_REQUEST[$KEY]; + - pattern: echo $_COOKIE[$KEY]; + - pattern: print $_GET[$KEY]; + - pattern: print $_POST[$KEY]; + - pattern: print $_REQUEST[$KEY]; + - pattern: print $_COOKIE[$KEY]; + - pattern: printf($_GET[$KEY], $...ARGS); + - pattern: printf($_POST[$KEY], $...ARGS); + - pattern: printf($_REQUEST[$KEY], $...ARGS); + # Concatenation with superglobals in output + - pattern: echo "..." . $_GET[$KEY] . "..."; + - pattern: echo "..." . $_POST[$KEY] . "..."; + - pattern: echo "..." . $_REQUEST[$KEY] . "..."; + - pattern: echo '...' . $_GET[$KEY] . '...'; + - pattern: echo '...' . $_POST[$KEY] . '...'; + - pattern: echo '...' . $_REQUEST[$KEY] . '...'; + - pattern: print "..." . $_GET[$KEY] . "..."; + - pattern: print "..." . $_POST[$KEY] . "..."; + - pattern: print "..." . $_REQUEST[$KEY] . "..."; + - pattern: print '...' . $_GET[$KEY] . '...'; + - pattern: print '...' . $_POST[$KEY] . '...'; + - pattern: print '...' . $_REQUEST[$KEY] . '...'; + # Assignment to HTML variables (common XSS pattern) + - pattern: $HTML .= "..." . $_GET[$KEY] . "..."; + - pattern: $HTML .= "..." . $_POST[$KEY] . "..."; + - pattern: $HTML .= "..." . $_REQUEST[$KEY] . "..."; + - pattern: $HTML .= '...' . $_GET[$KEY] . '...'; + - pattern: $HTML .= '...' . $_POST[$KEY] . '...'; + - pattern: $HTML .= '...' . $_REQUEST[$KEY] . '...'; + - pattern: $HTML = "..." . $_GET[$KEY] . "..."; + - pattern: $HTML = "..." . $_POST[$KEY] . "..."; + - pattern: $HTML = "..." . $_REQUEST[$KEY] . "..."; + - pattern: $HTML = '...' . $_GET[$KEY] . '...'; + - pattern: $HTML = '...' . $_POST[$KEY] . '...'; + - pattern: $HTML = '...' . $_REQUEST[$KEY] . '...'; + # print_r with superglobals + - pattern: print_r($_GET) + - pattern: print_r($_POST) + - pattern: print_r($_REQUEST) + - pattern: print_r($_COOKIE) metadata: category: security cwe: CWE-79 - confidence: low + confidence: high # Hardcoded secrets - id: php-hardcoded-secrets @@ -152,34 +249,72 @@ rules: # Path traversal - id: php-path-traversal - message: "Path traversal vulnerability detected" + message: "Path traversal vulnerability detected - user input flows to file operations without validation" severity: HIGH languages: [php] - pattern-either: - - pattern: file_get_contents($PATH . $USER_INPUT) - - pattern: fopen($PATH . $USER_INPUT, ...) - - pattern: include($PATH . $USER_INPUT) - - pattern: readfile($PATH . $USER_INPUT) - - pattern: unlink($PATH . $USER_INPUT) + mode: taint + pattern-sources: + - pattern: $_GET + - pattern: $_POST + - pattern: $_REQUEST + - pattern: $_COOKIE + - pattern: $_SERVER['REQUEST_URI'] + - pattern: $_SERVER['QUERY_STRING'] + - pattern: file_get_contents('php://input') + pattern-sinks: + - pattern: file_get_contents($PATH) + - pattern: fopen($PATH, ...) + - pattern: include($PATH) + - pattern: include_once($PATH) + - pattern: require($PATH) + - pattern: require_once($PATH) + - pattern: readfile($PATH) + - pattern: unlink($PATH) + - pattern: file($PATH) + - pattern: file_put_contents($PATH, ...) + - pattern: copy($SRC, $DEST) + - pattern: rename($OLD, $NEW) + - pattern: mkdir($PATH, ...) + - pattern: rmdir($PATH) + - pattern: is_file($PATH) + - pattern: is_dir($PATH) + - pattern: scandir($PATH) + - pattern: glob($PATH) + pattern-sanitizers: + - pattern: basename($PATH) + - pattern: realpath($PATH) metadata: category: security cwe: CWE-22 - confidence: medium + confidence: high # Open redirect - id: php-open-redirect - message: "Open redirect vulnerability detected" + message: "Open redirect vulnerability detected - user input flows to redirect location" severity: HIGH languages: [php] - pattern-either: - - pattern: "header('Location: ' . $USER_INPUT)" - - pattern: 'header("Location: $USER_INPUT")' - - pattern: "header('Location: ' . $_GET[$PARAM])" - - pattern: "header('Location: ' . $_POST[$PARAM])" + mode: taint + pattern-sources: + - pattern: $_GET + - pattern: $_POST + - pattern: $_REQUEST + - pattern: $_COOKIE + - pattern: $_SERVER['REQUEST_URI'] + - pattern: $_SERVER['QUERY_STRING'] + - pattern: $_SERVER['HTTP_REFERER'] + pattern-sinks: + - pattern: | + header('Location: ' . $URL) + - pattern: | + header("Location: $URL") + - pattern: header($HEADER) + pattern-sanitizers: + - pattern: filter_var($URL, FILTER_VALIDATE_URL) + - pattern: parse_url($URL) metadata: category: security cwe: CWE-601 - confidence: medium + confidence: high # XXE vulnerabilities - id: php-xxe-vulnerability @@ -277,10 +412,11 @@ rules: message: "Use of HTTP instead of HTTPS" severity: MEDIUM languages: [php] - pattern: $URL - metavariable-regex: - metavariable: $URL - regex: "http://.*" + pattern-either: + - pattern: file_get_contents("http://...") + - pattern: curl_setopt($CH, CURLOPT_URL, "http://...") + - pattern: | + $VAR = "http://..."; metadata: category: security cwe: CWE-319 @@ -308,13 +444,13 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [php] - pattern-either: - - pattern: var_dump($USER_INPUT) - - pattern: print_r($USER_INPUT) - - pattern: error_reporting(E_ALL) - - pattern: ini_set('display_errors', 1) - - pattern: phpinfo() - where: + patterns: + - pattern-either: + - pattern: var_dump($USER_INPUT) + - pattern: print_r($USER_INPUT) + - pattern: error_reporting(E_ALL) + - pattern: ini_set('display_errors', 1) + - pattern: phpinfo() - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* @@ -328,10 +464,11 @@ rules: message: "Hardcoded IP address detected" severity: LOW languages: [php] - pattern: $IP_ADDRESS - metavariable-regex: - metavariable: $IP_ADDRESS - regex: "(192\\.168\\.\\d{1,3}\\.\\d{1,3})|(10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})|(172\\.16\\.\\d{1,3}\\.\\d{1,3})|127\\.0\\.0\\.1|localhost" + pattern-either: + - pattern: $VAR = "192.168.$X.$Y"; + - pattern: $VAR = "10.$X.$Y.$Z"; + - pattern: $VAR = "127.0.0.1"; + - pattern: $VAR = "localhost"; metadata: category: security cwe: CWE-798 diff --git a/socket_basics/rules/python.yml b/socket_basics/rules/python.yml index d90408f..11182b0 100644 --- a/socket_basics/rules/python.yml +++ b/socket_basics/rules/python.yml @@ -1,108 +1,1174 @@ rules: - # === Bandit B101: Assert statements === - - id: python-assert-used - message: "Use of assert detected. Assert statements are removed when compiling to optimized bytecode" - severity: WARNING + # ===================================================================== + # OWASP Top 10 2021 Coverage for Python + # ===================================================================== + + # ===================================================================== + # A01:2021 - Broken Access Control + # ===================================================================== + + # Path traversal vulnerabilities + - id: python-path-traversal-open + message: "Path traversal vulnerability detected. User-controlled data flows into file operations without proper validation. Use os.path.abspath() and validate the result is within allowed directory." + severity: HIGH languages: [python] - pattern: assert $CONDITION + mode: taint + pattern-sources: + # Flask request sources + - pattern: request.args + - pattern: request.form + - pattern: request.values + - pattern: request.json + - pattern: request.data + - pattern: request.cookies + - pattern: request.files + # Django request sources + - pattern: request.GET + - pattern: request.POST + - pattern: request.COOKIES + - pattern: request.FILES + # FastAPI request sources + - pattern: request.query_params + - pattern: request.path_params + # Generic input sources + - pattern: input(...) + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + # Path operations that propagate taint (if any arg is tainted, result is tainted) + - pattern: os.path.join(..., $X, ...) + from: $X + to: os.path.join + - pattern: pathlib.Path($X) + from: $X + to: pathlib.Path + pattern-sinks: + # File operations + - pattern: open(...) + - pattern: io.open(...) + - pattern: pathlib.Path(...).open(...) + - pattern: pathlib.Path(...).read_text(...) + - pattern: pathlib.Path(...).read_bytes(...) + - pattern: pathlib.Path(...).write_text(...) + - pattern: pathlib.Path(...).write_bytes(...) + # os module file operations + - pattern: os.remove(...) + - pattern: os.unlink(...) + - pattern: os.rmdir(...) + - pattern: os.rename(...) + - pattern: os.replace(...) + # shutil operations + - pattern: shutil.copy(...) + - pattern: shutil.copy2(...) + - pattern: shutil.copytree(...) + - pattern: shutil.move(...) + - pattern: shutil.rmtree(...) + pattern-sanitizers: + # Path validation functions + - pattern: os.path.abspath(...) + - pattern: os.path.realpath(...) + - pattern: pathlib.Path(...).resolve() metadata: category: security - bandit_equivalent: B101 - cwe: CWE-703 + owasp: "A01:2021" + cwe: CWE-22 + confidence: high + subcategory: access-control + + # Open redirect + - id: python-open-redirect + message: "Open redirect vulnerability detected. User-controlled data flows into redirect without validation. Validate URLs against an allowlist of trusted domains." + severity: MEDIUM + languages: [python] + mode: taint + pattern-sources: + # Flask request sources + - pattern: request.args + - pattern: request.form + - pattern: request.values + - pattern: request.json + - pattern: request.data + - pattern: request.cookies + # Django request sources + - pattern: request.GET + - pattern: request.POST + - pattern: request.COOKIES + # FastAPI request sources + - pattern: request.query_params + - pattern: request.path_params + # Generic input sources + - pattern: input(...) + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # Flask redirects + - pattern: flask.redirect(...) + - pattern: redirect(...) + # Django redirects + - pattern: django.shortcuts.redirect(...) + - pattern: django.http.HttpResponseRedirect(...) + - pattern: HttpResponseRedirect(...) + # FastAPI redirects + - pattern: fastapi.responses.RedirectResponse(...) + - pattern: RedirectResponse(...) + pattern-sanitizers: + # URL validation functions (if any are used) + - pattern: urllib.parse.urlparse(...) + metadata: + category: security + owasp: "A01:2021" + cwe: CWE-601 + confidence: high + subcategory: access-control + + # Insecure direct object reference + - id: python-idor-vulnerability + message: "Potential IDOR vulnerability - verify user authorization before accessing resource" + severity: HIGH + languages: [python] + patterns: + - pattern-either: + - pattern: $MODEL.objects.get(id=$REQ.$W.get(...)) + - pattern: $MODEL.objects.get(pk=$REQ.$W[...]) + - pattern: $SESSION.query($MODEL).get($REQ.$W.get(...)) + - pattern: $DB.get($MODEL, $REQ.$W.get(...)) + - pattern-not-inside: | + ... + if $USER.id == ...: + ... + - pattern-not-inside: | + ... + if $OBJ.user_id == $USER.id: + ... + metadata: + category: security + owasp: "A01:2021" + cwe: CWE-639 + confidence: medium + subcategory: access-control + + # Missing authorization check + - id: python-missing-auth-check + message: "Route handler missing authentication/authorization check" + severity: HIGH + languages: [python] + patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC($REQ, ...): + ... + - pattern-not-inside: | + @$APP.route(...) + @login_required + def $FUNC($REQ, ...): + ... + - pattern-not-inside: | + @$APP.route(...) + @permission_required(...) + def $FUNC($REQ, ...): + ... + - pattern-not-inside: | + ... + if not $REQ.user.is_authenticated: + ... + - metavariable-regex: + metavariable: $FUNC + regex: (create|update|delete|remove|edit|modify)_(user|account|profile|password|permission|role|admin|resource|data|record) + metadata: + category: security + owasp: "A01:2021" + cwe: CWE-862 + confidence: low + subcategory: access-control + + # ===================================================================== + # A02:2021 - Cryptographic Failures + # ===================================================================== + + # Weak cryptographic hash algorithms + - id: python-weak-hash-md5 + message: "MD5 is cryptographically broken and should not be used" + severity: HIGH + languages: [python] + pattern-either: + - pattern: hashlib.md5(...) + - pattern: Crypto.Hash.MD5.new(...) + - pattern: cryptography.hazmat.primitives.hashes.MD5() + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-327 + confidence: high + subcategory: crypto + + - id: python-weak-hash-sha1 + message: "SHA1 is cryptographically weak and should not be used for security" + severity: HIGH + languages: [python] + pattern-either: + - pattern: hashlib.sha1(...) + - pattern: Crypto.Hash.SHA1.new(...) + - pattern: cryptography.hazmat.primitives.hashes.SHA1() + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-327 + confidence: high + subcategory: crypto + + # Insecure random number generation + - id: python-insecure-random + message: "random module used for security-sensitive operation - use secrets module instead" + severity: HIGH + languages: [python] + patterns: + - pattern-either: + - pattern: random.random() + - pattern: random.randint(...) + - pattern: random.choice(...) + - pattern: random.randrange(...) + - pattern-inside: | + ... + $TOKEN = ... + ... + - metavariable-regex: + metavariable: $TOKEN + regex: (?i).*(token|secret|key|password|salt|nonce|session|auth|crypto).* + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-338 + confidence: medium + subcategory: crypto + fix: "Use secrets.token_bytes(), secrets.token_hex(), or secrets.choice() for security-sensitive operations" + + # Hardcoded secrets + - id: python-hardcoded-secret + message: "Hardcoded secret or credential detected - use environment variables" + severity: HIGH + languages: [python] + patterns: + - pattern-either: + - pattern: $VAR = "..." + - pattern: $VAR = '...' + - metavariable-regex: + metavariable: $VAR + regex: (?i).*(password|passwd|pwd|secret|api[_-]?key|private[_-]?key|access[_-]?token|auth[_-]?token|session[_-]?key|db[_-]?password).* + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-798 + confidence: medium + subcategory: crypto + + # Weak cipher algorithms + - id: python-weak-cipher-des + message: "Weak cipher algorithm DES detected - use AES-256-GCM instead" + severity: HIGH + languages: [python] + pattern-either: + - pattern: Crypto.Cipher.DES.new(...) + - pattern: Crypto.Cipher.DES3.new(...) + - pattern: Crypto.Cipher.ARC2.new(...) + - pattern: Crypto.Cipher.ARC4.new(...) + - pattern: Crypto.Cipher.Blowfish.new(...) + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-327 + confidence: high + subcategory: crypto + + # SSL/TLS verification disabled + - id: python-ssl-verify-disabled + message: "SSL certificate validation disabled - vulnerable to MITM attacks" + severity: CRITICAL + languages: [python] + pattern-either: + - pattern: requests.get(..., verify=False, ...) + - pattern: requests.post(..., verify=False, ...) + - pattern: requests.request(..., verify=False, ...) + - pattern: urllib.request.urlopen(..., context=ssl._create_unverified_context(), ...) + - pattern: httpx.get(..., verify=False, ...) + - pattern: aiohttp.ClientSession(..., connector=aiohttp.TCPConnector(ssl=False), ...) + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-295 confidence: high + subcategory: crypto - # === Bandit B102: Exec used === - - id: python-exec-used - message: "Use of exec detected. This can be dangerous if used with untrusted input" - severity: ERROR + # Insecure TLS versions + - id: python-insecure-tls-version + message: "Insecure TLS version - use TLS 1.2 or higher" + severity: HIGH languages: [python] pattern-either: - - pattern: exec($EXPR) - - pattern: exec($EXPR, ...) + - pattern: ssl.PROTOCOL_SSLv2 + - pattern: ssl.PROTOCOL_SSLv3 + - pattern: ssl.PROTOCOL_TLSv1 + - pattern: ssl.PROTOCOL_TLSv1_1 + - pattern: ssl.SSLContext(ssl.PROTOCOL_SSLv3) + - pattern: ssl.SSLContext(ssl.PROTOCOL_TLSv1) metadata: category: security - bandit_equivalent: B102 + owasp: "A02:2021" + cwe: CWE-327 + confidence: high + subcategory: crypto + + # ===================================================================== + # A03:2021 - Injection + # ===================================================================== + + # Code injection via eval + - id: python-code-injection-eval + message: "Code injection vulnerability detected. User-controlled data flows into eval()/exec() which can execute arbitrary code. Avoid eval/exec entirely or use ast.literal_eval() for safe evaluation." + severity: CRITICAL + languages: [python] + mode: taint + pattern-sources: + # Flask request sources + - pattern: request.args + - pattern: request.form + - pattern: request.values + - pattern: request.json + - pattern: request.data + - pattern: request.cookies + # Django request sources + - pattern: request.GET + - pattern: request.POST + - pattern: request.COOKIES + # FastAPI request sources + - pattern: request.query_params + - pattern: request.path_params + # Generic input sources + - pattern: input(...) + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # Code execution sinks + - pattern: eval(...) + - pattern: exec(...) + - pattern: compile(...) + - pattern: __import__(...) + pattern-sanitizers: + # Safe alternatives + - pattern: ast.literal_eval(...) + - pattern: json.loads(...) + metadata: + category: security + owasp: "A03:2021" cwe: CWE-94 confidence: high + subcategory: injection + + # SQL injection + - id: python-sql-injection + message: "SQL injection vulnerability detected. User-controlled data flows into SQL query without proper sanitization. Use parameterized queries with placeholders (?, %s) to prevent SQL injection." + severity: CRITICAL + languages: [python] + mode: taint + pattern-sources: + # Flask request sources + - pattern: request.args + - pattern: request.form + - pattern: request.values + - pattern: request.json + - pattern: request.data + - pattern: request.cookies + # Django request sources + - pattern: request.GET + - pattern: request.POST + - pattern: request.COOKIES + # FastAPI request sources + - pattern: request.query_params + - pattern: request.path_params + # Generic input sources + - pattern: input(...) + pattern-propagators: + # String concatenation and formatting + - pattern: $A + $B + from: $B + to: $A + # Template strings and formatting propagate taint implicitly + pattern-sinks: + # Database cursor/connection execute methods + - pattern: $CURSOR.execute(...) + - pattern: $CURSOR.executemany(...) + - pattern: $CONN.execute(...) + - pattern: $DB.execute(...) + # Django ORM raw queries + - pattern: $MODEL.objects.raw(...) + - pattern: RawSQL(...) + # SQLAlchemy text queries + - pattern: sqlalchemy.text(...) + - pattern: text(...) + # Psycopg2/psycopg3 + - pattern: $CURSOR.mogrify(...) + # MySQL connector + - pattern: mysql.connector.cursor.execute(...) + pattern-sanitizers: + # Parameterized queries with proper placeholders + - pattern: $CURSOR.execute("...", (...)) + - pattern: $CURSOR.execute("...", [...]) + - pattern: $CONN.execute("...", (...)) + - pattern: $CONN.execute("...", [...]) + # ORM methods that use parameterization + - pattern: $MODEL.objects.filter(...) + - pattern: $MODEL.objects.get(...) + - pattern: $QUERY.filter(...) + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-89 + confidence: high + subcategory: injection + + # NoSQL injection (MongoDB) + - id: python-nosql-injection + message: "NoSQL injection vulnerability - validate and sanitize user input" + severity: HIGH + languages: [python] + pattern-either: + # Direct request data in MongoDB queries + - pattern: $COLLECTION.find($REQ.GET) + - pattern: $COLLECTION.find($REQ.POST) + - pattern: $COLLECTION.find_one($REQ.GET.get(...)) + - pattern: $COLLECTION.update($REQ.POST, ...) + - pattern: $COLLECTION.delete_one($REQ.GET) + # Pymongo with user input + - pattern: "$DB[$COLLECTION].find({ ..., $KEY: $REQ.$W.get(...), ... })" + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-943 + confidence: high + subcategory: injection + + # Command injection + - id: python-command-injection + message: "Command injection vulnerability detected. User-controlled data flows into system command execution without proper sanitization. Avoid shell=True and use list arguments instead of string concatenation." + severity: CRITICAL + languages: [python] + mode: taint + pattern-sources: + # Flask request sources + - pattern: request.args + - pattern: request.form + - pattern: request.values + - pattern: request.json + - pattern: request.data + - pattern: request.cookies + # Django request sources + - pattern: request.GET + - pattern: request.POST + - pattern: request.COOKIES + # FastAPI request sources + - pattern: request.query_params + - pattern: request.path_params + # Generic input sources + - pattern: input(...) + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + # Template strings propagate taint implicitly + pattern-sinks: + # Dangerous command execution methods + - pattern: os.system(...) + - pattern: os.popen(...) + - pattern: os.popen2(...) + - pattern: os.popen3(...) + - pattern: os.popen4(...) + - pattern: subprocess.call(..., shell=True, ...) + - pattern: subprocess.run(..., shell=True, ...) + - pattern: subprocess.Popen(..., shell=True, ...) + - pattern: subprocess.check_output(..., shell=True, ...) + - pattern: subprocess.check_call(..., shell=True, ...) + - pattern: commands.getoutput(...) + - pattern: commands.getstatusoutput(...) + - pattern: eval(...) + - pattern: exec(...) + pattern-sanitizers: + # Safe subprocess usage with list arguments (not shell=True) + - pattern: subprocess.run([...], ...) + - pattern: subprocess.call([...], ...) + - pattern: subprocess.Popen([...], ...) + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-78 + confidence: high + subcategory: injection - # === Bandit B103: File permissions === - - id: python-bad-file-permissions - message: "File created with potentially unsafe permissions" - severity: ERROR + # LDAP injection + - id: python-ldap-injection + message: "LDAP injection vulnerability - sanitize user input in LDAP queries" + severity: HIGH languages: [python] pattern-either: - - pattern: os.chmod($PATH, $PERMS) - - pattern: os.fchmod($FD, $PERMS) - - pattern: os.lchmod($PATH, $PERMS) - where: - # Check for overly permissive permissions (world writable) - - metavariable-pattern: - metavariable: $PERMS - pattern-either: - - pattern: 0o777 - - pattern: 0o666 - - pattern: 0o644 - - pattern: 511 # 0o777 in decimal - - pattern: 438 # 0o666 in decimal + - pattern: ldap.search_s($BASE, $SCOPE, $FILTER + $USER_INPUT) + - pattern: ldap.search_s($BASE, $SCOPE, f"...{$USER_INPUT}...") + - pattern: ldap.search($BASE, $SCOPE, $FILTER + $USER_INPUT) metadata: category: security - bandit_equivalent: B103 + owasp: "A03:2021" + cwe: CWE-90 + confidence: high + subcategory: injection + + # XSS via template rendering + - id: python-xss-template + message: "XSS vulnerability detected. User-controlled data flows into template rendering without proper escaping. Use template auto-escaping or explicit escaping functions." + severity: HIGH + languages: [python] + mode: taint + pattern-sources: + # Flask request sources + - pattern: request.args + - pattern: request.form + - pattern: request.values + - pattern: request.json + - pattern: request.data + - pattern: request.cookies + # Django request sources + - pattern: request.GET + - pattern: request.POST + - pattern: request.COOKIES + # FastAPI request sources + - pattern: request.query_params + - pattern: request.path_params + # Generic input sources + - pattern: input(...) + pattern-propagators: + # String concatenation + - pattern: $A + $B + from: $B + to: $A + pattern-sinks: + # Flask template sinks + - pattern: flask.render_template_string(...) + - pattern: render_template_string(...) + # Jinja2 template sinks + - pattern: jinja2.Template(...).render(...) + - pattern: Template(...).render(...) + # Django mark_safe (disables escaping) + - pattern: django.utils.safestring.mark_safe(...) + - pattern: django.utils.html.mark_safe(...) + - pattern: mark_safe(...) + # Direct HTTP response with HTML + - pattern: HttpResponse(...) + - pattern: flask.Response(...) + pattern-sanitizers: + # Escaping functions + - pattern: flask.escape(...) + - pattern: django.utils.html.escape(...) + - pattern: html.escape(...) + - pattern: markupsafe.escape(...) + # Template rendering with auto-escape (safe) + - pattern: render_template(...) + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-79 + confidence: high + subcategory: injection + + # XXE (XML External Entity) + - id: python-xxe-vulnerability + message: "XXE vulnerability - disable external entity processing in XML parser" + severity: HIGH + languages: [python] + patterns: + - pattern-either: + - pattern: xml.etree.ElementTree.parse($FILE) + - pattern: xml.etree.ElementTree.fromstring($XML) + - pattern: lxml.etree.parse($FILE) + - pattern: lxml.etree.fromstring($XML) + - pattern-not-inside: | + ... + defusedxml.ElementTree.parse(...) + ... + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-611 + confidence: medium + subcategory: injection + + # Server-side template injection + - id: python-template-injection + message: "Template injection vulnerability - sanitize user input in templates" + severity: CRITICAL + languages: [python] + pattern-either: + # Jinja2 from string with user input + - pattern: jinja2.Environment().from_string($REQ.$W.get(...)) + - pattern: jinja2.Template($REQ.$W.get(...)) + # Flask template string with user input + - pattern: flask.render_template_string($REQ.args.get(...)) + - pattern: flask.render_template_string($REQ.form.get(...)) + # Mako template with user input + - pattern: mako.template.Template($REQ.$W.get(...)) + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-1336 + confidence: high + subcategory: injection + + # YAML deserialization + - id: python-yaml-load-unsafe + message: "Unsafe YAML deserialization - use yaml.safe_load() instead" + severity: CRITICAL + languages: [python] + pattern-either: + - pattern: yaml.load($DATA, ...) + - pattern: yaml.load_all($DATA, ...) + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-502 + confidence: high + subcategory: injection + + # ===================================================================== + # A04:2021 - Insecure Design + # ===================================================================== + + # Missing rate limiting + - id: python-missing-rate-limit + message: "Authentication route missing rate limiting - vulnerable to brute force attacks" + severity: MEDIUM + languages: [python] + patterns: + - pattern-inside: | + @$APP.route(..., methods=[..., "POST", ...]) + def $FUNC(...): + ... + - pattern-not-inside: | + @limiter.limit(...) + def $FUNC(...): + ... + - pattern-not-inside: | + @$APP.route(...) + @ratelimit(...) + def $FUNC(...): + ... + - metavariable-regex: + metavariable: $FUNC + regex: (login|signin|authenticate).* + metadata: + category: security + owasp: "A04:2021" + cwe: CWE-307 + confidence: low + subcategory: design + + # Insufficient input validation + - id: python-missing-input-validation + message: "User input used without validation" + severity: MEDIUM + languages: [python] + patterns: + - pattern-either: + - pattern: int($REQ.$W.get(...)) + - pattern: float($REQ.$W.get(...)) + - pattern: eval($REQ.$W.get(...)) + - pattern-not-inside: | + ... + if isinstance(..., ...): + ... + - pattern-not-inside: | + ... + try: + ... + except ValueError: + ... + metadata: + category: security + owasp: "A04:2021" + cwe: CWE-20 + confidence: low + subcategory: design + + # ===================================================================== + # A05:2021 - Security Misconfiguration + # ===================================================================== + + # Debug mode enabled + - id: python-debug-mode-enabled + message: "Debug mode enabled - exposes sensitive information in production" + severity: HIGH + languages: [python] + pattern-either: + # Flask debug + - pattern: $APP.run(..., debug=True, ...) + - pattern: $APP.debug = True + # Django settings + - pattern: DEBUG = True + # FastAPI + - pattern: fastapi.FastAPI(..., debug=True, ...) + metadata: + category: security + owasp: "A05:2021" + cwe: CWE-489 + confidence: high + subcategory: configuration + + # Weak session configuration + - id: python-weak-session-config + message: "Insecure session configuration" + severity: HIGH + languages: [python] + pattern-either: + # Flask session without secure flag + - pattern: $APP.config["SESSION_COOKIE_SECURE"] = False + - pattern: $APP.config["SESSION_COOKIE_HTTPONLY"] = False + - pattern: $APP.config["SESSION_COOKIE_SAMESITE"] = None + # Django session settings + - pattern: SESSION_COOKIE_SECURE = False + - pattern: SESSION_COOKIE_HTTPONLY = False + - pattern: CSRF_COOKIE_SECURE = False + metadata: + category: security + owasp: "A05:2021" + cwe: CWE-614 + confidence: high + subcategory: configuration + + # Exposed error messages + - id: python-error-exposure + message: "Error details exposed to client - can leak sensitive information" + severity: MEDIUM + languages: [python] + pattern-either: + - pattern: | + try: + ... + except $EXC as $E: + ... + return ..., str($E), ... + - pattern: | + try: + ... + except $EXC as $E: + ... + flask.jsonify(..., error=str($E), ...) + - pattern: | + try: + ... + except $EXC as $E: + ... + print($E) + metadata: + category: security + owasp: "A05:2021" + cwe: CWE-209 + confidence: medium + subcategory: configuration + + # Insecure file permissions + - id: python-insecure-file-permissions + message: "File created with insecure permissions" + severity: HIGH + languages: [python] + pattern-either: + - pattern: os.chmod($PATH, 0o777) + - pattern: os.chmod($PATH, 0o666) + - pattern: os.chmod($PATH, 511) + - pattern: os.chmod($PATH, 438) + - pattern: os.open($PATH, $FLAGS, 0o777) + metadata: + category: security + owasp: "A05:2021" cwe: CWE-732 + confidence: high + subcategory: configuration - # === Bandit B104: Hardcoded bind all interfaces === - - id: python-hardcoded-bind-all-interfaces - message: "Possible binding to all interfaces. Consider using localhost" - severity: WARNING + # Binding to all interfaces + - id: python-bind-all-interfaces + message: "Binding to all interfaces (0.0.0.0) - consider using localhost" + severity: LOW languages: [python] pattern-either: + - pattern: $APP.run(..., host="0.0.0.0", ...) - pattern: $SOCK.bind(("0.0.0.0", $PORT)) - - pattern: $SOCK.bind(('0.0.0.0', $PORT)) - pattern: $SERVER.serve_forever(host="0.0.0.0") - - pattern: $SERVER.serve_forever(host='0.0.0.0') metadata: category: security - bandit_equivalent: B104 + owasp: "A05:2021" cwe: CWE-200 + confidence: medium + subcategory: configuration + + # ===================================================================== + # A06:2021 - Vulnerable and Outdated Components + # ===================================================================== - # === Bandit B105: Hardcoded password string === - - id: python-hardcoded-password-string - message: "Possible hardcoded password detected" - severity: ERROR + # Deprecated functions + - id: python-deprecated-functions + message: "Deprecated function - use modern alternatives" + severity: LOW languages: [python] pattern-either: - - pattern: $VAR = "$VALUE" - where: - # Match variable names that are likely intended to be secrets. - # Require word boundaries or common separators to avoid matching names like PYPI_API or API_KEY_VERSION. - - metavariable-regex: - metavariable: $VAR - # match whole word or common snake/camel variants, case-insensitive - regex: (?i)^(?:.*\b(password|passwd|pwd|secret|token|key|api_key)\b.*|.*(?:_password|_passwd|_pwd|_secret|_token|_key|_api_key)$|^(?:password|passwd|pwd|secret|token|key|api_key)$) + - pattern: os.tempnam() + - pattern: os.tmpnam() + - pattern: platform.popen(...) + - pattern: imp.load_source(...) metadata: category: security - bandit_equivalent: B105 - cwe: CWE-259 + owasp: "A06:2021" + cwe: CWE-477 + confidence: high + subcategory: deprecated + + # ===================================================================== + # A07:2021 - Identification and Authentication Failures + # ===================================================================== - # === Bandit B106: Hardcoded password function argument === - - id: python-hardcoded-password-funcarg - message: "Possible hardcoded password in function argument" - severity: WARNING + # Weak password validation + - id: python-weak-password-validation + message: "Weak password validation - enforce strong password policy" + severity: MEDIUM + languages: [python] + patterns: + - pattern: | + if len($PASSWORD) < $N: + ... + - metavariable-comparison: + metavariable: $N + comparison: $N < 8 + metadata: + category: security + owasp: "A07:2021" + cwe: CWE-521 + confidence: low + subcategory: authentication + + # JWT without verification + - id: python-jwt-no-verify + message: "JWT decoded without signature verification - use jwt.decode() with verify=True" + severity: HIGH languages: [python] pattern-either: - - pattern: $FUNC(..., password="...", ...) - - pattern: $FUNC(..., passwd="...", ...) - - pattern: $FUNC(..., secret="...", ...) - - pattern: $FUNC(..., token="...", ...) - - pattern: $FUNC(..., api_key="...", ...) + - pattern: 'jwt.decode($TOKEN, options={"verify_signature": False})' + - pattern: jwt.decode($TOKEN, verify=False) + - pattern: 'jwt.decode($TOKEN, ..., options={..., "verify_signature": False, ...})' metadata: category: security - bandit_equivalent: B106 - cwe: CWE-259 + owasp: "A07:2021" + cwe: CWE-347 + confidence: high + subcategory: authentication + + # Weak JWT algorithm + - id: python-weak-jwt-algorithm + message: "Weak or no JWT algorithm - should use RS256 or HS256" + severity: HIGH + languages: [python] + pattern-either: + - pattern: jwt.encode(..., algorithm="none") + - pattern: jwt.decode(..., algorithms=["none"]) + - pattern: 'jwt.decode($TOKEN, ..., options={..., "verify_signature": False, ...})' + metadata: + category: security + owasp: "A07:2021" + cwe: CWE-347 + confidence: high + subcategory: authentication + + # Missing password hashing + - id: python-plain-text-password + message: "Password stored or compared in plain text - use bcrypt, argon2, or pbkdf2" + severity: CRITICAL + languages: [python] + patterns: + - pattern-either: + - pattern: $USER.password = $REQ.$W.get(...) + - pattern: $USER.password == $INPUT + - pattern: $PASSWORD == $REQ.$W.get(...) + - pattern-not-inside: | + ... + bcrypt.hashpw(...) + ... + - pattern-not-inside: | + ... + hashlib.pbkdf2_hmac(...) + ... + - pattern-not-inside: | + ... + werkzeug.security.generate_password_hash(...) + ... + metadata: + category: security + owasp: "A07:2021" + cwe: CWE-916 + confidence: medium + subcategory: authentication + + # ===================================================================== + # A08:2021 - Software and Data Integrity Failures + # ===================================================================== + + # Unsafe deserialization + - id: python-unsafe-deserialization + message: "Unsafe deserialization - can lead to remote code execution" + severity: CRITICAL + languages: [python] + pattern-either: + # Pickle + - pattern: pickle.loads($DATA) + - pattern: pickle.load($FILE) + - pattern: cPickle.loads($DATA) + # Marshal + - pattern: marshal.loads($DATA) + - pattern: marshal.load($FILE) + # Shelve + - pattern: shelve.open($FILE) + metadata: + category: security + owasp: "A08:2021" + cwe: CWE-502 + confidence: high + subcategory: integrity + + # Missing integrity check + - id: python-missing-integrity-check + message: "Downloaded file without integrity verification" + severity: MEDIUM + languages: [python] + patterns: + - pattern-either: + - pattern: requests.get($URL).content + - pattern: urllib.request.urlretrieve($URL, ...) + - pattern-not-inside: | + ... + hashlib.sha256(...).hexdigest() + ... + - pattern-not-inside: | + ... + if $HASH == ...: + ... + metadata: + category: security + owasp: "A08:2021" + cwe: CWE-353 + confidence: low + subcategory: integrity + + # ===================================================================== + # A09:2021 - Security Logging and Monitoring Failures + # ===================================================================== + + # Sensitive data in logs + - id: python-sensitive-data-in-logs + message: "Sensitive data logged - can expose credentials or personal information" + severity: MEDIUM + languages: [python] + pattern-either: + - pattern: logging.info(..., $PASSWORD, ...) + - pattern: logging.debug(..., $TOKEN, ...) + - pattern: logging.error(..., $SECRET, ...) + - pattern: print(..., $REQ.$W.get("password"), ...) + - pattern: logger.info(..., $REQ.$W.get("token"), ...) + metadata: + category: security + owasp: "A09:2021" + cwe: CWE-532 + confidence: low + subcategory: logging + + # Missing error logging + - id: python-missing-error-logging + message: "Error caught but not logged - can hide security issues" + severity: LOW + languages: [python] + patterns: + - pattern: | + try: + ... + except $EXC: + pass + - pattern-not-inside: | + try: + ... + except $EXC: + logging.error(...) + - pattern-not-inside: | + try: + ... + except $EXC: + logger.exception(...) + metadata: + category: security + owasp: "A09:2021" + cwe: CWE-778 + confidence: low + subcategory: logging + + # ===================================================================== + # A10:2021 - Server-Side Request Forgery (SSRF) + # ===================================================================== + + # SSRF via user-controlled URL + - id: python-ssrf-vulnerability + message: "SSRF vulnerability - validate and whitelist URLs before making requests" + severity: HIGH + languages: [python] + pattern-either: + - pattern: requests.get($REQ.$W.get(...)) + - pattern: requests.post($REQ.$W.get(...), ...) + - pattern: urllib.request.urlopen($REQ.$W.get(...)) + - pattern: urllib.request.urlretrieve($REQ.$W.get(...), ...) + - pattern: httpx.get($REQ.$W.get(...)) + - pattern: aiohttp.ClientSession().get($REQ.$W.get(...)) + metadata: + category: security + owasp: "A10:2021" + cwe: CWE-918 + confidence: high + subcategory: ssrf + + # ===================================================================== + # Python Best Practices + # ===================================================================== + + # Assert in production code + - id: python-assert-used + message: "Assert statement in code - removed when compiling to optimized bytecode" + severity: LOW + languages: [python] + pattern: assert $CONDITION + metadata: + category: best-practice + cwe: CWE-703 + confidence: high + subcategory: error-handling + + # Bare except clause + - id: python-bare-except + message: "Bare except clause catches all exceptions including system exits" + severity: MEDIUM + languages: [python] + pattern: | + try: + ... + except: + ... + metadata: + category: best-practice + cwe: CWE-396 + confidence: high + subcategory: error-handling + + # Use of exec/eval + - id: python-dangerous-eval-exec + message: "Use of eval/exec can execute arbitrary code - avoid if possible" + severity: HIGH + languages: [python] + patterns: + - pattern-either: + - pattern: eval(...) + - pattern: exec(...) + # Exclude hardcoded strings + - pattern-not: eval("...") + - pattern-not: exec("...") + metadata: + category: security + cwe: CWE-95 + confidence: high + subcategory: injection + + # SQL format string + - id: python-sql-format-string + message: "SQL query using string formatting - use parameterized queries" + severity: CRITICAL + languages: [python] + pattern-either: + - pattern: $DB.execute("SELECT ..." % ...) + - pattern: $DB.execute("INSERT ..." % ...) + - pattern: $DB.execute("UPDATE ..." % ...) + - pattern: $DB.execute("DELETE ..." % ...) + metadata: + category: security + cwe: CWE-89 + confidence: high + subcategory: injection + + # Tempfile without secure flags + - id: python-insecure-temp-file + message: "Temporary file created insecurely - use tempfile.mkstemp() or TemporaryFile()" + severity: MEDIUM + languages: [python] + pattern-either: + - pattern: open("/tmp/...", ...) + - pattern: open("/var/tmp/...", ...) + - pattern: tempfile.mktemp() + metadata: + category: security + cwe: CWE-377 + confidence: high + subcategory: file-operations + + # ReDoS vulnerability + - id: python-regex-dos + message: "Complex regex pattern with user input - potential ReDoS vulnerability" + severity: MEDIUM + languages: [python] + pattern-either: + # User input as regex pattern + - pattern: re.compile($REQ.$W.get(...)) + - pattern: re.match($REQ.$W.get(...), ...) + - pattern: re.search($REQ.$W.get(...), ...) + # Dangerous regex patterns + - pattern: re.compile(r"(.+)+") + - pattern: re.compile(r"(.*)+") + - pattern: re.compile(r"(.*)\\*") + - pattern: re.compile(r"(a+)+") + metadata: + category: security + cwe: CWE-1333 + confidence: medium + subcategory: dos + + # Unvalidated file upload + - id: python-unvalidated-file-upload + message: "File upload without validation - validate file type, size, and content" + severity: HIGH + languages: [python] + patterns: + - pattern-either: + - pattern: $FILE.save($PATH) + - pattern: open($PATH, "wb").write($REQ.files.get(...).read()) + - pattern-not-inside: | + ... + if $FILE.filename.endswith(...): + ... + - pattern-not-inside: | + ... + if $FILE.content_type in [...]: + ... + metadata: + category: security + cwe: CWE-434 + confidence: low + subcategory: upload # === Bandit B107: Hardcoded password default === - id: python-hardcoded-password-default message: "Possible hardcoded password in function default" - severity: WARNING + severity: MEDIUM languages: [python] pattern-either: - pattern: | @@ -122,7 +1188,7 @@ rules: # === Bandit B301: Pickle usage === - id: python-pickle-usage message: "Pickle usage detected. Pickle can be unsafe when loading untrusted data" - severity: ERROR + severity: CRITICAL languages: [python] pattern-either: - pattern: pickle.loads($DATA) @@ -140,7 +1206,7 @@ rules: # === Bandit B303: MD5 hash usage === - id: python-md5-usage message: "Use of insecure MD5 hash function detected" - severity: WARNING + severity: MEDIUM languages: [python] pattern-either: - pattern: hashlib.md5(...) @@ -155,7 +1221,7 @@ rules: # === Bandit B304: SHA1 hash usage === - id: python-sha1-usage message: "Use of insecure SHA1 hash function detected" - severity: WARNING + severity: MEDIUM languages: [python] pattern-either: - pattern: hashlib.sha1(...) @@ -170,9 +1236,12 @@ rules: # === Bandit B307: Eval usage === - id: python-eval-usage message: "Use of eval() detected. This can execute arbitrary code" - severity: ERROR + severity: CRITICAL languages: [python] - pattern: eval($EXPR) + patterns: + - pattern: eval($EXPR) + # Exclude hardcoded strings + - pattern-not: eval("...") metadata: category: security bandit_equivalent: B307 @@ -182,7 +1251,7 @@ rules: # === Bandit B501: Request without cert validation === - id: python-request-without-cert-validation message: "Request made without certificate verification" - severity: ERROR + severity: HIGH languages: [python] pattern-either: - pattern: requests.get(..., verify=False, ...) @@ -199,7 +1268,7 @@ rules: # === Bandit B502: SSL with bad version === - id: python-ssl-bad-version message: "Use of insecure SSL/TLS version detected" - severity: ERROR + severity: HIGH languages: [python] pattern-either: - pattern: ssl.PROTOCOL_SSLv2 @@ -216,7 +1285,7 @@ rules: # === Bandit B601: Paramiko calls === - id: python-paramiko-calls message: "Paramiko call detected. Ensure proper key verification" - severity: WARNING + severity: MEDIUM languages: [python] pattern-either: - pattern: paramiko.SSHClient().set_missing_host_key_policy(paramiko.AutoAddPolicy()) @@ -229,7 +1298,7 @@ rules: # === Bandit B602: Subprocess with shell=True === - id: python-subprocess-shell-true message: "Subprocess call with shell=True detected. This can be dangerous with user input" - severity: ERROR + severity: CRITICAL languages: [python] pattern-either: - pattern: subprocess.call(..., shell=True, ...) @@ -248,7 +1317,7 @@ rules: # === Bandit B605: Start process with shell === - id: python-start-process-with-shell message: "Starting a process with a shell, possible injection detected" - severity: ERROR + severity: CRITICAL languages: [python] pattern-either: - pattern: os.system($CMD) @@ -266,7 +1335,7 @@ rules: # === Bandit B608: SQL injection === - id: python-sql-injection-format message: "Possible SQL injection vector through string formatting" - severity: ERROR + severity: CRITICAL languages: [python] pattern-either: - pattern: $CURSOR.execute("..." % ...) @@ -284,7 +1353,7 @@ rules: # === Flask debug mode === - id: python-flask-debug-true message: "Flask app with debug=True detected. This should not be used in production" - severity: WARNING + severity: MEDIUM languages: [python] pattern-either: - pattern: $APP.run(debug=True, ...) @@ -298,7 +1367,7 @@ rules: # === Jinja2 autoescape false === - id: python-jinja2-autoescape-false message: "Jinja2 autoescape is set to false. This can lead to XSS vulnerabilities" - severity: ERROR + severity: HIGH languages: [python] pattern-either: - pattern: jinja2.Environment(autoescape=False, ...) @@ -311,7 +1380,7 @@ rules: # === Weak random === - id: python-weak-random message: "Use of insecure random number generator. Consider using secrets module" - severity: WARNING + severity: MEDIUM languages: [python] pattern-either: - pattern: random.random() @@ -325,9 +1394,9 @@ rules: confidence: high # === Temporary file creation === - - id: python-insecure-temp-file + - id: python-tempfile-mktemp message: "Insecure temporary file creation detected" - severity: WARNING + severity: LOW languages: [python] pattern-either: - pattern: tempfile.mktemp(...) diff --git a/socket_basics/rules/ruby.yml b/socket_basics/rules/ruby.yml index 7b60707..18da1c4 100644 --- a/socket_basics/rules/ruby.yml +++ b/socket_basics/rules/ruby.yml @@ -1,61 +1,100 @@ rules: # === Critical Severity Rules === - # Code injection via eval - keep generic + # Code injection via eval - using taint mode - id: ruby-eval-injection - message: "Code injection via eval, instance_eval, or class_eval" + message: "Code injection via eval detected. User-controlled data flows into eval without sanitization. Avoid eval with user input." severity: CRITICAL languages: [ruby] - pattern-either: - - pattern: eval($USER_INPUT) - - pattern: instance_eval($USER_INPUT) - - pattern: class_eval($USER_INPUT) - - pattern: module_eval($USER_INPUT) - - pattern: binding.eval($USER_INPUT) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: params + - pattern: request.params + - pattern: cookies + - pattern: request.query_string + pattern-propagators: + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + pattern-sinks: + # Code evaluation methods + - pattern: eval(...) + - pattern: instance_eval(...) + - pattern: class_eval(...) + - pattern: module_eval(...) + - pattern: binding.eval(...) metadata: category: security cwe: CWE-94 confidence: high - # Command injection - generic patterns + # Command injection - using taint mode for accurate detection - id: ruby-command-injection - message: "Command injection vulnerability detected" + message: "Command injection vulnerability detected. User-controlled data flows into system command without proper sanitization. Use safe command execution with array arguments or proper escaping." severity: CRITICAL languages: [ruby] - pattern-either: - - pattern: system($USER_INPUT) - - pattern: exec($USER_INPUT) - - pattern: spawn($USER_INPUT) - - pattern: IO.popen($USER_INPUT) - - pattern: Kernel.system($USER_INPUT) - # String concatenation patterns - - pattern: system($CMD + $VAR) - - pattern: system($CMD << $VAR) - - pattern: exec($CMD + $VAR) - # Backtick patterns (simplified) - - pattern: '$VAR' + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: params + - pattern: request.params + - pattern: cookies + - pattern: request.query_string + pattern-propagators: + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + pattern-sinks: + # Command execution methods + - pattern: system(...) + - pattern: exec(...) + - pattern: spawn(...) + - pattern: IO.popen(...) + - pattern: Kernel.system(...) + pattern-sanitizers: + # Array-based command execution is safe + - pattern: system([$CMD, ...]) + - pattern: spawn([$CMD, ...]) metadata: category: security cwe: CWE-78 confidence: high - # SQL injection - broad patterns that catch real cases + # SQL injection - using taint mode for accurate detection - id: ruby-sql-injection - message: "SQL injection vulnerability detected" + message: "SQL injection vulnerability detected. User-controlled data flows into SQL query without proper sanitization. Use parameterized queries with placeholders (?, :symbol) to prevent SQL injection." severity: CRITICAL languages: [ruby] - pattern-either: - # String concatenation (most common) - - pattern: $MODEL.where($QUERY + $VAR) - - pattern: $MODEL.find_by_sql($QUERY + $VAR) - - pattern: ActiveRecord::Base.connection.execute($QUERY + $VAR) - - pattern: $DB.query($QUERY + $VAR) - # String interpolation (catch variables that might contain interpolation) - - pattern: $MODEL.where($VAR) - - pattern: $MODEL.find_by_sql($VAR) - # Format string patterns - - pattern: $MODEL.where($QUERY % $VAR) - - pattern: $MODEL.where(sprintf($QUERY, $VAR)) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: params + - pattern: request.params + - pattern: cookies + - pattern: request.query_string + - pattern: request.GET + - pattern: request.POST + pattern-propagators: + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + # String interpolation is implicitly tracked + pattern-sinks: + # ActiveRecord query methods + - pattern: $MODEL.where(...) + - pattern: $MODEL.find_by_sql(...) + - pattern: ActiveRecord::Base.connection.execute(...) + - pattern: $DB.execute(...) + - pattern: $DB.query(...) + pattern-sanitizers: + # Parameterized queries + - pattern: $MODEL.where($KEY => $VAL) + - pattern: $MODEL.where("... ?", ...) + - pattern: $MODEL.where("... :$SYM", ...) metadata: category: security cwe: CWE-89 @@ -115,51 +154,98 @@ rules: cwe: CWE-798 confidence: medium - # File path traversal - generic patterns + # File path traversal - using taint mode - id: ruby-path-traversal - message: "Path traversal vulnerability detected" + message: "Path traversal vulnerability detected. User-controlled data flows into file operations without proper validation. Use File.expand_path or validate paths." severity: HIGH languages: [ruby] - pattern-either: - - pattern: File.open($PATH + $USER_INPUT) - - pattern: File.read($PATH + $USER_INPUT) - - pattern: File.write($PATH + $USER_INPUT, $DATA) - - pattern: IO.read($PATH + $USER_INPUT) - - pattern: Pathname.new($PATH + $USER_INPUT) - - pattern: Dir.glob($PATH + $USER_INPUT) - # Also catch direct user input - - pattern: File.open($USER_INPUT) - - pattern: File.read($USER_INPUT) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: params + - pattern: request.params + - pattern: cookies + pattern-propagators: + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + # File.join propagates taint + - pattern: File.join(..., (String $X), ...) + from: $X + to: File.join + pattern-sinks: + # File operations + - pattern: File.open(...) + - pattern: File.read(...) + - pattern: File.write(...) + - pattern: IO.read(...) + - pattern: Pathname.new(...) + - pattern: Dir.glob(...) + pattern-sanitizers: + # Path validation + - pattern: File.expand_path(...) + - pattern: File.basename(...) metadata: category: security cwe: CWE-22 - confidence: medium + confidence: high - # Open redirect - Rails patterns + # Open redirect - Rails patterns with taint mode - id: ruby-open-redirect message: "Open redirect vulnerability detected" severity: HIGH languages: [ruby] - pattern-either: - - pattern: redirect_to($USER_INPUT) - - pattern: redirect_to(params[$PARAM]) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: params + - pattern: request.params + - pattern: request.query_string + - pattern: cookies + pattern-propagators: + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + pattern-sinks: + # Redirect methods that are dangerous with user input + - pattern: redirect_to(...) + - pattern: redirect_back(...) metadata: category: security cwe: CWE-601 - confidence: medium + confidence: high - # XSS vulnerabilities - Rails specific + # XSS vulnerabilities - Rails specific with taint mode - id: ruby-xss-raw-output - message: "XSS vulnerability via raw HTML output" + message: "XSS vulnerability via raw HTML output. User-controlled data flows into raw HTML rendering without proper sanitization. Use sanitize() or escape HTML properly." severity: HIGH languages: [ruby] - pattern-either: - - pattern: raw($USER_INPUT) + mode: taint + pattern-sources: + # User-controlled input sources + - pattern: params + - pattern: request.params + - pattern: cookies + pattern-propagators: + # String concatenation + - pattern: (String $A) + (String $B) + from: $B + to: $A + pattern-sinks: + # Raw HTML output methods + - pattern: raw(...) - pattern: $VAR.html_safe + pattern-sanitizers: + # Proper HTML sanitization + - pattern: sanitize(...) + - pattern: h(...) + - pattern: html_escape(...) metadata: category: security cwe: CWE-79 - confidence: medium + confidence: high # SSL/TLS verification bypass - id: ruby-ssl-verification-bypass @@ -327,9 +413,9 @@ rules: severity: CRITICAL languages: [ruby] pattern-either: - - pattern: $MODEL.find_by_sql($VAR) - pattern: $MODEL.find_by_sql($QUERY + $VAR) - pattern: $MODEL.find_by_sql($QUERY % $VAR) + - pattern: $MODEL.find_by_sql("...#{$VAR}...") metadata: category: security framework: rails @@ -342,9 +428,9 @@ rules: severity: CRITICAL languages: [ruby] pattern-either: - - pattern: $MODEL.where($VAR) - pattern: $MODEL.where($QUERY + $VAR) - pattern: $MODEL.where($QUERY % $VAR) + - pattern: $MODEL.where("...#{$VAR}...") metadata: category: security framework: rails diff --git a/socket_basics/rules/rust.yml b/socket_basics/rules/rust.yml index 24e1994..ecfe598 100644 --- a/socket_basics/rules/rust.yml +++ b/socket_basics/rules/rust.yml @@ -22,12 +22,12 @@ rules: message: "Command injection vulnerability detected" severity: CRITICAL languages: [rust] - pattern-either: - - pattern: std::process::Command::new($CMD + $USER_INPUT) - - pattern: Command::new($CMD + $USER_INPUT) - - pattern: std::process::Command::new($CMD).arg($USER_INPUT) - - pattern: Command::new($CMD).args(&[$USER_INPUT]) - where: + patterns: + - pattern-either: + - pattern: std::process::Command::new($CMD + $USER_INPUT) + - pattern: Command::new($CMD + $USER_INPUT) + - pattern: std::process::Command::new($CMD).arg($USER_INPUT) + - pattern: Command::new($CMD).args(&[$USER_INPUT]) - metavariable-pattern: metavariable: $USER_INPUT pattern: $VAR @@ -41,11 +41,11 @@ rules: message: "Unsafe deserialization detected" severity: CRITICAL languages: [rust] - pattern-either: - - pattern: serde_pickle::from_slice($USER_INPUT) - - pattern: bincode::deserialize($USER_INPUT) - - pattern: postcard::from_bytes($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: serde_pickle::from_slice($USER_INPUT) + - pattern: bincode::deserialize($USER_INPUT) + - pattern: postcard::from_bytes($USER_INPUT) - metavariable-pattern: metavariable: $USER_INPUT pattern: $VAR @@ -76,14 +76,14 @@ rules: message: "Hardcoded secrets detected" severity: HIGH languages: [rust] - pattern-either: - - pattern: | - const $VAR: &str = "..."; - - pattern: | - static $VAR: &str = "..."; - - pattern: | - let $VAR = "..."; - where: + patterns: + - pattern-either: + - pattern: | + const $VAR: &str = "..."; + - pattern: | + static $VAR: &str = "..."; + - pattern: | + let $VAR = "..."; - metavariable-regex: metavariable: $VAR regex: (?i).*(password|secret|token|key|api_key|apikey|private_key|auth|credential).* @@ -141,12 +141,12 @@ rules: message: "Path traversal vulnerability detected" severity: HIGH languages: [rust] - pattern-either: - - pattern: std::fs::File::open($PATH + $USER_INPUT) - - pattern: std::fs::read_to_string($PATH + $USER_INPUT) - - pattern: std::fs::write($PATH + $USER_INPUT, ...) - - pattern: PathBuf::from($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: std::fs::File::open($PATH + $USER_INPUT) + - pattern: std::fs::read_to_string($PATH + $USER_INPUT) + - pattern: std::fs::write($PATH + $USER_INPUT, ...) + - pattern: PathBuf::from($USER_INPUT) - metavariable-pattern: metavariable: $USER_INPUT pattern: $VAR @@ -251,12 +251,12 @@ rules: message: "Potential integer overflow - consider using checked arithmetic" severity: MEDIUM languages: [rust] - pattern-either: - - pattern: $A + $B - - pattern: $A - $B - - pattern: $A * $B - - pattern: $A / $B - where: + patterns: + - pattern-either: + - pattern: $A + $B + - pattern: $A - $B + - pattern: $A * $B + - pattern: $A / $B - metavariable-pattern: metavariable: $A pattern: usize @@ -275,12 +275,12 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [rust] - pattern-either: - - pattern: println!($FMT, $USER_INPUT) - - pattern: print!($FMT, $USER_INPUT) - - pattern: dbg!($USER_INPUT) - - pattern: eprintln!($FMT, $USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: println!($FMT, $USER_INPUT) + - pattern: print!($FMT, $USER_INPUT) + - pattern: dbg!($USER_INPUT) + - pattern: eprintln!($FMT, $USER_INPUT) - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* @@ -422,11 +422,11 @@ rules: message: "Serde deserialization security issue" severity: HIGH languages: [rust] - pattern-either: - - pattern: serde_json::from_str::<$TYPE>($USER_INPUT) - - pattern: serde_yaml::from_str::<$TYPE>($USER_INPUT) - - pattern: toml::from_str::<$TYPE>($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: serde_json::from_str::<$TYPE>($USER_INPUT) + - pattern: serde_yaml::from_str::<$TYPE>($USER_INPUT) + - pattern: toml::from_str::<$TYPE>($USER_INPUT) - metavariable-pattern: metavariable: $USER_INPUT pattern: $VAR @@ -471,11 +471,11 @@ rules: message: "Environment variable injection potential" severity: MEDIUM languages: [rust] - pattern-either: - - pattern: std::env::var($USER_INPUT) - - pattern: env::var($USER_INPUT) - - pattern: std::env::set_var($USER_INPUT, $VALUE) - where: + patterns: + - pattern-either: + - pattern: std::env::var($USER_INPUT) + - pattern: env::var($USER_INPUT) + - pattern: std::env::set_var($USER_INPUT, $VALUE) - metavariable-pattern: metavariable: $USER_INPUT pattern: $VAR diff --git a/socket_basics/rules/scala.yml b/socket_basics/rules/scala.yml index 005a8d3..79e2789 100644 --- a/socket_basics/rules/scala.yml +++ b/socket_basics/rules/scala.yml @@ -16,6 +16,31 @@ rules: cwe: CWE-89 confidence: high + # Zip Slip / Path Traversal in ZIP extraction + - id: scala-zip-slip + message: "Zip Slip vulnerability - ZIP extraction without path validation" + severity: CRITICAL + languages: [scala] + pattern-either: + - pattern: $ZIP.extractAll(...) + - pattern: new ZipFile(...).extractAll(...) + - pattern: | + val $ZIP = new ZipFile(...) + ... + $ZIP.extractAll(...) + pattern-not-inside: | + ... + if ($ENTRY.getName().contains("..")) { + ... + } + ... + metadata: + category: security + cwe: CWE-22 + confidence: high + references: + - https://snyk.io/research/zip-slip-vulnerability + # Code injection via eval or compilation - id: scala-code-injection message: "Code injection via eval or compilation" @@ -36,11 +61,19 @@ rules: message: "Command injection vulnerability detected" severity: CRITICAL languages: [scala] - pattern-either: - - pattern: Runtime.getRuntime().exec($CMD + $USER_INPUT) - - pattern: ProcessBuilder($CMD + $USER_INPUT) - - pattern: sys.process.Process($CMD + $USER_INPUT) - - pattern: $CMD.!($USER_INPUT) + patterns: + - pattern-either: + - pattern: Runtime.getRuntime().exec($CMD + $USER_INPUT) + - pattern: ProcessBuilder($CMD + $USER_INPUT) + - pattern: sys.process.Process($CMD + $USER_INPUT) + - pattern: $CMD.! + - pattern: $CMD.!! + - pattern: Seq($SH, "-c", $CMD).! + - pattern: Seq($SH, "-c", $CMD).!! + - pattern-not: '"...".!' + - pattern-not: '"...".!!' + - pattern-not: 'Seq($SH, "-c", "...").!' + - pattern-not: 'Seq($SH, "-c", "...").!!' metadata: category: security cwe: CWE-78 @@ -67,16 +100,16 @@ rules: message: "Hardcoded secrets detected" severity: HIGH languages: [scala] - pattern-either: - - pattern: | - val $VAR = "..." - - pattern: | - var $VAR = "..." - - pattern: | - final val $VAR = "..." - - pattern: | - private val $VAR = "..." - where: + patterns: + - pattern-either: + - pattern: | + val $VAR = "..." + - pattern: | + var $VAR = "..." + - pattern: | + final val $VAR = "..." + - pattern: | + private val $VAR = "..." - metavariable-regex: metavariable: $VAR regex: (?i).*(password|secret|token|key|api_key|apikey|private_key|auth).* @@ -227,12 +260,12 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [scala] - pattern-either: - - pattern: println($USER_INPUT) - - pattern: print($USER_INPUT) - - pattern: Console.println($USER_INPUT) - - pattern: System.out.println($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: println($USER_INPUT) + - pattern: print($USER_INPUT) + - pattern: Console.println($USER_INPUT) + - pattern: System.out.println($USER_INPUT) - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* diff --git a/socket_basics/rules/swift.yml b/socket_basics/rules/swift.yml index ca7afb9..5132419 100644 --- a/socket_basics/rules/swift.yml +++ b/socket_basics/rules/swift.yml @@ -50,16 +50,16 @@ rules: message: "Hardcoded secrets detected" severity: HIGH languages: [swift] - pattern-either: - - pattern: | - let $VAR = "..." - - pattern: | - var $VAR = "..." - - pattern: | - private let $VAR = "..." - - pattern: | - static let $VAR = "..." - where: + patterns: + - pattern-either: + - pattern: | + let $VAR = "..." + - pattern: | + var $VAR = "..." + - pattern: | + private let $VAR = "..." + - pattern: | + static let $VAR = "..." - metavariable-regex: metavariable: $VAR regex: (?i).*(password|secret|token|key|apiKey|api_key|privateKey|private_key|auth|credential).* @@ -163,10 +163,13 @@ rules: message: "Use of HTTP instead of HTTPS" severity: MEDIUM languages: [swift] - pattern: $URL - metavariable-regex: - metavariable: $URL - regex: "http://.*" + pattern-either: + - pattern: | + URL(string: "http://...") + - pattern: | + URLRequest(url: URL(string: "http://...")) + - pattern: | + let $URL = "http://..." metadata: category: security cwe: CWE-319 @@ -229,12 +232,12 @@ rules: message: "Debug information disclosure detected" severity: LOW languages: [swift] - pattern-either: - - pattern: print($USER_INPUT) - - pattern: NSLog($USER_INPUT) - - pattern: os_log($USER_INPUT, ...) - - pattern: debugPrint($USER_INPUT) - where: + patterns: + - pattern-either: + - pattern: print($USER_INPUT) + - pattern: NSLog($USER_INPUT) + - pattern: os_log($USER_INPUT, ...) + - pattern: debugPrint($USER_INPUT) - metavariable-regex: metavariable: $USER_INPUT regex: (?i).*(password|token|secret|key|credential).* @@ -248,10 +251,15 @@ rules: message: "Hardcoded IP address detected" severity: LOW languages: [swift] - pattern: $IP_ADDRESS - metavariable-regex: - metavariable: $IP_ADDRESS - regex: "(192\\.168\\.\\d{1,3}\\.\\d{1,3})|(10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})|(172\\.16\\.\\d{1,3}\\.\\d{1,3})|127\\.0\\.0\\.1|localhost" + pattern-either: + - pattern: | + let $VAR = "192.168.$X.$Y" + - pattern: | + let $VAR = "10.$X.$Y.$Z" + - pattern: | + let $VAR = "127.0.0.1" + - pattern: | + let $VAR = "localhost" metadata: category: security cwe: CWE-798 @@ -293,11 +301,11 @@ rules: message: "Insecure data storage detected" severity: HIGH languages: [swift] - pattern-either: - - pattern: 'UserDefaults.standard.set($SENSITIVE_DATA, forKey: $...KEY)' - - pattern: 'NSUserDefaults.standard.set($SENSITIVE_DATA, forKey: $...KEY)' - - pattern: '$SENSITIVE_DATA.write(to: URL($...ARGS), atomically: true)' - where: + patterns: + - pattern-either: + - pattern: 'UserDefaults.standard.set($SENSITIVE_DATA, forKey: $...KEY)' + - pattern: 'NSUserDefaults.standard.set($SENSITIVE_DATA, forKey: $...KEY)' + - pattern: '$SENSITIVE_DATA.write(to: URL($...ARGS), atomically: true)' - metavariable-regex: metavariable: $SENSITIVE_DATA regex: (?i).*(password|token|secret|key|credential|credit_card|ssn).* diff --git a/socket_basics/version.py b/socket_basics/version.py index c916e68..edb5a8e 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.21" +__version__ = "1.0.22" From 4f4436a4a748f78c9a523520b9a212cc627b03fb Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Tue, 28 Oct 2025 11:17:07 -0700 Subject: [PATCH 2/2] Updated installation directions --- README.md | 10 ++-- docs/github-action.md | 38 +++++++-------- docs/local-install-docker.md | 70 ++++++++++++++-------------- docs/local-installation.md | 90 +++++++++++++++--------------------- docs/pre-commit-hook.md | 7 ++- pyproject.toml | 2 +- socket_basics/version.py | 2 +- 7 files changed, 101 insertions(+), 118 deletions(-) diff --git a/README.md b/README.md index 5953e44..c957f42 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.22 + uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.22 . +docker build -t socketdev/socket-basics:1.0.23 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.22 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.23 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/docs/github-action.md b/docs/github-action.md index 03b9f37..d09c41b 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.22 + uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.22 +> - uses: SocketDev/socket-basics@1.0.23 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.22 +- uses: SocketDev/socket-basics@1.0.23 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.22 + uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.22 + uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.22:${{ github.sha }} . + run: docker build -t myapp:1.0.23:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.22 + uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.22 + uses: SocketDev/socket-basics@1.0.23 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.22 + - uses: SocketDev/socket-basics@1.0.23 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index d247963..483071d 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.22 . +docker build -t socket-basics:1.0.23 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.22 . +docker build -t socket-basics:1.0.23 . # Or build with latest tag -docker build -t socket-basics:1.0.22:latest . +docker build -t socket-basics:1.0.23:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.22 . +docker build -t myorg/security-scanner:1.0.23 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.22 . +docker build --platform linux/amd64 -t socket-basics:1.0.23 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.22 socket-basics --version -docker run --rm socket-basics:1.0.22 socket --version -docker run --rm socket-basics:1.0.22 trivy --version -docker run --rm socket-basics:1.0.22 semgrep --version -docker run --rm socket-basics:1.0.22 trufflehog --version +docker run --rm socket-basics:1.0.23 socket-basics --version +docker run --rm socket-basics:1.0.23 socket --version +docker run --rm socket-basics:1.0.23 trivy --version +docker run --rm socket-basics:1.0.23 opengrep --version +docker run --rm socket-basics:1.0.23 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.22 + socket-basics:1.0.23 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.22').inside( + docker.image('socket-basics:1.0.23').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.22 + image: socket-basics:1.0.23 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.22 + socket-basics:1.0.23 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.22 + socket-basics:1.0.23 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.22 \ + socket-basics:1.0.23 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.22 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.23 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.22 .' +alias sb-build='docker build -t socket-basics:1.0.23 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.22" +IMAGE_NAME="socket-basics:1.0.23" ENV_FILE=".env" # Create results directory diff --git a/docs/local-installation.md b/docs/local-installation.md index a17dcb8..d08e645 100644 --- a/docs/local-installation.md +++ b/docs/local-installation.md @@ -18,17 +18,22 @@ Complete guide to installing Socket Basics and all security tools for native exe For experienced users on macOS/Linux with Homebrew: ```bash -# Install Socket Basics -pip install socket-basics +# Install Socket Basics (from source) +git clone https://github.com/SocketDev/socket-basics.git +cd socket-basics +pip install -e . # Install security tools -brew install socket trivy semgrep trufflehog +brew install socket trivy trufflehog + +# Install OpenGrep (SAST scanning) +curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh | bash # Verify installation socket-basics --version socket --version trivy --version -semgrep --version +opengrep --version trufflehog --version ``` @@ -99,21 +104,9 @@ curl -LsSf https://astral.sh/uv/install.sh | sh ## Socket Basics Installation -### Method 1: From PyPI (Recommended for Users) - -```bash -# Create and activate virtual environment (recommended) -python -m venv .venv -source .venv/bin/activate # On Windows: .venv\Scripts\activate +### Method 1: From Source (Required - Not on PyPI) -# Install Socket Basics -pip install socket-basics - -# Verify installation -socket-basics --version -``` - -### Method 2: From Source (Recommended for Development) +Socket Basics is not published to PyPI. You must install from source: ```bash # Clone the repository @@ -136,7 +129,7 @@ pip install -e . socket-basics --version ``` -### Method 3: Using uv (Fastest) +### Method 2: Using uv (Faster Alternative) ```bash # Install uv @@ -228,37 +221,28 @@ trivy --version **Documentation:** https://github.com/aquasecurity/trivy -### Semgrep/OpenGrep (SAST) +### OpenGrep (SAST) **Required for:** Static Application Security Testing (SAST) for all languages **Installation:** ```bash -# macOS/Linux with Homebrew: -brew install semgrep +# Install OpenGrep using the official installer: +curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh | bash -# Using pip: -pip install semgrep - -# Using Docker (alternative): -docker pull semgrep/semgrep:latest +# Add to PATH (if not automatically added): +export PATH="$HOME/.opengrep/cli/latest:$PATH" # Verify installation -semgrep --version +opengrep --version ``` **Configuration:** -```bash -# Login to Semgrep (optional, for custom rules): -semgrep login - -# Or run without login using bundled rules -semgrep --config=auto -``` +OpenGrep works with the bundled Socket Basics SAST rules. No additional configuration is required for basic usage. -**Documentation:** https://semgrep.dev/docs/ +**Documentation:** https://github.com/opengrep/opengrep ### TruffleHog (Secret Scanning) @@ -318,9 +302,9 @@ socket cdxgen --help trivy --version trivy image --help -# Test Semgrep -semgrep --version -semgrep --help +# Test OpenGrep +opengrep --version +opengrep --help # Test TruffleHog trufflehog --version @@ -368,11 +352,11 @@ else echo "✅ trivy found: $(trivy --version | head -1)" fi -# Check Semgrep -if ! command -v semgrep &> /dev/null; then - echo "⚠️ semgrep not found (needed for SAST)" +# Check OpenGrep +if ! command -v opengrep &> /dev/null; then + echo "⚠️ opengrep not found (needed for SAST)" else - echo "✅ semgrep found: $(semgrep --version)" + echo "✅ opengrep found: $(opengrep --version)" fi # Check TruffleHog @@ -607,7 +591,7 @@ pip install -e . **Solutions:** ```bash # Check if tool is in PATH -which trivy # or semgrep, trufflehog, socket +which trivy # or opengrep, trufflehog, socket # Add to PATH if needed export PATH="/usr/local/bin:$PATH" @@ -669,20 +653,20 @@ export SOCKET_SECURITY_API_KEY="your-api-key" socket info ``` -### Semgrep/OpenGrep Errors +### OpenGrep Errors -**Problem:** Semgrep crashes or fails +**Problem:** OpenGrep crashes or fails **Solutions:** ```bash -# Update Semgrep -pip install --upgrade semgrep +# Reinstall OpenGrep +curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh | bash -# Clear Semgrep cache -rm -rf ~/.semgrep/cache +# Ensure OpenGrep is in PATH +export PATH="$HOME/.opengrep/cli/latest:$PATH" -# Test Semgrep standalone -semgrep --config=auto --test test_file.py +# Test OpenGrep standalone +opengrep --version ``` ### Python Version Conflicts @@ -694,7 +678,7 @@ semgrep --config=auto --test test_file.py # Always use python3 explicitly python3 -m venv .venv source .venv/bin/activate -python3 -m pip install socket-basics +python3 -m pip install -e . # Or set Python 3 as default alias python=python3 diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 07a586f..77e138c 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.22 . +docker build -t socket-basics:1.0.23 . ``` **2. Create pre-commit hook:** @@ -194,8 +194,7 @@ source .venv/bin/activate # On Windows: .venv\Scripts\activate **Socket Basics:** ```bash -pip install socket-basics -# Or for development: +# Install from source (Socket Basics is not on PyPI) git clone https://github.com/SocketDev/socket-basics.git cd socket-basics pip install -e . @@ -206,7 +205,7 @@ pip install -e . See [Local Installation Guide](local-installation.md) for detailed instructions on installing: - Socket CLI - Trivy -- Semgrep (OpenGrep) +- OpenGrep - TruffleHog ### Setup Steps diff --git a/pyproject.toml b/pyproject.toml index 86484e7..18e95fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.22" +version = "1.0.23" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/version.py b/socket_basics/version.py index edb5a8e..89e4f67 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.22" +__version__ = "1.0.23"