diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..96a7a1c3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: / + schedule: + interval: "weekly" + target-branch: "master" + groups: + github-actions-dependency: + applies-to: version-updates + patterns: + - "*" + - package-ecosystem: pip + directory: /src/python + schedule: + interval: weekly + target-branch: "master" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..a9539b87 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,48 @@ +name: "CodeQL Scan" + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + schedule: + - cron: "37 3 * * 0" + +permissions: {} # No permissions by default on workflow level + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + runs-on: ubuntu-latest + permissions: + security-events: write # required to publish sarif + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: python + build-mode: none + - language: c-cpp + build-mode: none + + steps: + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + queries: security-extended + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index af9faac8..aa666c75 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,5 +1,5 @@ name: Build Docs -permissions: read-all +permissions: {} # No permissions by default on workflow level on: workflow_dispatch: # run on request (no need for PR) @@ -14,20 +14,29 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.10" - name: Install dependencies run: pip install 'src/python/.[docs]' - name: Install and Generate Doxygen - uses: mattnotmitt/doxygen-action@v1.12.0 + uses: mattnotmitt/doxygen-action@b84fe17600245bb5db3d6c247cc274ea98c15a3b # v1.12.0 - name: Build Docs run: | cd docs make html + - name: Branch name + id: branch_name + shell: bash + run: | + echo ::set-output name=SOURCE_NAME::${GITHUB_REF#refs/*/} - name: Create gh-pages branch + env: + SOURCE: ${{steps.branch_name.outputs.SOURCE_NAME}} run: | if [[ ${{github.event_name}} == 'workflow_dispatch' ]]; then echo RELEASE_VERSION="test_build" >> $GITHUB_ENV @@ -52,7 +61,7 @@ jobs: git add .nojekyll git commit -m "Initializing gh-pages branch" git push origin gh-pages - git checkout ${{steps.branch_name.outputs.SOURCE_NAME}} + git checkout "${SOURCE}" echo "Created gh-pages branch" else echo "Branch gh-pages already exists" @@ -77,7 +86,7 @@ jobs: git add index.html git commit -m "Update documentation" -a || true - name: Push changes - uses: ad-m/github-push-action@master + uses: ad-m/github-push-action@77c5b412c50b723d2a4fbc6d71fb5723bcd439aa with: github_token: ${{ secrets.GITHUB_TOKEN }} branch: gh-pages diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index df97e0fd..70ba102b 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -1,7 +1,12 @@ +##### +# This workflow is triggered by pull_request_target event. +# Never checkout the PR and run ANY local code on it. +##### + name: "Pull Request Labeler" -permissions: read-all +permissions: {} # No permissions by default on workflow level on: - - pull_request_target + - pull_request_target # zizmor: ignore[dangerous-triggers] jobs: labeler: @@ -10,6 +15,6 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/pre_commit.yml b/.github/workflows/pre_commit.yml index ece1788f..99476058 100644 --- a/.github/workflows/pre_commit.yml +++ b/.github/workflows/pre_commit.yml @@ -1,5 +1,5 @@ name: Pre-Commit Checks -permissions: read-all +permissions: {} # No permissions by default on workflow level on: push: @@ -18,13 +18,15 @@ jobs: runs-on: ubuntu-22.04 steps: - name: CHECKOUT REPOSITORY - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.10" - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 - name: Install clang-format @@ -37,12 +39,47 @@ jobs: runs-on: ubuntu-22.04 steps: - name: CHECKOUT REPOSITORY - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.9" - name: Install dependencies run: pip install 'src/python/.[tests,ovms]' - name: Run python unit tests run: pytest tests/python/unit + Zizmor-Scan-PR: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Run Zizmor scan + uses: open-edge-platform/anomalib/.github/actions/security/zizmor@fadfedd5150eb8cd39dfb659ae9bd0eb1c06720d + with: + scan-scope: "changed" + severity-level: "MEDIUM" + confidence-level: "HIGH" + fail-on-findings: true + Bandit-Scan-PR: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Run Bandit scan + uses: open-edge-platform/anomalib/.github/actions/security/bandit@fadfedd5150eb8cd39dfb659ae9bd0eb1c06720d + with: + scan-scope: "changed" + severity-level: "LOW" + confidence-level: "LOW" + config_file: "src/python/pyproject.toml" + fail-on-findings: true diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 0edf4d04..3b830779 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -5,8 +5,7 @@ on: release: types: [published] -# Declare default permissions as read only. -permissions: read-all +permissions: {} # No permissions by default on workflow level jobs: build: @@ -14,9 +13,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: Set up Python 3.10 - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.10" - name: Install pypa/build @@ -25,14 +26,14 @@ jobs: - name: Build sdist run: | python -m build --sdist src/python/ - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: artifact-sdist path: src/python/dist/*.tar.gz - name: Build wheel run: | python -m build --wheel src/python/ - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: artifact-wheel path: src/python/dist/*.whl @@ -43,9 +44,8 @@ jobs: environment: pypi runs-on: ubuntu-latest permissions: - packages: write - contents: write - id-token: write + contents: write # required by svenstaro/upload-release-action + id-token: write # required by trusted publisher steps: - name: Download artifacts uses: actions/download-artifact@v4 @@ -56,13 +56,13 @@ jobs: # to determine where to publish the package distribution to PyPI or TestPyPI - name: Check tag id: check-tag - uses: actions-ecosystem/action-regex-match@v2 + uses: actions-ecosystem/action-regex-match@9e6c4fb3d5e898f505be7a1fb6e7b0a278f6665b # v2.0.2 with: text: ${{ github.ref }} regex: '^refs/tags/[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)+(\.[0-9]+rc[0-9]+|rc[0-9]+)?$' - name: Upload package distributions to github if: ${{ steps.check-tag.outputs.match != '' }} - uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # v2 + uses: svenstaro/upload-release-action@ebd922b779f285dafcac6410a0710daee9c12b82 # v2.10.0 with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: dist/* @@ -71,10 +71,10 @@ jobs: file_glob: true - name: Publish package distributions to PyPI if: ${{ steps.check-tag.outputs.match != '' }} - uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.3 + uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 - name: Publish package distributions to TestPyPI if: ${{ steps.check-tag.outputs.match == '' }} - uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.3 + uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 with: repository-url: https://test.pypi.org/legacy/ verbose: true diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml new file mode 100644 index 00000000..ee48ca7f --- /dev/null +++ b/.github/workflows/scorecards.yml @@ -0,0 +1,40 @@ +name: Scorecards supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + schedule: + # Run security checks every day at 2 AM UTC + - cron: "0 2 * * *" + workflow_dispatch: + +permissions: {} + +jobs: + analysis: + name: Scorecards analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard + security-events: write + # Needed to publish results and get a badge + id-token: write + + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + # Upload the results to GitHub's code scanning dashboard + - name: Upload to code-scanning + uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 + with: + sarif_file: results.sarif diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml new file mode 100644 index 00000000..5b2ea46e --- /dev/null +++ b/.github/workflows/security-scan.yml @@ -0,0 +1,83 @@ +name: Security Scans + +on: + schedule: + # Run security checks every day at 2 AM UTC + - cron: "0 2 * * *" + workflow_dispatch: + push: + branches: + - master + - release** + +permissions: {} + +jobs: + zizmor-scan: + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write # Needed to upload the results to code-scanning dashboard + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Run Zizmor scan + uses: open-edge-platform/anomalib/.github/actions/security/zizmor@fadfedd5150eb8cd39dfb659ae9bd0eb1c06720d + with: + scan-scope: "all" + severity-level: "LOW" + confidence-level: "LOW" + fail-on-findings: false # reports only + + bandit-scan: + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write # Needed to upload the results to code-scanning dashboard + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Run Bandit scan + uses: open-edge-platform/anomalib/.github/actions/security/bandit@fadfedd5150eb8cd39dfb659ae9bd0eb1c06720d + with: + scan-scope: "all" + severity-level: "LOW" + confidence-level: "LOW" + config_file: "src/python/pyproject.toml" + fail-on-findings: false # reports only + + trivy-scan: + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write # Needed to upload the results to code-scanning dashboard + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.10" + - name: Install pip-tools + run: python -m pip install pip-tools + + - name: Freeze dependencies + run: pip-compile --extra=full -o requirements.txt src/python/pyproject.toml + + - name: Run Trivy scan + id: trivy + uses: open-edge-platform/anomalib/.github/actions/security/trivy@fadfedd5150eb8cd39dfb659ae9bd0eb1c06720d + with: + scan_type: "fs" + scan-scope: all + severity: LOW + scanners: "vuln,secret,config" + format: "sarif" + timeout: "15m" + ignore_unfixed: "false" diff --git a/.github/workflows/test_accuracy.yml b/.github/workflows/test_accuracy.yml index 0ce9dc10..74f16cee 100644 --- a/.github/workflows/test_accuracy.yml +++ b/.github/workflows/test_accuracy.yml @@ -1,5 +1,5 @@ name: test_accuracy -permissions: read-all +permissions: {} # No permissions by default on workflow level on: pull_request: merge_group: @@ -12,8 +12,10 @@ jobs: test_accuracy: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.12" cache: pip diff --git a/.github/workflows/test_precommit.yml b/.github/workflows/test_precommit.yml index 5ae39dcb..b5a8a675 100644 --- a/.github/workflows/test_precommit.yml +++ b/.github/workflows/test_precommit.yml @@ -1,5 +1,5 @@ name: test_precommit -permissions: read-all +permissions: {} # No permissions by default on workflow level on: pull_request: merge_group: @@ -13,9 +13,11 @@ jobs: runs-on: ubuntu-22.04 steps: - name: CHECKOUT REPOSITORY - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: 3.9 cache: pip @@ -40,9 +42,11 @@ jobs: name: CPP-Code-Quality runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: cppcheck - uses: chmorgan/cppcheck-action@main + uses: chmorgan/cppcheck-action@88696b3fd4a3ced3df76a2f7dc44b251d8232bcb # v1.4 with: github_token: ${{ secrets.GITHUB_TOKEN}} # missingInclude: cppcheck can't find stl, openvino, opencv @@ -50,8 +54,10 @@ jobs: CPP-Precommit: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.10" cache: pip @@ -83,8 +89,10 @@ jobs: CPP-Windows-Precommit: runs-on: windows-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: 3.9 cache: pip @@ -138,8 +146,10 @@ jobs: run: | brew install colima docker colima start - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ matrix.python-version }} cache: pip diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 84949ee2..63f95eaf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,3 +46,26 @@ repos: hooks: - id: clang-format args: [--style=file, --version=13] + + # zizmor detects security issues in GitHub Actions workflows. + - repo: https://github.com/woodruffw/zizmor-pre-commit + rev: v1.9.0 + hooks: + - id: zizmor + args: ["--min-severity", "medium", "--min-confidence", "high"] + + # add bandit for security checks + - repo: https://github.com/PyCQA/bandit + rev: 1.8.3 + hooks: + - id: bandit + args: + [ + "-c", + "src/python/pyproject.toml", + "--severity-level", + "all", + "--confidence-level", + "all", + ] + additional_dependencies: ["bandit[toml]"] diff --git a/README.md b/README.md index 25f654d1..3d33d80f 100644 --- a/README.md +++ b/README.md @@ -53,13 +53,14 @@ Training Extensions embed all the metadata required for inference into model fil ``` - Build library: - - Create `build` folder and navigate into it: + ```bash mkdir build && cd build ``` + - Run cmake: ```bash diff --git a/examples/cpp/asynchronous_api/README.md b/examples/cpp/asynchronous_api/README.md index 88e44483..475f760b 100644 --- a/examples/cpp/asynchronous_api/README.md +++ b/examples/cpp/asynchronous_api/README.md @@ -18,19 +18,22 @@ This example demonstrates how to use a C++ API of OpenVINO Model API for asynchr ``` - Build example: - - Create `build` folder and navigate into it: + ```bash mkdir build && cd build ``` + - Run cmake: + ```bash cmake ../ ``` + - Build: ```bash diff --git a/examples/cpp/synchronous_api/README.md b/examples/cpp/synchronous_api/README.md index d391467f..8b5b196a 100644 --- a/examples/cpp/synchronous_api/README.md +++ b/examples/cpp/synchronous_api/README.md @@ -16,24 +16,29 @@ This example demonstrates how to use a C++ API of OpenVINO Model API for synchro ``` - Build example: - - Create `build` folder and navigate into it: + ```bash mkdir build && cd build ``` - - Run cmake: + - ```bash - cmake ../ - ``` +- Run cmake: + - - Build: +```bash +cmake ../ +``` - ```bash - make -j - ``` + + +- Build: + +```bash +make -j +``` - Download a model by running a Python code with Model API, see Python [example](../../python/synchronous_api/README.md): diff --git a/src/python/model_api/visualizer/scene/segmentation/instance_segmentation.py b/src/python/model_api/visualizer/scene/segmentation/instance_segmentation.py index f3dbcc8a..9a2f8033 100644 --- a/src/python/model_api/visualizer/scene/segmentation/instance_segmentation.py +++ b/src/python/model_api/visualizer/scene/segmentation/instance_segmentation.py @@ -20,7 +20,7 @@ class InstanceSegmentationScene(Scene): def __init__(self, image: Image, result: InstanceSegmentationResult, layout: Union[Layout, None] = None) -> None: # nosec as random is used for color generation - self.color_per_label = {label: f"#{random.randint(0, 0xFFFFFF):06x}" for label in set(result.label_names)} # noqa: S311 + self.color_per_label = {label: f"#{random.randint(0, 0xFFFFFF):06x}" for label in set(result.label_names)} # noqa: S311 # nosec B311 super().__init__( base=image, label=self._get_labels(result), diff --git a/src/python/pyproject.toml b/src/python/pyproject.toml index 84695158..f5a9a32f 100644 --- a/src/python/pyproject.toml +++ b/src/python/pyproject.toml @@ -248,3 +248,7 @@ notice-rgx = """ # Copyright \\(C\\) (\\d{4}(-\\d{4})?) Intel Corporation # SPDX-License-Identifier: Apache-2\\.0 """ +[tool.bandit] +exclude_dirs = ["tests"] +tests = ["B301","B302","B303","B304","B305","B306","B308","B310","B311","B312","B313","B314","B315","B316","B317","B318","B319","B321","B323","B324","B401","B402","B403","B404","B405","B406","B407","B408","B409","B411","B412","B413"] +skips = ["B101","B102","B103","B104","B105","B106","B107","B108","B110","B112","B201","B501","B502","B503","B504","B505","B506","B507","B601","B602","B603","B604","B605","B606","B607","B608","B609","B610","B611","B701","B702","B703"]