name: Security Audit
on:
push:
branches: [ develop, main ]
pull_request:
branches: [ develop, main ]
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
permissions:
contents: read
security-events: write
actions: read
jobs:
secret-scan:
name: Secret Scanning
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with:
fetch-depth: 0
- name: Gitleaks Secret Scan
run: |
# Use the Gitleaks Docker image to avoid license requirements of the managed GitHub Action
docker run -v ${{ github.workspace }}:/path zricethezav/gitleaks:latest detect --source=/path --verbose --redact
continue-on-error: true
sca-audit:
name: Software Composition Analysis
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b with:
enable-cache: true
python-version: '3.14'
- name: Extract versions and Patch PyProject
run: |
python -c "
import os, re
with open('pyproject.toml', 'r', encoding='utf-8') as f:
content = f.read()
m_match = re.search(r'coreason-manifest[>=]=([0-9]+\.[0-9]+\.[0-9]+)', content)
if not m_match:
print('Failed to extract coreason-manifest version from pyproject.toml')
exit(1)
m_ver = 'v' + m_match.group(1)
# coreason-urn-authority is optional (removed in Rust refactor)
u_match = re.search(r'coreason-urn-authority[>=~]+([0-9]+\.[0-9]+\.[0-9]+)', content)
u_ver = 'v' + u_match.group(1) if u_match else None
github_env = os.environ.get('GITHUB_ENV')
if github_env:
with open(github_env, 'a', encoding='utf-8') as ge:
ge.write(f'MANIFEST_VERSION={m_ver}\n')
if u_ver:
ge.write(f'URN_AUTHORITY_VERSION={u_ver}\n')
content = content.replace('coreason-manifest = { git = \"https://github.com/CoReason-AI/coreason-manifest.git\" }', f'coreason-manifest = {{ git = \"https://github.com/CoReason-AI/coreason-manifest.git\", tag = \"{m_ver}\" }}')
content = content.replace('coreason-manifest = { path = \"../coreason-manifest\" }', f'coreason-manifest = {{ git = \"https://github.com/CoReason-AI/coreason-manifest.git\", tag = \"{m_ver}\" }}')
if u_ver:
content = content.replace('coreason-urn-authority = { git = \"https://github.com/CoReason-AI/coreason-urn-authority.git\" }', f'coreason-urn-authority = {{ git = \"https://github.com/CoReason-AI/coreason-urn-authority.git\", tag = \"{u_ver}\" }}')
content = content.replace('coreason-urn-authority = { path = \"../coreason-urn-authority\" }', f'coreason-urn-authority = {{ git = \"https://github.com/CoReason-AI/coreason-urn-authority.git\", tag = \"{u_ver}\" }}')
content = content.replace('prerelease = \"allow\"', f'prerelease = \"allow\"\noverride-dependencies = [\"coreason-manifest @ git+https://github.com/CoReason-AI/coreason-manifest.git@{m_ver}\"]')
with open('pyproject.toml', 'w', encoding='utf-8') as f:
f.write(content)
"
uv lock
shell: bash
- name: Python SCA Audit (pip-audit)
run: |
if [ -f "pyproject.toml" ]; then
uv export --format requirements-txt > requirements.txt
uv tool run pip-audit -r requirements.txt -f sarif -o pip-audit.sarif || echo "Vulnerabilities found!"
uv tool run pip-audit -r requirements.txt -f html -o pip-audit-report.html || true
fi
shell: bash
- name: Node.js SCA Audit (npm audit)
run: |
if [ -f "package.json" ]; then
npm install --package-lock-only
npm audit --json > npm-audit.json || true
npx @microsoft/npm-audit-sarif -i npm-audit.json -o npm-audit.sarif || true
fi
shell: bash
- name: Black Duck Compliance Check
run: |
echo "INFO: Ready for Black Duck integration."
shell: bash
- name: Upload SARIF Reports to GitHub Advanced Security
uses: github/codeql-action/upload-sarif@3f135f3a928cf93b5749d98d169a49e1d7cf7048 with:
sarif_file: .
continue-on-error: true
- name: Upload Compliance Reports as Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with:
name: security-audit-reports
path: |
pip-audit-report.html
npm-audit.json
retention-days: 14