From bee0668cd0981df475b958469bf78d22bcd0e9d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Mon, 9 Dec 2024 21:47:28 +0100 Subject: [PATCH] Add tests and update expected results --- .../.github/actions/action6/action.yml | 251 +++++++++++++++++ .../.github/actions/action7/action.yml | 252 ++++++++++++++++++ .../CWE-094/.github/workflows/test28.yml | 34 +++ .../CWE-094/CodeInjectionCritical.expected | 9 + .../CWE-094/CodeInjectionMedium.expected | 15 ++ .../UntrustedCheckoutCritical.expected | 4 - 6 files changed, 561 insertions(+), 4 deletions(-) create mode 100644 ql/test/query-tests/Security/CWE-094/.github/actions/action6/action.yml create mode 100644 ql/test/query-tests/Security/CWE-094/.github/actions/action7/action.yml create mode 100644 ql/test/query-tests/Security/CWE-094/.github/workflows/test28.yml diff --git a/ql/test/query-tests/Security/CWE-094/.github/actions/action6/action.yml b/ql/test/query-tests/Security/CWE-094/.github/actions/action6/action.yml new file mode 100644 index 00000000000..0048a4ca31e --- /dev/null +++ b/ql/test/query-tests/Security/CWE-094/.github/actions/action6/action.yml @@ -0,0 +1,251 @@ +# Ultralytics Actions 🚀, AGPL-3.0 License https://ultralytics.com/license + +name: "Ultralytics Actions" +author: "Ultralytics" +description: "Optimize code and docs with official Ultralytics Actions for syntax, spelling, and link checks." +branding: + icon: "code" + color: "blue" +inputs: + token: + description: "GitHub token" + required: true + labels: + description: "Run issue and PR auto-labeling" + required: false + default: "false" + python: + description: "Run Python formatting" + required: false + default: "false" + markdown: + description: "Run Markdown formatting (deprecated in favor of prettier)" + required: false + default: "false" + prettier: + description: "Run Prettier formatting for JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, HTML, JSON, GraphQL, Markdown, YAML" + required: false + default: "false" + swift: + description: "Run Swift formatting" + required: false + default: "false" + spelling: + description: "Run Spelling checks" + required: false + default: "false" + links: + description: "Run Broken Links checks" + required: false + default: "false" + summary: + description: "Run PR Summary" + required: false + default: "false" + openai_api_key: + description: "OpenAI API Key" + required: false + openai_model: + description: "OpenAI Model" + required: false + default: "gpt-4o" + first_issue_response: + description: "Example response to a new issue" + required: false + first_pr_response: + description: "Example response to a new PR" + required: false + github_username: + description: "GitHub username for commits" + required: false + default: "UltralyticsAssistant" + github_email: + description: "GitHub email for commits" + required: false + default: "web@ultralytics.com" +runs: + using: "composite" + steps: + - uses: astral-sh/setup-uv@v3 + - name: Install Dependencies + # Note tomli required for codespell with pyproject.toml + # For debug: + # python -m pip install --upgrade pip wheel + # pip install -q git+https://github.com/ultralytics/actions@main codespell tomli + run: | + packages="ultralytics-actions" + if [ "${{ inputs.spelling }}" = "true" ]; then + packages="$packages codespell tomli" + fi + + # On macOS, don't use sudo as it can cause environment issues + if [ "$(uname)" = "Darwin" ]; then + pip install -q $packages + else + sudo env "PATH=$PATH" uv pip install --system $packages + fi + + ultralytics-actions-info + shell: bash + + # Checkout Repository ---------------------------------------------------------------------------------------------- + - name: Checkout Repository + if: github.event.action != 'closed' + uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} + token: ${{ inputs.token }} + ref: ${{ github.head_ref || github.ref }} + fetch-depth: 0 + + # PR Summary ------------------------------------------------------------------------------------------------------- + - name: PR Summary + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && inputs.summary == 'true' && github.event.action != 'synchronize' + env: + GITHUB_TOKEN: ${{ inputs.token }} + OPENAI_API_KEY: ${{ inputs.openai_api_key }} + OPENAI_MODEL: ${{ inputs.openai_model }} + run: | + ultralytics-actions-summarize-pr + shell: bash + continue-on-error: true + + # Python formatting ------------------------------------------------------------------------------------------------ + # Ignores the following Docs rules to match Google-style docstrings: + # D100: Missing docstring in public module + # D104: Missing docstring in public package + # D203: 1 blank line required before class docstring + # D205: 1 blank line required between summary line and description + # D212: Multi-line docstring summary should start at the first line + # D213: Multi-line docstring summary should start at the second line + # D401: First line of docstring should be in imperative mood + # D406: Section name should end with a newline + # D407: Missing dashed underline after section + # D413: Missing blank line after last section + # --target-version is Python 3.8 for --extend-select UP (pyupgrade) + - name: Run Python + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && inputs.python == 'true' && github.event.action != 'closed' + run: | + ruff format \ + --line-length 120 \ + . || true + ruff check \ + --fix \ + --unsafe-fixes \ + --extend-select I,D,UP \ + --target-version py38 \ + --ignore D100,D104,D203,D205,D212,D213,D401,D406,D407,D413 \ + . || true + docformatter \ + --wrap-summaries 120 \ + --wrap-descriptions 120 \ + --pre-summary-newline \ + --close-quotes-on-newline \ + --in-place \ + --recursive \ + . + shell: bash + continue-on-error: true + + # Prettier (JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, HTML, JSON, GraphQL, Markdown, YAML) ------------- + - name: Run Prettier + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && (inputs.prettier == 'true' || inputs.markdown == 'true') && github.event.action != 'closed' + run: | + ultralytics-actions-update-markdown-code-blocks + npm install --global prettier + npx prettier --write "**/*.{js,jsx,ts,tsx,css,less,scss,json,yml,yaml,html,vue,svelte}" '!**/*lock.{json,yaml,yml}' '!**/*.lock' '!**/model.json' + # Handle Markdown separately + find . -name "*.md" ! -path "*/docs/*" -exec npx prettier --write {} + + if [ -d "./docs" ]; then + find ./docs -name "*.md" ! -path "*/reference/*" -exec npx prettier --tab-width 4 --write {} + + fi + shell: bash + continue-on-error: true + + # - name: Fix MkDocs reference section changes + # if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && (inputs.prettier == 'true' || inputs.markdown == 'true') && github.event.action != 'closed' + # run: | + # from pathlib import Path + # for file in Path("./docs").rglob('*.md'): + # content = file.read_text() + # updated_content = content.replace(".\_","._") + # file.write_text(updated_content) + # shell: python + # continue-on-error: true + + # Swift formatting ------------------------------------------------------------------------------------------------- + - name: Run Swift Formatter + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && inputs.swift == 'true' && github.event.action != 'closed' + run: | + brew install swift-format + swift-format --in-place --recursive . + shell: bash + continue-on-error: true + + # Spelling --------------------------------------------------------------------------------------------------------- + - name: Run Codespell + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && inputs.spelling == 'true' && github.event.action != 'closed' + run: | + codespell \ + --write-changes \ + --ignore-words-list "crate,nd,ned,strack,dota,ane,segway,fo,gool,winn,commend,bloc,nam,afterall,skelton,goin" \ + --skip "*.pt,*.pth,*.torchscript,*.onnx,*.tflite,*.pb,*.bin,*.param,*.mlmodel,*.engine,*.npy,*.data*,*.csv,*pnnx*,*venv*,*translat*,*lock*,__pycache__*,*.ico,*.jpg,*.png,*.mp4,*.mov,/runs,/.git,./docs/??/*.md,./docs/mkdocs_??.yml" + shell: bash + continue-on-error: true + + # Autolabel Issues and PRs (run before commit changes in case commit fails) ---------------------------------------- + - name: Autolabel Issues and PRs + if: inputs.labels == 'true' && (github.event.action == 'opened' || github.event.action == 'created') + env: + GITHUB_TOKEN: ${{ inputs.token }} + FIRST_ISSUE_RESPONSE: ${{ inputs.first_issue_response }} + FIRST_PR_RESPONSE: ${{ inputs.first_pr_response }} + OPENAI_API_KEY: ${{ inputs.openai_api_key }} + OPENAI_MODEL: ${{ inputs.openai_model }} + run: | + ultralytics-actions-first-interaction + shell: bash + continue-on-error: true + + # Commit Changes --------------------------------------------------------------------------------------------------- + - name: Commit and Push Changes + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.action != 'closed' + run: | + git config --global user.name "${{ inputs.github_username }}" + git config --global user.email "${{ inputs.github_email }}" + git pull origin ${{ github.head_ref || github.ref }} + git add . + git reset HEAD -- .github/workflows/ # workflow changes are not permitted with default token + if ! git diff --staged --quiet; then + git commit -m "Auto-format by https://ultralytics.com/actions" + git push + else + echo "No changes to commit" + fi + shell: bash + continue-on-error: false + + # Broken links ----------------------------------------------------------------------------------------------------- + - name: Broken Link Checker + if: inputs.links == 'true' && github.event.action != 'closed' + uses: lycheeverse/lychee-action@v2.0.2 + with: + # Check all markdown and html files in repo. Ignores the following status codes to reduce false positives: + # - 403(OpenVINO, "forbidden") + # - 429(Instagram, "too many requests") + # - 500(Zenodo, "cached") + # - 502(Zenodo, "bad gateway") + # - 999(LinkedIn, "unknown status code") + args: | + --scheme https + --timeout 60 + --insecure + --accept 403,429,500,502,999 + --exclude-all-private + --exclude "https?://(www\.)?(github\.com|linkedin\.com|twitter\.com|instagram\.com|kaggle\.com|fonts\.gstatic\.com|url\.com)" + "./**/*.md" + "./**/*.html" + token: ${{ inputs.token }} + output: ../lychee/results.md + fail: true + continue-on-error: false diff --git a/ql/test/query-tests/Security/CWE-094/.github/actions/action7/action.yml b/ql/test/query-tests/Security/CWE-094/.github/actions/action7/action.yml new file mode 100644 index 00000000000..8bffcdc4020 --- /dev/null +++ b/ql/test/query-tests/Security/CWE-094/.github/actions/action7/action.yml @@ -0,0 +1,252 @@ +# Ultralytics Actions 🚀, AGPL-3.0 License https://ultralytics.com/license + +name: "Ultralytics Actions" +author: "Ultralytics" +description: "Optimize code and docs with official Ultralytics Actions for syntax, spelling, and link checks." +branding: + icon: "code" + color: "blue" +inputs: + token: + description: "GitHub token" + required: true + labels: + description: "Run issue and PR auto-labeling" + required: false + default: "false" + python: + description: "Run Python formatting" + required: false + default: "false" + markdown: + description: "Run Markdown formatting (deprecated in favor of prettier)" + required: false + default: "false" + prettier: + description: "Run Prettier formatting for JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, HTML, JSON, GraphQL, Markdown, YAML" + required: false + default: "false" + swift: + description: "Run Swift formatting" + required: false + default: "false" + spelling: + description: "Run Spelling checks" + required: false + default: "false" + links: + description: "Run Broken Links checks" + required: false + default: "false" + summary: + description: "Run PR Summary" + required: false + default: "false" + openai_api_key: + description: "OpenAI API Key" + required: false + openai_model: + description: "OpenAI Model" + required: false + default: "gpt-4o" + first_issue_response: + description: "Example response to a new issue" + required: false + first_pr_response: + description: "Example response to a new PR" + required: false + github_username: + description: "GitHub username for commits" + required: false + default: "UltralyticsAssistant" + github_email: + description: "GitHub email for commits" + required: false + default: "web@ultralytics.com" +runs: + using: "composite" + steps: + - uses: astral-sh/setup-uv@v3 + - name: Install Dependencies + # Note tomli required for codespell with pyproject.toml + # For debug: + # python -m pip install --upgrade pip wheel + # pip install -q git+https://github.com/ultralytics/actions@main codespell tomli + run: | + packages="ultralytics-actions" + if [ "${{ inputs.spelling }}" = "true" ]; then + packages="$packages codespell tomli" + fi + + # On macOS, don't use sudo as it can cause environment issues + if [ "$(uname)" = "Darwin" ]; then + pip install -q $packages + else + sudo env "PATH=$PATH" uv pip install --system $packages + fi + + ultralytics-actions-info + shell: bash + + # Checkout Repository ---------------------------------------------------------------------------------------------- + - name: Checkout Repository + if: github.event.action != 'closed' + uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} + token: ${{ inputs.token }} + ref: ${{ github.head_ref || github.ref }} + fetch-depth: 0 + + # PR Summary ------------------------------------------------------------------------------------------------------- + - name: PR Summary + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && inputs.summary == 'true' && github.event.action != 'synchronize' + env: + GITHUB_TOKEN: ${{ inputs.token }} + OPENAI_API_KEY: ${{ inputs.openai_api_key }} + OPENAI_MODEL: ${{ inputs.openai_model }} + run: | + ultralytics-actions-summarize-pr + shell: bash + continue-on-error: true + + # Python formatting ------------------------------------------------------------------------------------------------ + # Ignores the following Docs rules to match Google-style docstrings: + # D100: Missing docstring in public module + # D104: Missing docstring in public package + # D203: 1 blank line required before class docstring + # D205: 1 blank line required between summary line and description + # D212: Multi-line docstring summary should start at the first line + # D213: Multi-line docstring summary should start at the second line + # D401: First line of docstring should be in imperative mood + # D406: Section name should end with a newline + # D407: Missing dashed underline after section + # D413: Missing blank line after last section + # --target-version is Python 3.8 for --extend-select UP (pyupgrade) + - name: Run Python + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && inputs.python == 'true' && github.event.action != 'closed' + run: | + ruff format \ + --line-length 120 \ + . || true + ruff check \ + --fix \ + --unsafe-fixes \ + --extend-select I,D,UP \ + --target-version py38 \ + --ignore D100,D104,D203,D205,D212,D213,D401,D406,D407,D413 \ + . || true + docformatter \ + --wrap-summaries 120 \ + --wrap-descriptions 120 \ + --pre-summary-newline \ + --close-quotes-on-newline \ + --in-place \ + --recursive \ + . + shell: bash + continue-on-error: true + + # Prettier (JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, HTML, JSON, GraphQL, Markdown, YAML) ------------- + - name: Run Prettier + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && (inputs.prettier == 'true' || inputs.markdown == 'true') && github.event.action != 'closed' + run: | + ultralytics-actions-update-markdown-code-blocks + npm install --global prettier + npx prettier --write "**/*.{js,jsx,ts,tsx,css,less,scss,json,yml,yaml,html,vue,svelte}" '!**/*lock.{json,yaml,yml}' '!**/*.lock' '!**/model.json' + # Handle Markdown separately + find . -name "*.md" ! -path "*/docs/*" -exec npx prettier --write {} + + if [ -d "./docs" ]; then + find ./docs -name "*.md" ! -path "*/reference/*" -exec npx prettier --tab-width 4 --write {} + + fi + shell: bash + continue-on-error: true + + # - name: Fix MkDocs reference section changes + # if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && (inputs.prettier == 'true' || inputs.markdown == 'true') && github.event.action != 'closed' + # run: | + # from pathlib import Path + # for file in Path("./docs").rglob('*.md'): + # content = file.read_text() + # updated_content = content.replace(".\_","._") + # file.write_text(updated_content) + # shell: python + # continue-on-error: true + + # Swift formatting ------------------------------------------------------------------------------------------------- + - name: Run Swift Formatter + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && inputs.swift == 'true' && github.event.action != 'closed' + run: | + brew install swift-format + swift-format --in-place --recursive . + shell: bash + continue-on-error: true + + # Spelling --------------------------------------------------------------------------------------------------------- + - name: Run Codespell + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && inputs.spelling == 'true' && github.event.action != 'closed' + run: | + codespell \ + --write-changes \ + --ignore-words-list "crate,nd,ned,strack,dota,ane,segway,fo,gool,winn,commend,bloc,nam,afterall,skelton,goin" \ + --skip "*.pt,*.pth,*.torchscript,*.onnx,*.tflite,*.pb,*.bin,*.param,*.mlmodel,*.engine,*.npy,*.data*,*.csv,*pnnx*,*venv*,*translat*,*lock*,__pycache__*,*.ico,*.jpg,*.png,*.mp4,*.mov,/runs,/.git,./docs/??/*.md,./docs/mkdocs_??.yml" + shell: bash + continue-on-error: true + + # Autolabel Issues and PRs (run before commit changes in case commit fails) ---------------------------------------- + - name: Autolabel Issues and PRs + if: inputs.labels == 'true' && (github.event.action == 'opened' || github.event.action == 'created') + env: + GITHUB_TOKEN: ${{ inputs.token }} + FIRST_ISSUE_RESPONSE: ${{ inputs.first_issue_response }} + FIRST_PR_RESPONSE: ${{ inputs.first_pr_response }} + OPENAI_API_KEY: ${{ inputs.openai_api_key }} + OPENAI_MODEL: ${{ inputs.openai_model }} + run: | + ultralytics-actions-first-interaction + shell: bash + continue-on-error: true + + # Commit Changes --------------------------------------------------------------------------------------------------- + - name: Commit and Push Changes + if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.action != 'closed' + run: | + git config --global user.name "${{ inputs.github_username }}" + git config --global user.email "${{ inputs.github_email }}" + # this action is not called in the test + git pull origin ${{ github.head_ref || github.ref }} + git add . + git reset HEAD -- .github/workflows/ # workflow changes are not permitted with default token + if ! git diff --staged --quiet; then + git commit -m "Auto-format by https://ultralytics.com/actions" + git push + else + echo "No changes to commit" + fi + shell: bash + continue-on-error: false + + # Broken links ----------------------------------------------------------------------------------------------------- + - name: Broken Link Checker + if: inputs.links == 'true' && github.event.action != 'closed' + uses: lycheeverse/lychee-action@v2.0.2 + with: + # Check all markdown and html files in repo. Ignores the following status codes to reduce false positives: + # - 403(OpenVINO, "forbidden") + # - 429(Instagram, "too many requests") + # - 500(Zenodo, "cached") + # - 502(Zenodo, "bad gateway") + # - 999(LinkedIn, "unknown status code") + args: | + --scheme https + --timeout 60 + --insecure + --accept 403,429,500,502,999 + --exclude-all-private + --exclude "https?://(www\.)?(github\.com|linkedin\.com|twitter\.com|instagram\.com|kaggle\.com|fonts\.gstatic\.com|url\.com)" + "./**/*.md" + "./**/*.html" + token: ${{ inputs.token }} + output: ../lychee/results.md + fail: true + continue-on-error: false diff --git a/ql/test/query-tests/Security/CWE-094/.github/workflows/test28.yml b/ql/test/query-tests/Security/CWE-094/.github/workflows/test28.yml new file mode 100644 index 00000000000..dbc0137ed5b --- /dev/null +++ b/ql/test/query-tests/Security/CWE-094/.github/workflows/test28.yml @@ -0,0 +1,34 @@ +# Ultralytics 🚀 - AGPL-3.0 License https://ultralytics.com/license +# Ultralytics Actions https://github.com/ultralytics/actions +# This workflow automatically formats code and documentation in PRs to official Ultralytics standards + +name: Ultralytics Actions + +on: + issues: + types: [opened, edited] + discussion: + types: [created] + pull_request_target: + branches: [main] + types: [opened, closed, synchronize, review_requested] + +permissions: + contents: write + +jobs: + format: + runs-on: ubuntu-latest + steps: + - name: Run Ultralytics Formatting + uses: ./.github/actions/action6 + with: + token: ${{ secrets._GITHUB_TOKEN }} # note GITHUB_TOKEN automatically generated + labels: true # autolabel issues and PRs + python: true # format Python code and docstrings + prettier: true # format YAML, JSON, Markdown and CSS + spelling: true # check spelling + links: false # check broken links + summary: true # print PR summary with GPT4o (requires 'openai_api_key') + openai_api_key: ${{ secrets.OPENAI_API_KEY }} + first_issue_response: "foo" diff --git a/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected b/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected index deee6f5202b..b2afe0577aa 100644 --- a/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected +++ b/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected @@ -230,6 +230,8 @@ edges | .github/workflows/untrusted_checkout1.yml:12:14:13:63 | echo "::set-output name=pr_number::$(> $GITHUB_OUTPUT\necho "$fileList" >> $GITHUB_OUTPUT\necho "EOF" >> $GITHUB_OUTPUT\n\ngit push \\\n "https://oauth2:${BOT_PA_TOKEN}@github.com/${{ github.event.workflow_run.head_repository.full_name }}.git" \\\n 'HEAD:refs/heads/${{ github.event.workflow_run.head_branch }}'\n | .github/reusable_workflows/TestOrg/TestRepo/.github/workflows/publishResults.yml:94:30:94:70 | steps.git-commit.outputs.file-list | Potential code injection in $@, which may be controlled by an external user ($@). | .github/reusable_workflows/TestOrg/TestRepo/.github/workflows/publishResults.yml:94:30:94:70 | steps.git-commit.outputs.file-list | ${{ steps.git-commit.outputs.file-list }} | .github/workflows/test22.yml:2:3:2:14 | workflow_run | workflow_run | diff --git a/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected b/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected index e13c2b80a72..605fa2924ff 100644 --- a/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected +++ b/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected @@ -230,6 +230,8 @@ edges | .github/workflows/untrusted_checkout1.yml:12:14:13:63 | echo "::set-output name=pr_number::$(