diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5a986397..a9181dce 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,19 +1,21 @@ version: 2 updates: - # 1. Keep GitHub Actions up to date - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" + cooldown: + default-days: 7 labels: - "security" - "github-actions" - # 2. Keep Python dependencies up to date - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" + cooldown: + default-days: 7 labels: - "security" - - "python" \ No newline at end of file + - "python" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d087599d..bb5d3a53 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,9 +2,12 @@ name: "CodeQL Security Scan" on: pull_request: - branches: [ "main" ] + branches: [main] schedule: - - cron: '0 12 * * 1' # Runs every Monday at 12:00 UTC + - cron: '0 12 * * 1' + +permissions: + contents: read jobs: analyze: @@ -18,21 +21,21 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'python' ] + language: ['python'] steps: - - name: Checkout repository - uses: actions/checkout@v6 + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false - - name: Initialize CodeQL - uses: github/codeql-action/init@v4 - with: - languages: ${{ matrix.language }} - # If you have specific queries you want to run, you can specify them here. - # "security-extended" adds deeper vulnerability hunting. - queries: security-extended,security-and-quality + - name: Initialize CodeQL + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 + with: + languages: ${{ matrix.language }} + queries: security-extended,security-and-quality - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 - with: - category: "/language:${{matrix.language}}" \ No newline at end of file + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index d1886dd0..97473b84 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -3,21 +3,23 @@ name: Deploy Museum of Code Docs on: push: branches: - - main # Triggers the action when you push to the main branch - workflow_dispatch: # Allows you to manually trigger the build from the GitHub UI + - main + workflow_dispatch: -# Grants the action permission to push the built site to the gh-pages branch permissions: - contents: write + contents: read jobs: deploy: + permissions: + contents: write runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: - fetch-depth: 0 # Required for git info/history (like last updated timestamps) + fetch-depth: 0 + persist-credentials: false - name: Configure Git Credentials run: | @@ -25,13 +27,13 @@ jobs: git config user.email 41898282+github-actions[bot]@users.noreply.github.com - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: - python-version: 3.x + python-version: "3.x" + cache: false - name: Install Dependencies - # Installs Material theme and the PyMdown extensions required by your mkdocs.yml run: pip install mkdocs-material pymdown-extensions - name: Build and Deploy Docs - run: mkdocs gh-deploy --force \ No newline at end of file + run: mkdocs gh-deploy --force diff --git a/.github/workflows/gitgalaxy.yml b/.github/workflows/gitgalaxy.yml index 88faabfa..bcf5d30e 100644 --- a/.github/workflows/gitgalaxy.yml +++ b/.github/workflows/gitgalaxy.yml @@ -2,38 +2,50 @@ name: GitGalaxy Zero-Trust Pipeline on: pull_request: - branches: [ "main" ] + branches: [main] + +permissions: + contents: read jobs: vault-sentinel: name: Vault Sentinel runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: squid-protocol/gitgalaxy@v2.2.6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false + + - uses: squid-protocol/gitgalaxy@c5ae49362540d53bb85809ff4547d2c6feb9deba # v2.2.6 with: - tool: 'vault-sentinel' - target: '.' + tool: vault-sentinel + target: . xray-inspector: name: X-Ray Inspector runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: squid-protocol/gitgalaxy@v2.2.6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false + + - uses: squid-protocol/gitgalaxy@c5ae49362540d53bb85809ff4547d2c6feb9deba # v2.2.6 with: - tool: 'xray-inspector' - target: '.' + tool: xray-inspector + target: . supply-chain-firewall: name: Supply Chain Firewall runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: squid-protocol/gitgalaxy@v2.2.6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: - tool: 'supply-chain-firewall' - target: '.' + persist-credentials: false + + - uses: squid-protocol/gitgalaxy@c5ae49362540d53bb85809ff4547d2c6feb9deba # v2.2.6 + with: + tool: supply-chain-firewall + target: . architectural-report: name: LLM Structural Brief @@ -41,32 +53,28 @@ jobs: runs-on: ubuntu-latest if: github.event_name == 'push' permissions: - contents: write # Critical: Grants the Action permission to push to main + contents: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: fetch-depth: 0 - name: Generate GalaxyScope LLM Brief - uses: squid-protocol/gitgalaxy@v2.2.6 + uses: squid-protocol/gitgalaxy@c5ae49362540d53bb85809ff4547d2c6feb9deba # v2.2.6 with: - tool: 'galaxyscope' - target: '.' - args: '--llm-only' + tool: galaxyscope + target: . + args: --llm-only full_precision: 'true' - name: Commit and Push LLM Brief to Main run: | - # Move the report to the docs folder for clean organization mkdir -p docs mv *_galaxy_llm.md docs/gitgalaxy_architecture_brief.md || true - - # Configure the GitHub Actions bot identity + git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" - - # Stage the file + git add docs/gitgalaxy_architecture_brief.md - - # Only commit and push if there are actual changes to prevent pipeline failures - git diff --quiet && git diff --staged --quiet || (git commit -m "docs: auto-update LLM architectural brief" && git push) \ No newline at end of file + + git diff --quiet && git diff --staged --quiet || (git commit -m "docs: auto-update LLM architectural brief" && git push) diff --git a/.github/workflows/muninn.yml b/.github/workflows/muninn.yml new file mode 100644 index 00000000..2fa8e5ab --- /dev/null +++ b/.github/workflows/muninn.yml @@ -0,0 +1,33 @@ +name: Muninn Security Scan + +on: + pull_request: + push: + branches: [main] + +jobs: + muninn: + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + pull-requests: write + + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false + + - name: Run Muninn + # zizmor: ignore[github_action_from_unverified_creator_used] + uses: skaldlab/muninn@de7174d6a498900ad104cd1e09f0077ac600a588 # v0.3.3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fail-on: info + format: sarif,comment + + - name: Upload SARIF + if: always() && hashFiles('muninn.sarif') != '' + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 + with: + sarif_file: muninn.sarif diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 00584969..cdc813cd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,37 +4,38 @@ on: release: types: [published] +permissions: + contents: read + jobs: pypi-publish: name: Build and Publish to PyPI runs-on: ubuntu-latest - - # This matches the environment name you set in PyPI environment: name: pypi url: https://pypi.org/p/gitgalaxy - - # This specific permission is REQUIRED for Trusted Publishing permissions: id-token: write contents: read steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 # <--- ADD THIS so it downloads your Git tags! - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.10" - - - name: Install build tools - run: python -m pip install --upgrade pip build - - - name: Build the wheel and source distribution - run: python -m build - - - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 \ No newline at end of file + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: "3.10" + cache: false + + - name: Install build tools + run: python -m pip install --upgrade pip build + + - name: Build the wheel and source distribution + run: python -m build + + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index 743743b9..43641095 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -2,63 +2,67 @@ name: GitGalaxy Smoke Tests on: pull_request: - branches: [ "main" ] + branches: [main] + +permissions: + contents: read jobs: smoke-test: runs-on: ${{ matrix.os }} env: - PYTHONUTF8: "1" # <--- FIX 1: Forces Windows to render emojis without crashing + PYTHONUTF8: "1" strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: ["3.9", "3.10", "3.11", "3.12"] - + steps: - - name: Check out repository code - uses: actions/checkout@v6 + - name: Check out repository code + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: ${{ matrix.python-version }} + cache: false - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 - with: - python-version: ${{ matrix.python-version }} + - name: Install macOS dependencies (OpenMP for XGBoost) + if: runner.os == 'macOS' + run: brew install libomp - - name: Install macOS dependencies (OpenMP for XGBoost) - if: runner.os == 'macOS' - run: brew install libomp + - name: Install dependencies + shell: bash + run: | + python -m pip install --upgrade pip setuptools wheel + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install PyYAML networkx tiktoken pandas xgboost pytest flake8 + pip install --no-build-isolation -e . - - name: Install dependencies - shell: bash - run: | - python -m pip install --upgrade pip setuptools wheel - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - pip install PyYAML networkx tiktoken pandas xgboost pytest flake8 - pip install --no-build-isolation -e . # <--- FIX 2: Bypasses the pip build bubble - - - name: Global Syntax Sweep (Flake8) - run: | - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + - name: Global Syntax Sweep (Flake8) + run: | + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - - name: Smoke Test - Core Engine - # Using the -m flag is the safest way to run modules inside a package - run: python -m gitgalaxy.galaxyscope --help + - name: Smoke Test - Core Engine + run: python -m gitgalaxy.galaxyscope --help - - name: Smoke Test - Legacy Refractor Controller - run: python -m gitgalaxy.cobol_refractor_controller --help + - name: Smoke Test - Legacy Refractor Controller + run: python -m gitgalaxy.cobol_refractor_controller --help - - name: Smoke Test - Java Spring Forge Controller - run: python -m gitgalaxy.cobol_to_java_controller --help + - name: Smoke Test - Java Spring Forge Controller + run: python -m gitgalaxy.cobol_to_java_controller --help - - name: Smoke Test - SBOM Generator - run: python -m gitgalaxy.tools.compliance.sbom_generator --help + - name: Smoke Test - SBOM Generator + run: python -m gitgalaxy.tools.compliance.sbom_generator --help - - name: Smoke Test - Supply Chain Firewall - run: python -m gitgalaxy.tools.supply_chain_security.supply_chain_firewall --help + - name: Smoke Test - Supply Chain Firewall + run: python -m gitgalaxy.tools.supply_chain_security.supply_chain_firewall --help - - name: Smoke Test - API Network Map - run: python -m gitgalaxy.tools.network_auditing.full_api_network_map --help + - name: Smoke Test - API Network Map + run: python -m gitgalaxy.tools.network_auditing.full_api_network_map --help - - name: Golden Record Integration Test (Pytest) - run: | - pytest tests/ -v \ No newline at end of file + - name: Golden Record Integration Test (Pytest) + run: pytest tests/ -v diff --git a/.gitignore b/.gitignore index c87ee25a..e00448d9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ .env.* *.pem *.key +muninn.json +muninn.sarif # PYTHON, FLASK & VIRTUAL ENVIRONMENTS __pycache__/ diff --git a/action.yml b/action.yml index 228dd375..6f579a09 100644 --- a/action.yml +++ b/action.yml @@ -32,22 +32,26 @@ runs: using: "composite" steps: - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: '3.10' + cache: false - name: Install GitGalaxy shell: bash + env: + GG_VERSION: ${{ inputs.version }} + GG_FULL_PRECISION: ${{ inputs.full_precision }} run: | - if [ "${{ inputs.version }}" = "latest" ]; then + if [ "$GG_VERSION" = "latest" ]; then echo "Installing latest GitGalaxy from PyPI..." pip install gitgalaxy else - echo "Installing GitGalaxy version ${{ inputs.version }}..." - pip install gitgalaxy==${{ inputs.version }} + echo "Installing GitGalaxy version ${GG_VERSION}..." + pip install "gitgalaxy==${GG_VERSION}" fi - - if [ "${{ inputs.full_precision }}" = "true" ]; then + + if [ "$GG_FULL_PRECISION" = "true" ]; then echo "Unlocking Full Precision Mode..." pip install networkx tiktoken xgboost pandas numpy else @@ -56,6 +60,11 @@ runs: - name: Execute GitGalaxy Tool shell: bash + env: + GG_TOOL: ${{ inputs.tool }} + GG_TARGET: ${{ inputs.target }} + GG_ARGS: ${{ inputs.args }} run: | - echo "Running: ${{ inputs.tool }} ${{ inputs.target }} ${{ inputs.args }}" - ${{ inputs.tool }} ${{ inputs.target }} ${{ inputs.args }} \ No newline at end of file + echo "Running: ${GG_TOOL} ${GG_TARGET} ${GG_ARGS}" + set -- ${GG_TOOL} ${GG_TARGET} ${GG_ARGS} + "$@" diff --git a/muninn.yml b/muninn.yml new file mode 100644 index 00000000..cdfb63a9 --- /dev/null +++ b/muninn.yml @@ -0,0 +1,56 @@ +version: 1 +fail-on: info + +scanners: + gitleaks: + enabled: true + zizmor: + enabled: true + actionlint: + enabled: true + poutine: + enabled: true + semgrep: + enabled: true + rulesets: + - p/security-audit + - p/secrets + osv-scanner: + enabled: true + trivy: + enabled: true + ignore-unfixed: true + checkov: + enabled: true + +suppressions: + - id: tests/fixtures/ + reason: > + Intentional frankenstein test corpus with synthetic vulnerabilities + for security-auditing tool validation. + expires: "" + - id: tests/core_engine/test_licensing.py + rule-id: generic-api-key + reason: Mock enterprise license keys in licensing unit tests. + expires: "" + - id: tests/security_auditing/test_security_lens.py + rule-id: generic-api-key + reason: Intentional malicious sample code for security lens tests. + expires: "" + - id: mkdocs.yml + rule-id: generic-api-key + reason: False positive on navigation label "API Exposure". + expires: "" + - id: .github/workflows/muninn.yml + rule-id: github_action_from_unverified_creator_used + reason: > + Skald Lab Muninn is this project's security scanner; Marketplace + publisher verification is pending. + expires: "" + - id: .github/workflows/gitgalaxy.yml + tool: zizmor + rule-id: artipacked + reason: > + architectural-report job must persist checkout credentials to push + generated docs back to main. + expires: "" diff --git a/zizmor.yml b/zizmor.yml new file mode 100644 index 00000000..3c428f71 --- /dev/null +++ b/zizmor.yml @@ -0,0 +1,5 @@ +rules: + cache-poisoning: + ignore: + # setup-node sets cache: false; zizmor still flags PyPI publish workflows. + - publish.yml