Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
619 changes: 619 additions & 0 deletions .codespellignore

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,10 @@ BUILD_JOBS=4
# data-driven tests; those tests report FAIL_INVALID_TEST_DATA when their
# fixtures are missing.
OPENCV_TEST_DATA_PATH=

# Android camera stubs root directory. Required only when building the Android
# camera modules (platforms/android/). Point this at a checkout of the Android
# NDK camera stubs (e.g. from the OpenCV Android SDK or a local mirror).
# Leave empty for non-Android builds.
# Example: ANDROID_STUB_ROOT=/opt/android/stubs
ANDROID_STUB_ROOT=
33 changes: 33 additions & 0 deletions .github/codeql/codeql-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# CodeQL configuration for OpenCV C/C++ codebase
#
# This file customizes the CodeQL analysis to focus on security-relevant
# patterns in a computer vision library: memory safety, integer overflows,
# buffer handling, and input validation in file parsers.

name: "OpenCV CodeQL Config"

# Disable default queries and use only security-focused suites
disable-default-queries: true

queries:
# Security-extended: CWE coverage beyond the default suite
- uses: security-extended
# Security-and-quality: adds maintainability/reliability queries
- uses: security-and-quality

# Path filters: exclude generated code, third-party vendored sources,
# and test files from analysis (they add noise and are not our code to fix).
paths-ignore:
- "3rdparty/**"
- "build*/**"
- "**/test/**"
- "**/perf/**"
- "**/samples/**"
- "modules/*/gen/**"
- "platforms/**"
- "*.generated.*"
- "*_generated.*"

# Custom query packs can be added here if needed
# packs:
# - github/codeql-cpp-queries@main
207 changes: 207 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
# read secrets. If a dependency is ever compromised, this limits the blast radius.
permissions:
contents: read
security-events: write # For CodeQL SARIF uploads

# A new push to a PR cancels the previous in-flight run for that ref.
concurrency:
Expand Down Expand Up @@ -113,6 +114,59 @@ jobs:
# stops one hung test from burning the whole 60 minute budget.
run: ctest --test-dir "$BUILD_DIR" --output-on-failure --timeout 900

- name: Run address sanitizer build (fast subset)
# ASan catches memory errors at runtime. We run a quick build with
# a subset of modules to keep the time budget reasonable.
if: github.event_name == 'pull_request'
run: |
cmake -S . -B build-asan -G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \
-DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \
-DCMAKE_LINKER_FLAGS="-fsanitize=address" \
-DBUILD_TESTS=ON \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_EXAMPLES=OFF \
-DBUILD_DOCS=OFF \
-DBUILD_opencv_apps=OFF \
-DBUILD_opencv_java=OFF \
-DBUILD_opencv_python2=OFF \
-DBUILD_opencv_python3=OFF \
-DBUILD_opencv_viz=OFF \
-DBUILD_opencv_videostab=OFF \
-DBUILD_opencv_superres=OFF \
-DBUILD_opencv_cudaarithm=OFF \
-DBUILD_opencv_cudabgsegm=OFF \
-DBUILD_opencv_cudacodec=OFF \
-DBUILD_opencv_cudafeatures2d=OFF \
-DBUILD_opencv_cudafilters=OFF \
-DBUILD_opencv_cudaimgproc=OFF \
-DBUILD_opencv_cudalegacy=OFF \
-DBUILD_opencv_cudaobjdetect=OFF \
-DBUILD_opencv_cudaoptflow=OFF \
-DBUILD_opencv_cudastereo=OFF \
-DBUILD_opencv_cudawarping=OFF \
-DBUILD_opencv_cudev=OFF \
-DBUILD_ZLIB=ON \
-DBUILD_PNG=ON \
-DBUILD_JPEG=ON \
-DBUILD_TIFF=ON \
-DBUILD_OPENEXR=ON \
-DWITH_1394=OFF \
-DWITH_CUDA=OFF \
-DWITH_EIGEN=OFF \
-DWITH_FFMPEG=OFF \
-DWITH_GSTREAMER=OFF \
-DWITH_GTK=OFF \
-DWITH_IPP=OFF \
-DWITH_JASPER=OFF \
-DWITH_OPENCL=OFF \
-DWITH_TBB=OFF \
-DWITH_V4L=OFF \
-DWITH_WEBP=OFF
cmake --build build-asan --parallel "$(nproc)" --target opencv_test_core opencv_test_imgproc opencv_test_imgcodecs
ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 ctest --test-dir build-asan --output-on-failure -R "opencv_test_(core|imgproc|imgcodecs)" --timeout 300

lint:
name: Lint & repository hygiene
runs-on: ubuntu-latest
Expand Down Expand Up @@ -209,3 +263,156 @@ jobs:
- name: pip-audit
# --strict fails on unpinned requirements as well as on advisories.
run: python -m pip_audit --requirement requirements-dev.txt --strict

secret-scan:
name: Secret scanning
# Detect committed secrets, API keys, tokens, and credentials.
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for secret scanning

- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
with:
args: --verbose --no-banner --redact

container-scan:
name: Container vulnerability scan
# Scan the built container image for known vulnerabilities using Trivy.
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build container image (toolchain stage)
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
target: toolchain
load: true
tags: opencv-dev:ci-scan
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: opencv-dev:ci-scan
format: sarif
output: trivy-results.sarif
severity: HIGH,CRITICAL
ignore-unfixed: true
vuln-type: os,library

- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: trivy-results.sarif
category: container-scan

cmake-security:
name: CMake security hardening check
# Verify that security-relevant CMake policies and compiler flags are set.
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- name: Check for security hardening flags in CMake
run: |
set -euo pipefail
echo "Checking for security hardening configurations..."

