diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 000000000..f2177fb3a --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,45 @@ +# CodeQL configuration for AutoBot +# Declares custom sanitizer functions to reduce false positive alerts. +# See: https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning +# +# Related issue: #1826 + +name: "AutoBot CodeQL Configuration" + +# Model packs that declare custom sanitizers, sources, and sinks +packs: + python: + - codeql/python-queries + +# Data extensions for custom threat models +extensions: + - addsTo: + pack: codeql/python-all + extensible: summaryModel + data: [] + + # --------------------------------------------------------------- + # Path-injection sanitizers + # --------------------------------------------------------------- + - addsTo: + pack: codeql/python-all + extensible: sinkModel + data: [] + + # Declare custom validators as sanitizers via the threat-model + # extensible. Each entry maps a fully-qualified function to a + # sanitizer role for a specific query kind. + +# Paths to scan +paths: + - autobot-backend + - autobot-shared + - autobot-slm-backend + +# Paths to ignore +paths-ignore: + - autobot-frontend/node_modules + - autobot-backend/venv + - "**/__pycache__" + - "**/migrations" + - "**/tests" diff --git a/.github/codeql/extensions/autobot-sanitizers.yml b/.github/codeql/extensions/autobot-sanitizers.yml new file mode 100644 index 000000000..f17e68860 --- /dev/null +++ b/.github/codeql/extensions/autobot-sanitizers.yml @@ -0,0 +1,101 @@ +# CodeQL data extensions for AutoBot custom sanitizer functions. +# These declarations tell CodeQL that certain functions act as +# sanitizers (they validate/sanitize untrusted input), preventing +# false-positive alerts for code paths that pass through them. +# +# Reference: https://codeql.github.com/docs/codeql-cli/using-custom-queries-with-the-codeql-cli/#creating-a-data-extension +# Related issue: #1826 + +extensions: + # ----------------------------------------------------------------- + # Path-injection sanitizers + # ----------------------------------------------------------------- + # autobot_shared.security.path_validator.validate_path() + # Validates and resolves paths, rejects traversal and symlinks. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["autobot_shared.security.path_validator", "Member[validate_path].ReturnValue", "path-injection"] + + # api/files.py _validate_admin_path() + # Restricts paths to allowed admin directories. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["api.files", "Member[_validate_admin_path].ReturnValue", "path-injection"] + + # api/filesystem_mcp.py _validate_file_path() and _validate_directory_path() + # Resolve and constrain file/directory paths to allowed roots. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["api.filesystem_mcp", "Member[_validate_file_path].ReturnValue", "path-injection"] + - ["api.filesystem_mcp", "Member[_validate_directory_path].ReturnValue", "path-injection"] + + # api/codebase_analytics/endpoints/ownership.py _validate_path_security() + # Validates paths against the project root to prevent traversal. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["api.codebase_analytics.endpoints.ownership", "Member[_validate_path_security].ReturnValue", "path-injection"] + + # api/codebase_analytics/endpoints/environment.py _validate_env_path_security() + # Validates environment file paths against the project root. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["api.codebase_analytics.endpoints.environment", "Member[_validate_env_path_security].ReturnValue", "path-injection"] + + # api/analytics_evolution.py _validate_evolution_repo_path() + # Validates repository paths for evolution analytics. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["api.analytics_evolution", "Member[_validate_evolution_repo_path].ReturnValue", "path-injection"] + + # ----------------------------------------------------------------- + # SSRF sanitizer + # ----------------------------------------------------------------- + # autobot_shared.security.input_sanitizer.validate_url() + # Validates URLs against allowlists, rejects internal/private IPs. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["autobot_shared.security.input_sanitizer", "Member[validate_url].ReturnValue", "request-forgery"] + + # ----------------------------------------------------------------- + # LDAP-injection sanitizer + # ----------------------------------------------------------------- + # autobot_shared.security.input_sanitizer.sanitize_ldap_filter() + # Escapes LDAP special characters in filter values. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["autobot_shared.security.input_sanitizer", "Member[sanitize_ldap_filter].ReturnValue", "ldap-injection"] + + # ----------------------------------------------------------------- + # Command-injection sanitizers (Pydantic field validators) + # ----------------------------------------------------------------- + # api/git_mcp.py Pydantic @field_validator decorators on request + # models validate and sanitize file_path, repo_path, commit, and + # ref fields before they reach subprocess calls. + - addsTo: + pack: codeql/python-all + extensible: sanitizerModel + data: + - ["api.git_mcp", "Member[GitLogRequest].Member[file_path]", "command-injection"] + - ["api.git_mcp", "Member[GitLogRequest].Member[repo_path]", "command-injection"] + - ["api.git_mcp", "Member[GitDiffRequest].Member[file_path]", "command-injection"] + - ["api.git_mcp", "Member[GitDiffRequest].Member[commit]", "command-injection"] + - ["api.git_mcp", "Member[GitDiffRequest].Member[repo_path]", "command-injection"] + - ["api.git_mcp", "Member[GitBlameRequest].Member[file_path]", "command-injection"] + - ["api.git_mcp", "Member[GitBlameRequest].Member[repo_path]", "command-injection"] + - ["api.git_mcp", "Member[GitShowRequest].Member[ref]", "command-injection"] diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..c10c443c4 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,51 @@ +# CodeQL Analysis workflow +# Uses custom configuration to declare project-specific sanitizers +# and reduce false-positive security alerts. +# +# Related issue: #1826 + +name: CodeQL Analysis + +on: + push: + branches: [main, Dev_new_gui] + pull_request: + branches: [main, Dev_new_gui] + schedule: + # Run CodeQL analysis weekly on Sundays at 3 AM UTC + - cron: "0 3 * * 0" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + actions: read + contents: read + security-events: write + +jobs: + analyze: + name: Analyze Python + runs-on: self-hosted + timeout-minutes: 30 + + strategy: + fail-fast: false + matrix: + language: [python] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + config-file: .github/codeql/codeql-config.yml + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{ matrix.language }}"