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
38 changes: 0 additions & 38 deletions .github/workflows/scorecard-analysis.yml

This file was deleted.

95 changes: 5 additions & 90 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
name: Security

# Dependency review, Trivy filesystem, OSV, and OpenSSF Scorecard are covered by
# the org-wide CENTRAL required workflows in ContextualWisdomLab/.github.
# CodeQL and Python supply-chain evidence stay repo-local because CodeQL default
# setup is not configured and pip-audit/SBOM evidence is not covered centrally.

on:
push:
branches: [main]
Expand Down Expand Up @@ -42,36 +47,6 @@ jobs:
with:
category: "/language:python"

dependency_review:
name: Dependency review
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
# Keep dependency review intentionally resilient when repository settings disable dependency graph.
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout@v7
with:
persist-credentials: false

- name: Detect dependency graph support
id: dependency_graph_support
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
enabled="$(gh api "repos/${GITHUB_REPOSITORY}" --jq '.security_and_analysis.dependency_graph.enabled // false' || echo false)"
enabled="$(printf '%s' "${enabled}" | tr -d '\r' | tr -d '[:space:]')"
echo "enabled=${enabled}" >> "${GITHUB_OUTPUT}"

- name: Review dependency changes
if: ${{ steps.dependency_graph_support.outputs.enabled == 'true' }}
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # actions/dependency-review-action@v5.0.0
with:
fail-on-severity: high

python_supply_chain:
name: Python supply chain
runs-on: ubuntu-latest
Expand Down Expand Up @@ -105,63 +80,3 @@ jobs:
with:
name: cyclonedx-sbom
path: cyclonedx-sbom.json

trivy_filesystem:
name: Trivy filesystem
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout@v7
with:
persist-credentials: false

- name: Run Trivy filesystem scan
uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # aquasecurity/trivy-action@v0.36.0
with:
scan-type: fs
scan-ref: "."
format: sarif
output: trivy-results.sarif
severity: CRITICAL,HIGH
ignore-unfixed: true
exit-code: "1"

- name: Upload Trivy SARIF
if: ${{ always() && hashFiles('trivy-results.sarif') != '' }}
uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # github/codeql-action/upload-sarif@v4.35.3
with:
sarif_file: trivy-results.sarif
category: trivy-filesystem

scorecard_analysis:
name: OpenSSF Scorecard
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout@v7
with:
persist-credentials: false

- name: Run OpenSSF Scorecard
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # ossf/scorecard-action@v2.4.3
with:
results_format: sarif
results_file: scorecard-results.sarif
publish_results: true