# Check for FORTIFY_SOURCE
if ! grep -r "FORTIFY_SOURCE" cmake/ CMakeLists.txt 2>/dev/null; then
echo "::warning::FORTIFY_SOURCE not explicitly set in CMake files"
else
echo "✓ FORTIFY_SOURCE found"
fi

# Check for stack protector
if ! grep -r "stack-protector" cmake/ CMakeLists.txt 2>/dev/null; then
echo "::warning::Stack protector not explicitly configured"
else
echo "✓ Stack protector found"
fi

# Check for PIE/PIC
if ! grep -r "POSITION_INDEPENDENT_CODE\|CMAKE_POSITION_INDEPENDENT_CODE" cmake/ CMakeLists.txt 2>/dev/null; then
echo "::warning::Position Independent Code not explicitly enabled"
else
echo "✓ PIE/PIC found"
fi

# Check for RELRO
if ! grep -r "RELRO\|BIND_NOW" cmake/ CMakeLists.txt 2>/dev/null; then
echo "::warning::RELRO/BIND_NOW not explicitly configured"
else
echo "✓ RELRO found"
fi

# Check for format security
if ! grep -r "format-security\|FORMAT_SECURITY" cmake/ CMakeLists.txt 2>/dev/null; then
echo "::warning::Format security not explicitly configured"
else
echo "✓ Format security found"
fi

echo "CMake security hardening check completed (warnings are informational)"

license-check:
name: License compliance
# Verify that all dependencies have acceptable licenses.
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- name: Check Python dependency licenses
run: |
python -m pip install --upgrade pip
python -m pip install pip-licenses
python -m pip install -r requirements-dev.txt
# Check for problematic licenses (GPL, AGPL, etc. in a permissive project)
python -m pip_licenses --format=json --with-urls > licenses.json
python - <<'PY'
import json, sys
with open('licenses.json') as f:
deps = json.load(f)
problematic = ['GPL', 'AGPL', 'LGPL', 'SSPL', 'BSL', 'Commons Clause']
violations = []
for dep in deps:
license_name = dep.get('License', '').upper()
for bad in problematic:
if bad in license_name:
violations.append(f"{dep['Name']} ({dep['Version']}): {dep['License']}")
if violations:
print("::error::Problematic licenses found:")
for v in violations:
print(f" {v}")
sys.exit(1)
else:
print("✓ All Python dependencies have acceptable licenses")
PY

- name: Check vendored third-party licenses
run: |
# Verify 3rdparty/ directories have license files
for dir in 3rdparty/*/; do
if [ -d "$dir" ]; then
name=$(basename "$dir")
if [ ! -f "$dir/LICENSE" ] && [ ! -f "$dir/COPYING" ] && [ ! -f "$dir/license.txt" ] && [ ! -f "$dir/License.txt" ]; then
echo "::warning::3rdparty/$name: No license file found"
else
echo "✓ 3rdparty/$name: License file present"
fi
fi
done
102 changes: 102 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: CodeQL Analysis

# Security-focused static analysis for C/C++ codebase.
# Runs on schedule, on push to default branch, and on pull requests.
# Results appear in the Security tab and as PR annotations.

on:
push:
branches: [master, main]
pull_request:
branches: [master, main]
schedule:
- cron: '0 6 * * 1' # Weekly on Monday 06:00 UTC
workflow_dispatch:

permissions:
contents: read
security-events: write
actions: read

jobs:
analyze:
name: CodeQL C/C++ Analysis
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
language: [cpp]
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# Use the extended query suite for deeper coverage
queries: +security-extended,+security-and-quality
config-file: .github/codeql/codeql-config.yml

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential cmake ninja-build pkg-config

- name: Configure build for CodeQL
# Use the same minimal flag set as CI/Dockerfile so the analysis
# covers the exact code paths that ship.
run: |
cmake -S . -B build-codeql -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTS=OFF \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_EXAMPLES=OFF \
-DBUILD_DOCS=OFF \
-DBUILD_opencv_apps=OFF \
-DBUILD_opencv_java=OFF \
-DBUILD_opencv_python2=OFF \
-DBUILD_opencv_python3=OFF \
-DBUILD_opencv_viz=OFF \
-DBUILD_opencv_videostab=OFF \
-DBUILD_opencv_superres=OFF \
-DBUILD_opencv_cudaarithm=OFF \
-DBUILD_opencv_cudabgsegm=OFF \
-DBUILD_opencv_cudacodec=OFF \
-DBUILD_opencv_cudafeatures2d=OFF \
-DBUILD_opencv_cudafilters=OFF \
-DBUILD_opencv_cudaimgproc=OFF \
-DBUILD_opencv_cudalegacy=OFF \
-DBUILD_opencv_cudaobjdetect=OFF \
-DBUILD_opencv_cudaoptflow=OFF \
-DBUILD_opencv_cudastereo=OFF \
-DBUILD_opencv_cudawarping=OFF \
-DBUILD_opencv_cudev=OFF \
-DBUILD_ZLIB=ON \
-DBUILD_PNG=ON \
-DBUILD_JPEG=ON \
-DBUILD_TIFF=ON \
-DBUILD_OPENEXR=ON \
-DWITH_1394=OFF \
-DWITH_CUDA=OFF \
-DWITH_EIGEN=OFF \
-DWITH_FFMPEG=OFF \
-DWITH_GSTREAMER=OFF \
-DWITH_GTK=OFF \
-DWITH_IPP=OFF \
-DWITH_JASPER=OFF \
-DWITH_OPENCL=OFF \
-DWITH_TBB=OFF \
-DWITH_V4L=OFF \
-DWITH_WEBP=OFF

- name: Build for CodeQL analysis
run: cmake --build build-codeql --parallel "$(nproc)"

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
upload: true
Loading
Loading