Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
136 changes: 136 additions & 0 deletions .github/workflows/gitleaks-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: Gitleaks Secret Scan

on:
workflow_call:
inputs:
soft-fail:
description: 'Whether to continue on secret detection'
required: false
type: boolean
default: false
upload-sarif:
description: 'Whether to upload SARIF results to Security tab'
required: false
type: boolean
default: false
upload-artifact:
description: 'Whether to upload results as artifact'
required: false
type: boolean
default: true

permissions:
contents: read

jobs:
scan:
name: Gitleaks Secret Scan
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
with:
persist-credentials: false
fetch-depth: 0

- name: Download and verify gitleaks
shell: bash
run: |
set -euo pipefail

GITLEAKS_VERSION="8.30.0"
GITLEAKS_SHA256="79a3ab579b53f71efd634f3aaf7e04a0fa0cf206b7ed434638d1547a2470a66e"
GITLEAKS_URL="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
GITLEAKS_TARBALL="gitleaks.tar.gz"

echo "Downloading gitleaks v${GITLEAKS_VERSION}..."
curl -fsSL -o "${GITLEAKS_TARBALL}" "${GITLEAKS_URL}"

echo "Verifying SHA256 checksum..."
echo "${GITLEAKS_SHA256} ${GITLEAKS_TARBALL}" | sha256sum -c -

echo "Extracting gitleaks binary..."
tar -xzf "${GITLEAKS_TARBALL}" gitleaks
chmod +x gitleaks

echo "Gitleaks version:"
./gitleaks version

- name: Run gitleaks scan
id: gitleaks
shell: bash
run: |
set -euo pipefail

mkdir -p logs

SCAN_ARGS=(
"git"
"--report-format" "sarif"
"--report-path" "logs/gitleaks-results.sarif"
"--redact"
"--log-level" "info"
)

# Respect .gitleaksignore for pre-existing secrets
if [ -f ".gitleaksignore" ]; then
echo "Found .gitleaksignore — known secrets will be suppressed."
fi

echo "Running gitleaks scan..."
EXIT_CODE=0
./gitleaks "${SCAN_ARGS[@]}" || EXIT_CODE=$?

if [ "$EXIT_CODE" -eq 0 ]; then
echo "No secrets detected."
echo "leaks-found=false" >> "$GITHUB_OUTPUT"
elif [ "$EXIT_CODE" -eq 1 ]; then
echo "::warning::Gitleaks detected secrets in the repository."
echo "leaks-found=true" >> "$GITHUB_OUTPUT"
if [ "${{ inputs.soft-fail }}" != "true" ]; then
echo "::error::Secret scanning failed. Review detected secrets in logs/gitleaks-results.sarif"
exit 1
fi
else
echo "::error::Gitleaks encountered an unexpected error (exit code: $EXIT_CODE)"
exit "$EXIT_CODE"
fi

- name: Upload SARIF to Security tab
if: inputs.upload-sarif && always()
uses: github/codeql-action/upload-sarif@ce729e4d353d580e6cacd6a8cf2921b72e5e310a # v3.27.0
with:
sarif_file: logs/gitleaks-results.sarif
category: gitleaks
continue-on-error: true

- name: Upload scan results
if: inputs.upload-artifact && always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v4.4.3
with:
name: gitleaks-results
path: logs/gitleaks-results.sarif
retention-days: 90

- name: Add job summary
if: always()
shell: bash
run: |
LEAKS_FOUND="${{ steps.gitleaks.outputs.leaks-found }}"
if [ "$LEAKS_FOUND" = "true" ]; then
STATUS="⚠️ Secrets Detected"
else
STATUS="✅ No Secrets Found"
fi

cat >> "$GITHUB_STEP_SUMMARY" <<EOF
## Gitleaks Secret Scan Results

| Metric | Value |
|--------|-------|
| Status | $STATUS |

EOF
12 changes: 12 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ jobs:
upload-sarif: true
upload-artifact: true

gitleaks-scan:
name: Gitleaks Secret Scan
uses: ./.github/workflows/gitleaks-scan.yml
permissions:
contents: read
security-events: write
with:
soft-fail: false
upload-sarif: true
upload-artifact: true

pester-tests:
name: PowerShell Tests
uses: ./.github/workflows/pester-tests.yml
Expand All @@ -69,6 +80,7 @@ jobs:
- markdown-lint
- table-format
- dependency-pinning-scan
- gitleaks-scan
- pester-tests
runs-on: ubuntu-latest
outputs:
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ jobs:
upload-sarif: true
upload-artifact: false

