Skip to content

fix: block RCE via module denylist in YAML config loader #1

fix: block RCE via module denylist in YAML config loader

fix: block RCE via module denylist in YAML config loader #1

# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Continuous Integration
on:
push:
branches: [main, v1]
paths:
- '**.py'
- '.pre-commit-config.yaml'
- 'pyproject.toml'
- 'tests/**'
pull_request:
branches: [main, v1]
paths:
- '**.py'
- '.pre-commit-config.yaml'
- 'pyproject.toml'
- 'tests/**'
permissions:
contents: read
jobs:
# 1. Code format and linting (Linter)
lint:
name: Pre-commit Linter
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: Run pre-commit checks
uses: pre-commit/action@v3.0.1
# 2. Static type analysis (Mypy Check with Matrix)
# Compares new changes against the target base branch dynamically to support v1.
type-check:
name: Mypy Check (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Generate Baseline
env:
TARGET_BRANCH: ${{ github.base_ref || github.ref_name }}
run: |
# Switch to target base branch to generate baseline
git checkout origin/$TARGET_BRANCH
git checkout ${{ github.sha }} -- pyproject.toml
# Install dependencies for target branch
uv venv .venv
source .venv/bin/activate
uv sync --all-extras
# Run mypy, filter for errors only, remove line numbers, and sort
# We ignore exit code (|| true) because we expect errors on baseline
uv run mypy . | grep "error:" | sed 's/:\([0-9]\+\):/::/g' | sort > baseline_errors.txt || true
echo "Found $(wc -l < baseline_errors.txt) errors on $TARGET_BRANCH."
- name: Check PR Branch
run: |
# Switch back to the PR commit
git checkout ${{ github.sha }}
# Re-sync dependencies in case the PR changed them
source .venv/bin/activate
uv sync --all-extras
# Run mypy on PR code, apply same processing
uv run mypy . | grep "error:" | sed 's/:\([0-9]\+\):/::/g' | sort > pr_errors.txt || true
echo "Found $(wc -l < pr_errors.txt) errors on PR branch."
- name: Compare and Fail on New Errors
run: |
# 'comm -13' suppresses unique lines in file1 (baseline) and common lines,
# leaving only lines unique to file2 (PR) -> The new errors.
comm -13 baseline_errors.txt pr_errors.txt > new_errors.txt
if [ -s new_errors.txt ]; then
echo "::error::The following NEW mypy errors were introduced:"
cat new_errors.txt
exit 1
else
echo "Great job! No new mypy errors introduced."
fi
# 3. Unit testing (Unit Tests with Matrix)
unit-test:
name: Unit Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v7
- name: Install dependencies
run: |
uv venv .venv
source .venv/bin/activate
uv sync --extra test
- name: Run unit tests with pytest
run: |
source .venv/bin/activate
pytest tests/unittests \
-n auto \
--ignore=tests/unittests/artifacts/test_artifact_service.py \
--ignore=tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py