Skip to content

Bump immutable from 5.1.4 to 5.1.5 #3

Bump immutable from 5.1.4 to 5.1.5

Bump immutable from 5.1.4 to 5.1.5 #3

Workflow file for this run

name: Security Scan
on:
pull_request:
branches:
- main
- release
- develop
schedule:
# Run every week on Monday at 2 AM UTC (3 AM EST)
- cron: '0 2 * * 1'
jobs:
# Check GitHub Advanced Security availability
check-advanced-security:
name: Check Advanced Security
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
ghas-enabled: ${{ steps.check-ghas.outputs.enabled }}
steps:
- name: Check GitHub Advanced Security Status
id: check-ghas
run: |
echo "πŸ” Checking GitHub Advanced Security status..."
GHAS_STATUS=$(gh api repos/${{ github.repository }} --jq '.security_and_analysis.advanced_security.status // "disabled"')
echo "Advanced Security status: $GHAS_STATUS"
if [ "$GHAS_STATUS" = "enabled" ]; then
echo "βœ… GitHub Advanced Security is enabled"
echo "enabled=true" >> "$GITHUB_OUTPUT"
else
echo "⚠️ GitHub Advanced Security is not enabled"
echo "CodeQL and dependency review will be skipped"
echo "enabled=false" >> "$GITHUB_OUTPUT"
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Basic security checks that must pass before other jobs
essential-security:
name: Essential Security Checks
runs-on: ubuntu-latest
needs: check-advanced-security
permissions:
contents: read
outputs:
secrets-clean: ${{ steps.secrets-check.outputs.clean }}
env-files-clean: ${{ steps.env-check.outputs.clean }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
# Fetch full history for comprehensive scan
fetch-depth: 0
- name: Environment File Validation
id: env-check
run: |
echo "πŸ” Checking for accidentally committed environment files..."
# Check for .env files
if find . -name ".env*" -not -path "./vendor/*" -not -path "./node_modules/*" -not -path "./.github/*" -not -name ".env.example" -not -name ".env.*.example" -not -name ".env.testing" -not -name ".env.ci" -type f | grep -q .; then
echo "❌ Found potentially sensitive .env files:"
find . -name ".env*" -not -path "./vendor/*" -not -path "./node_modules/*" -not -path "./.github/*" -not -name ".env.example" -not -name ".env.*.example" -not -name ".env.testing" -not -name ".env.ci" -type f
echo "clean=false" >> "$GITHUB_OUTPUT"
exit 1
fi
echo "βœ… No sensitive environment files found"
echo "clean=true" >> "$GITHUB_OUTPUT"
- name: File Permissions Check
run: |
echo "πŸ” Checking for overly permissive file permissions..."
# Check for world-writable files
if find . -type f -perm -002 -not -path "./vendor/*" -not -path "./node_modules/*" -not -path "./.git/*" | grep -q .; then
echo "❌ Found world-writable files:"
find . -type f -perm -002 -not -path "./vendor/*" -not -path "./node_modules/*" -not -path "./.git/*"
exit 1
fi
# Check for executable files that shouldn't be
if find . -type f -name "*.php" -perm -111 -not -path "./vendor/*" -not -path "./artisan" | grep -q .; then
echo "⚠️ Found executable PHP files (may be intentional):"
find . -type f -name "*.php" -perm -111 -not -path "./vendor/*" -not -path "./artisan"
fi
echo "βœ… File permissions look secure"
- name: Hardcoded Secrets Patterns
run: |
echo "πŸ” Scanning for hardcoded secrets patterns..."
# Define patterns for common secrets
patterns=(
'password\s*=\s*["\x27][^"\x27\s]{8,}'
'api[_-]?key\s*[=:]\s*["\x27][A-Za-z0-9]{20,}'
'secret[_-]?key\s*[=:]\s*["\x27][A-Za-z0-9]{20,}'
'access[_-]?token\s*[=:]\s*["\x27][A-Za-z0-9]{20,}'
'private[_-]?key\s*[=:]\s*["\x27][A-Za-z0-9+/=]{40,}'
)
found_secrets=false
for pattern in "${patterns[@]}"; do
if grep -rEi "$pattern" . --include="*.php" --include="*.js" --include="*.ts" --include="*.json" --exclude-dir=vendor --exclude-dir=node_modules --exclude-dir=.git; then
found_secrets=true
fi
done
if [ "$found_secrets" = true ]; then
echo "❌ Found potential hardcoded secrets! Please review the matches above."
exit 1
fi
echo "βœ… No hardcoded secrets patterns detected"
- name: Download and Run Gitleaks
id: secrets-check
run: |
# Download Gitleaks binary
curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.28.0/gitleaks_8.28.0_linux_x64.tar.gz | tar -xz
# Run Gitleaks scan
echo "πŸ” Running Gitleaks secret scan..."
./gitleaks detect --config=.gitleaks.toml --verbose || exit_code=$?
# Check results
if [ "${exit_code:-0}" -eq 1 ]; then
echo "❌ Gitleaks found potential secrets in the repository!"
echo "Please review the findings above and remove any secrets before merging."
echo "clean=false" >> "$GITHUB_OUTPUT"
exit 1
fi
echo "βœ… No secrets detected by Gitleaks - repository is clean!"
echo "clean=true" >> "$GITHUB_OUTPUT"
# Note: SARIF upload disabled - requires GitHub Advanced Security
# CodeQL Analysis - only runs if GitHub Advanced Security is enabled
codeql-analysis:
name: CodeQL Analysis
runs-on: ubuntu-latest
needs: [check-advanced-security, essential-security]
if: needs.essential-security.outputs.secrets-clean == 'true' && needs.check-advanced-security.outputs.ghas-enabled == 'true'
permissions:
contents: read
security-events: write
actions: read
strategy:
fail-fast: false
matrix:
language: [javascript]
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- name: Setup Node (for JavaScript analysis)
if: matrix.language == 'javascript'
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'
- name: Install Node Dependencies
if: matrix.language == 'javascript'
run: npm ci
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
# Dependency Review - only runs if GitHub Advanced Security is enabled
dependency-review:
name: Dependency Review
runs-on: ubuntu-latest
needs: [check-advanced-security, essential-security]
if: needs.essential-security.outputs.secrets-clean == 'true' && needs.check-advanced-security.outputs.ghas-enabled == 'true' && github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Run Dependency Review
uses: actions/dependency-review-action@v4
with:
# Fail on high and critical vulnerabilities
fail-on-severity: high
# Allow licenses compatible with commercial use
allow-licenses: 'MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, CC0-1.0'
license-compliance:
name: License Compliance Check
runs-on: ubuntu-latest
needs: essential-security
if: needs.essential-security.outputs.secrets-clean == 'true'
permissions:
contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.4
tools: composer:v2
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'
- name: Copy Environment File
run: cp .env.testing .env
- name: Install Dependencies
run: |
composer install --no-interaction --prefer-dist --optimize-autoloader
npm ci
- name: Check PHP License Compliance
run: |
echo "πŸ” Checking PHP package licenses..."
# Get license information and show dual-licensed packages
composer licenses > licenses.txt
echo "Checking for packages with problematic licensing..."
# Check for packages that have ONLY GPL licenses (no alternatives)
problematic_found=false
# Look for lines that contain GPL but NOT any acceptable licenses
while IFS= read -r line; do
if echo "$line" | grep -E "(GPL-3\.0|AGPL-3\.0)" | grep -v -E "(MIT|Apache|BSD|ISC|CC0)" | grep -v "GPL-2\.0" ; then
# Double check this isn't a dual-licensed package with acceptable alternatives
package_line=$(echo "$line" | grep -E "(GPL-3\.0|AGPL-3\.0)")
if [[ -n "$package_line" ]] && ! echo "$package_line" | grep -E "(MIT|Apache|BSD|ISC)"; then
if [[ "$problematic_found" == "false" ]]; then
echo "❌ Found packages with only prohibited licenses:"
problematic_found=true
fi
echo "$package_line"
fi
fi
done < licenses.txt
if [[ "$problematic_found" == "true" ]]; then
exit 1
fi
echo "βœ… All PHP licenses are compliant (dual-licensed packages with BSD/MIT alternatives are acceptable)"
- name: Check Node License Compliance
run: |
echo "πŸ” Checking Node.js package licenses..."
# Install license-checker
npm install -g license-checker
# Check licenses (including common font and build tool licenses)
license-checker --onlyAllow 'MIT;Apache-2.0;BSD;BSD-2-Clause;BSD-3-Clause;ISC;CC0-1.0;Unlicense;WTFPL;OFL-1.1;SIL OFL 1.1;MPL-2.0' --excludePrivatePackages --production
owasp-dependency-check:
name: OWASP Dependency Check
runs-on: ubuntu-latest
needs: essential-security
if: needs.essential-security.outputs.secrets-clean == 'true'
permissions:
contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Run OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'annotation-management-system'
path: '.'
format: 'HTML'
out: 'dependency-check-report'
args: >
--enableRetired
--enableExperimental
--nvdApiDelay 2000
--disableOssIndex
- name: Upload OWASP Report as Artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: owasp-dependency-check-report
path: dependency-check-report/
retention-days: 30
dependency-scan:
name: Dependency Security Scan
runs-on: ubuntu-latest
needs: [essential-security, license-compliance]
if: needs.essential-security.outputs.secrets-clean == 'true'
permissions:
contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.4
tools: composer:v2
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'
- name: Copy Environment File
run: cp .env.testing .env
- name: Install PHP Dependencies
run: composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
- name: Install Node Dependencies
run: npm ci --production
- name: Run PHP Security Audit
run: composer audit --format=table
- name: Run Node Security Audit
run: npm audit --audit-level=high
code-quality:
name: Code Quality & Static Analysis
runs-on: ubuntu-latest
needs: [essential-security, dependency-scan]
if: needs.essential-security.outputs.secrets-clean == 'true'
permissions:
contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.4
tools: composer:v2
- name: Copy Environment File
run: cp .env.testing .env
- name: Install Dependencies
run: composer install --no-interaction --prefer-dist --optimize-autoloader
- name: Run PHPStan
run: ./vendor/bin/phpstan analyse --memory-limit=2G
- name: Run PHP Code Style Check
run: ./vendor/bin/pint --test
security-headers:
name: Security Headers Check
runs-on: ubuntu-latest
needs: [essential-security, code-quality]
if: github.event_name == 'pull_request' && needs.essential-security.outputs.secrets-clean == 'true'
permissions:
contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Check Security Headers Middleware
run: |
if [ -f "app/Http/Middleware/AddSecurityHeaders.php" ]; then
echo "βœ… Security headers middleware found"
grep -q "X-Frame-Options\|X-Content-Type-Options\|X-XSS-Protection\|Strict-Transport-Security" app/Http/Middleware/AddSecurityHeaders.php && echo "βœ… Basic security headers are configured" || echo "❌ Missing basic security headers"
else
echo "❌ Security headers middleware not found"
exit 1
fi
- name: Check HTTPS Configuration
run: |
if grep -q "HTTPS\|SSL" config/app.php || grep -q "secure" config/session.php; then
echo "βœ… HTTPS configuration found"
else
echo "⚠️ Consider configuring HTTPS for production"
fi
- name: Check Content Security Policy (CSP)
run: |
if grep -q "Content-Security-Policy" app/Http/Middleware/AddSecurityHeaders.php; then
echo "βœ… Content Security Policy (CSP) is configured"
else
echo "⚠️ Consider adding a Content Security Policy (CSP) for enhanced security"
fi
- name: Check Secure Cookies
run: |
if grep -q "'secure' => env('SESSION_SECURE_COOKIE', true)" config/session.php; then
echo "βœ… Secure cookies are enabled"
else
echo "⚠️ Consider enabling secure cookies in config/session.php"
fi
- name: Check HSTS Configuration
run: |
if grep -q "Strict-Transport-Security" app/Http/Middleware/AddSecurityHeaders.php; then
echo "βœ… HSTS is configured"
else
echo "⚠️ Consider adding HSTS for enhanced security"
fi
- name: Check Referrer Policy
run: |
if grep -q "Referrer-Policy" app/Http/Middleware/AddSecurityHeaders.php; then
echo "βœ… Referrer Policy is configured"
else
echo "⚠️ Consider adding a Referrer Policy for enhanced privacy"
fi
- name: Check X-Content-Type-Options
run: |
if grep -q "X-Content-Type-Options" app/Http/Middleware/AddSecurityHeaders.php; then
echo "βœ… X-Content-Type-Options is configured"
else
echo "⚠️ Consider adding X-Content-Type-Options to prevent MIME type sniffing"
fi
- name: Check X-Frame-Options
run: |
if grep -q "X-Frame-Options" app/Http/Middleware/AddSecurityHeaders.php; then
echo "βœ… X-Frame-Options is configured"
else
echo "⚠️ Consider adding X-Frame-Options to prevent clickjacking"
fi
- name: Check X-XSS-Protection
run: |
if grep -q "X-XSS-Protection" app/Http/Middleware/AddSecurityHeaders.php; then
echo "βœ… X-XSS-Protection is configured"
else
echo "⚠️ Consider adding X-XSS-Protection to mitigate XSS attacks"
fi