- name: Upload Scorecard SARIF
if: ${{ always() && hashFiles('scorecard-results.sarif') != '' }}
uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # github/codeql-action/upload-sarif@v4.35.3
with:
sarif_file: scorecard-results.sarif
category: openssf-scorecard
31 changes: 20 additions & 11 deletions contextual_orchestrator/orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2885,7 +2885,8 @@ def has_file(path: str) -> bool:
"pyproject.toml",
"requirements.lock",
".github/workflows/security.yml",
".github/workflows/scorecard-analysis.yml",
".github/dependabot.yml",
"ContextualWisdomLab/.github central required security workflows",
],
"repository_artifact",
"ready"
Expand All @@ -2897,11 +2898,11 @@ def has_file(path: str) -> bool:
"pyproject.toml",
"requirements.lock",
".github/workflows/security.yml",
".github/workflows/scorecard-analysis.yml",
".github/dependabot.yml",
)
)
else "blocked",
"License, security policy, package metadata, locked requirements, and security workflows are present.",
"License, security policy, package metadata, locked requirements, local supply-chain workflow, Dependabot metadata, and central required security workflows are present.",
"Restore missing security or package metadata before release-candidate handoff.",
),
self._buyer_evidence_item(
Expand Down Expand Up @@ -3181,7 +3182,13 @@ def has_file(path: str) -> bool:
"item_name": "security_package_metadata",
"label": "Security package metadata",
"owner": "Security reviewer",
"sources": ["SECURITY.md", "requirements.lock", ".github/workflows/security.yml", ".github/workflows/scorecard-analysis.yml"],
"sources": [
"SECURITY.md",
"requirements.lock",
".github/workflows/security.yml",
".github/dependabot.yml",
"ContextualWisdomLab/.github central required security workflows",
],
"evidence_type": "repository_artifact",
"completion_state": "ready"
if all(
Expand All @@ -3190,11 +3197,11 @@ def has_file(path: str) -> bool:
"SECURITY.md",
"requirements.lock",
".github/workflows/security.yml",
".github/workflows/scorecard-analysis.yml",
".github/dependabot.yml",
)
)
else "blocked",
"evidence": "Security policy, locked dependencies, and security workflows are present.",
"evidence": "Security policy, locked dependencies, local supply-chain workflow, Dependabot metadata, and central required security workflows are present.",
"required_input": "Restore missing security metadata before procurement review.",
},
{
Expand Down Expand Up @@ -3996,7 +4003,7 @@ def has_file(path: str) -> bool:
"sources": [
".github/dependabot.yml",
".github/workflows/security.yml",
".github/workflows/scorecard-analysis.yml",
"ContextualWisdomLab/.github central required security workflows",
],
"evidence_type": "repository_artifact",
"completion_state": "ready"
Expand All @@ -4005,11 +4012,10 @@ def has_file(path: str) -> bool:
for path in (
".github/dependabot.yml",
".github/workflows/security.yml",
".github/workflows/scorecard-analysis.yml",
)
)
else "blocked",
"evidence": "Dependabot, CodeQL, dependency review, pip-audit, SBOM, Trivy, and Scorecard workflow metadata are defined.",
"evidence": "Dependabot plus local CodeQL and pip-audit/SBOM workflows are defined; dependency review, Trivy, OSV, and Scorecard are delegated to central required workflows.",
"action": "Attach workflow definitions and latest passing run evidence when the buyer review requests hosted CI proof.",
"exit_criteria": "Buyer can inspect the configured security workflow controls and their latest run status separately.",
},
Expand Down Expand Up @@ -4053,11 +4059,14 @@ def has_file(path: str) -> bool:
"item_name": "vulnerability_scan_evidence",
"label": "Vulnerability scan evidence",
"owner": "Security owner",
"sources": [".github/workflows/security.yml", ".github/workflows/scorecard-analysis.yml"],
"sources": [
".github/workflows/security.yml",
"ContextualWisdomLab/.github central required security workflows",
],
"evidence_type": "external_attestation_required",
"completion_state": "warning",
"source_gap_status": "external_attestation_required",
"evidence": "Security scan workflow metadata exists, but the buyer packet still needs the latest hosted scan result or buyer-accepted equivalent.",
"evidence": "Local supply-chain workflow metadata and central security scan workflow metadata exist, but the buyer packet still needs the latest hosted scan result or buyer-accepted equivalent.",
"action": "Attach latest CodeQL, pip-audit, Trivy, SBOM, and Scorecard results when CI completes or the buyer requests evidence.",
"exit_criteria": "Hosted scan outputs are attached, or the buyer explicitly accepts workflow definitions as sufficient for this stage.",
},
Expand Down
2 changes: 1 addition & 1 deletion docs/commercial_security_attestation.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ creates an extraction trigger.
| Commercial evidence export | `/api/v1/commercial_evidence_exports/latest` | Portable buyer evidence source. |
| Security policy | `SECURITY.md` | Vulnerability reporting and support scope evidence. |
| Dependency and package metadata | `requirements.lock`, `pyproject.toml` | Supply-chain review baseline. |
| Security workflow metadata | `.github/workflows/security.yml`, `.github/workflows/scorecard-analysis.yml`, `.github/dependabot.yml` | CI security controls and dependency update metadata. |
| Security workflow metadata | `.github/workflows/security.yml`, `.github/dependabot.yml`, `ContextualWisdomLab/.github` central required security workflows | Local CodeQL and supply-chain controls, dependency update metadata, and centralized dependency review, Trivy, OSV, and Scorecard governance. |
| Runtime access controls | `contextual_orchestrator/server.py` | Admin/inference auth, trace exposure, rate limit, and concurrency evidence. |

## Runtime Shape
Expand Down
19 changes: 13 additions & 6 deletions tests/test_repository_security_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ def test_security_workflow_covers_core_repository_security_process():
"cron:",
"workflow_dispatch:",
"contents: read",
"ContextualWisdomLab/.github",
"Dependency review, Trivy filesystem, OSV, and OpenSSF Scorecard are covered",
"CodeQL and Python supply-chain evidence stay repo-local",
"security-events: write",
"id-token: write",
"actions/checkout@v7",
"github/codeql-action/init@v4",
"github/codeql-action/analyze@v4",
"actions/dependency-review-action@v5",
"python_supply_chain:",
"actions/setup-python@v6",
"python -m pip install --require-hashes -r requirements-security-ci.txt",
Expand All @@ -47,15 +48,21 @@ def test_security_workflow_covers_core_repository_security_process():
"python -m pip_audit -r requirements.lock",
"cyclonedx-py environment",
"actions/upload-artifact@v5",
"aquasecurity/trivy-action@v0.36.0",
"github/codeql-action/upload-sarif@v4",
"ossf/scorecard-action@v2.4.3",
"publish_results: true",
]

for expected_token in expected_tokens:
assert expected_token in workflow_text

removed_duplicate_scanners = [
"actions/dependency-review-action@",
"aquasecurity/trivy-action@",
"ossf/scorecard-action@",
"github/codeql-action/upload-sarif@",
"id-token: write",
]
for duplicate_scanner in removed_duplicate_scanners:
assert duplicate_scanner not in workflow_text

uses_lines = [line.strip() for line in workflow_text.splitlines() if line.strip().startswith("uses:")]
assert uses_lines
assert all(re.search(r"@[0-9a-f]{40}(?:\s+#|$)", line) for line in uses_lines)
Expand Down
Loading