gitleaks-scan:
name: Gitleaks Secret Scan
uses: ./.github/workflows/gitleaks-scan.yml
permissions:
contents: read
security-events: write
with:
soft-fail: false
upload-sarif: true
upload-artifact: false

npm-audit:
name: npm Security Audit
runs-on: ubuntu-latest
Expand Down
25 changes: 25 additions & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# False positives: fake GitHub PAT 'ghp_test123456789' used as test fixture data
# in Pester security test files for SHA pinning and staleness validation.
# Rule: generic-api-key

# Test-SHAStaleness.Tests.ps1
1c9634d8334ebe8e88513f9a531b49d03590c307:scripts/tests/security/Test-SHAStaleness.Tests.ps1:generic-api-key:33
1c9634d8334ebe8e88513f9a531b49d03590c307:scripts/tests/security/Test-SHAStaleness.Tests.ps1:generic-api-key:38
1c9634d8334ebe8e88513f9a531b49d03590c307:scripts/tests/security/Test-SHAStaleness.Tests.ps1:generic-api-key:55
1c9634d8334ebe8e88513f9a531b49d03590c307:scripts/tests/security/Test-SHAStaleness.Tests.ps1:generic-api-key:105

# Update-ActionSHAPinning.Tests.ps1
1c9634d8334ebe8e88513f9a531b49d03590c307:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:60
1c9634d8334ebe8e88513f9a531b49d03590c307:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:92
1c9634d8334ebe8e88513f9a531b49d03590c307:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:143
3a11b26086c43b9551e6a7b666ffb6aa5dd8a8d7:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:93
3a11b26086c43b9551e6a7b666ffb6aa5dd8a8d7:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:127
3a11b26086c43b9551e6a7b666ffb6aa5dd8a8d7:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:193
4ef6d20475e42b753c29846aa28489843e70a8ed:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:256
4ef6d20475e42b753c29846aa28489843e70a8ed:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:488
a02335e7c98e5f2e22b1921442e99f01c6781a19:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:280
a02335e7c98e5f2e22b1921442e99f01c6781a19:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:511
f7c9b9a6f776e6403f393adf90a67127f3fc3405:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:791
f7c9b9a6f776e6403f393adf90a67127f3fc3405:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:869
6b84a8e49193d266411df9e4b8e8b1be2369eed2:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:792
6b84a8e49193d266411df9e4b8e8b1be2369eed2:scripts/tests/security/Update-ActionSHAPinning.Tests.ps1:generic-api-key:874
23 changes: 12 additions & 11 deletions docs/security/threat-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -723,11 +723,11 @@ These threats address ethical and responsible AI considerations aligned with Mic

### Vulnerability Management Controls

| ID | Control | Implementation | Validates Against |
|------|---------------------------------|----------------------------|-------------------|
| VM-1 | Coordinated Disclosure | SECURITY.md | I-1 |
| VM-2 | Secret Scanning | GitHub native | I-1, I-2 |
| VM-3 | Credential Persistence Disabled | persist-credentials: false | I-1, E-1 |
| ID | Control | Implementation | Validates Against |
|------|---------------------------------|-----------------------------------------------------|-------------------|
| VM-1 | Coordinated Disclosure | SECURITY.md | I-1 |
| VM-2 | Secret Scanning | GitHub native, gitleaks PR gate (gitleaks-scan.yml) | I-1, I-2 |
| VM-3 | Credential Persistence Disabled | persist-credentials: false | I-1, E-1 |

## Assurance Argument

Expand Down Expand Up @@ -863,12 +863,13 @@ HVE Core documents integrations with Model Context Protocol servers. This sectio

### Validation Workflow Coverage

| Workflow | Trigger | Security Checks |
|---------------------------------|--------------------|----------------------------|
| pr-validation.yml | PR to main/develop | Pinning, npm audit, CodeQL |
| codeql-analysis.yml | Push, PR, weekly | Static analysis |
| dependency-review.yml | PR to main/develop | Vulnerability scanning |
| weekly-security-maintenance.yml | Sundays 2 AM UTC | Pinning, staleness, CodeQL |
| Workflow | Trigger | Security Checks |
|---------------------------------|--------------------|--------------------------------------|
| pr-validation.yml | PR to main/develop | Pinning, npm audit, CodeQL, gitleaks |
| main.yml | Push to main | Pinning, gitleaks |
| codeql-analysis.yml | Push, PR, weekly | Static analysis |
| dependency-review.yml | PR to main/develop | Vulnerability scanning |
| weekly-security-maintenance.yml | Sundays 2 AM UTC | Pinning, staleness, CodeQL |

## References

Expand Down
Loading