Skip to content

D10 - Security Review #9

D10 - Security Review

D10 - Security Review #9

name: D10 - Security Review
on:
schedule:
- cron: '0 21 * * 3' # Runs every Wednesday at 8:30PM UTC / 5:00 EDT / 4:00 EST.
- cron: '30 06 * * 4' # Runs every Thursday at 6:30AM UTC / 2:30 EDT / 1:30 EST.
jobs:
drupal-security-audit:
runs-on: ubuntu-latest
name: Drupal security audit
steps:
- name: "Checkout code"
uses: actions/checkout@v4
- name: Install PHP with extensions
uses: shivammathur/[email protected]
with:
coverage: "none"
php-version: 8.2
tools: composer:v2
- name: "Composer install"
uses: "ramsey/[email protected]"
with:
composer-options: "--prefer-dist"
- name: Run composer audit for Drupal packages
id: audit # Needed for email
run: |
echo "# Drupal Security Audit Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Run audit in JSON format for easier parsing
composer audit --locked --format=json > audit_results.json 2>&1 || AUDIT_EXIT_CODE=$?
# Check if we have any vulnerabilities at all
if [ -f "audit_results.json" ] && [ "${AUDIT_EXIT_CODE:-0}" != "0" ]; then
echo "Parsing JSON audit results..."
# Extract Drupal and non-Drupal vulnerabilities using jq
echo "Extracting Drupal vulnerabilities..."
jq '[.advisories | to_entries[] | select(.key | startswith("drupal/")) | .value | to_entries[] | .value]' audit_results.json > drupal_advisories.json 2>/dev/null || echo '[]' > drupal_advisories.json
echo "Extracting non-Drupal vulnerabilities..."
jq '[.advisories | to_entries[] | select(.key | startswith("drupal/") | not) | .value[]]' audit_results.json > non_drupal_advisories.json 2>/dev/null || echo '[]' > non_drupal_advisories.json
# Check what we found
DRUPAL_COUNT=$(jq length drupal_advisories.json 2>/dev/null || echo 0)
NON_DRUPAL_COUNT=$(jq length non_drupal_advisories.json 2>/dev/null || echo 0)
HAS_DRUPAL=$([ "$DRUPAL_COUNT" -gt 0 ] && echo "true" || echo "false")
HAS_NON_DRUPAL=$([ "$NON_DRUPAL_COUNT" -gt 0 ] && echo "true" || echo "false")
echo "Found $DRUPAL_COUNT Drupal vulnerabilities"
echo "Found $NON_DRUPAL_COUNT non-Drupal vulnerabilities"
# Save counts for email
echo "drupal_count=$DRUPAL_COUNT" >> $GITHUB_OUTPUT
echo "non_drupal_count=$NON_DRUPAL_COUNT" >> $GITHUB_OUTPUT
# Function to create a table from JSON advisories
create_table() {
local json_file=$1
local output_file=$2
if [ -f "$json_file" ] && [ "$(jq length "$json_file")" -gt 0 ]; then
# Create table header
echo "+-------------------+----------------------------------------------------------------------------------+" > "$output_file"
echo "| Package | Details |" >> "$output_file"
echo "+-------------------+----------------------------------------------------------------------------------+" >> "$output_file"
# Process each advisory using a YAML-safe approach
jq -r '.[] | ["| " + .packageName + " | " + .packageName + " |", "| Severity | " + (.severity // "") + " |", "| CVE | " + (.cve // "") + " |", "| Title | " + .title + " |", "| URL | " + .link + " |", "| Affected versions | " + .affectedVersions + " |", "| Reported at | " + .reportedAt + " |", "+-------------------+----------------------------------------------------------------------------------+"] | .[]' "$json_file" >> "$output_file"
fi
}
# Create tables for Drupal and non-Drupal vulnerabilities
if [ "$HAS_DRUPAL" = "true" ]; then
create_table drupal_advisories.json drupal_table.txt
fi
if [ "$HAS_NON_DRUPAL" = "true" ]; then
create_table non_drupal_advisories.json non_drupal_table.txt
fi
# Show Drupal vulnerabilities if any
if [ "$HAS_DRUPAL" = "true" ]; then
echo "⚠️ **Security vulnerabilities detected in Drupal packages!**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
cat drupal_table.txt >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
# Save Drupal vulnerabilities for email
if [ "$HAS_DRUPAL" = "true" ]; then
DRUPAL_DETAILS=$(cat drupal_table.txt)
echo "drupal_details<<EOF" >> $GITHUB_OUTPUT
echo "$DRUPAL_DETAILS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
fi
# Show non-Drupal vulnerabilities if any
if [ "$HAS_NON_DRUPAL" = "true" ]; then
if [ "$HAS_DRUPAL" = "true" ]; then
echo "ℹ️ **Security vulnerabilities also found in non-Drupal packages:**" >> $GITHUB_STEP_SUMMARY
else
echo "✅ **No security vulnerabilities found in Drupal packages!**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "ℹ️ **Security vulnerabilities detected in non-Drupal packages:**" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
cat non_drupal_table.txt >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
fi
# Save non-Drupal vulnerabilities for email
if [ "$HAS_NON_DRUPAL" = "true" ]; then
NON_DRUPAL_DETAILS=$(cat non_drupal_table.txt)
echo "non_drupal_details<<EOF" >> $GITHUB_OUTPUT
echo "$NON_DRUPAL_DETAILS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
fi
# Console output
if [ "$HAS_DRUPAL" = "true" ]; then
echo "❌ Drupal security audit failed - vulnerabilities found in Drupal packages"
echo "Drupal security vulnerabilities:"
cat drupal_table.txt
exit 1
else
echo "✅ Drupal security audit passed - no vulnerabilities detected in Drupal packages"
if [ "$HAS_NON_DRUPAL" = "true" ]; then
echo "ℹ️ Non-Drupal packages have vulnerabilities (shown in summary)"
fi
fi
else
echo "✅ **No security vulnerabilities found in any packages!**" >> $GITHUB_STEP_SUMMARY
echo "✅ Drupal security audit passed - no vulnerabilities detected in any packages"
echo "drupal_count=0" >> $GITHUB_OUTPUT
echo "non_drupal_count=0" >> $GITHUB_OUTPUT
fi
- name: Send email notification on failure
if: failure()
uses: dawidd6/action-send-mail@v6
with:
server_address: smtp.gmail.com
server_port: 465
secure: true
username: ${{ secrets.EMAIL_USERNAME }}
password: ${{ secrets.EMAIL_PASSWORD }}
subject: "🚨 Drupal Security Vulnerabilities - ${{ github.repository }}"
to: ${{ vars.PALANTIR_NOTIFICATION_EMAIL }}
from: "Palantir Security Bot <${{ secrets.EMAIL_USERNAME }}>"
html_body: |
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<h2 style="color: #d73a49;">🚨 Drupal Security Alert</h2>
<p>One or more Drupal security vulnerabilities need to be addressed for a client's website${{ vars.CLIENT_WEBSITE_URL && format(':<br><a href="{0}">{0}</a>', vars.CLIENT_WEBSITE_URL) || '.' }}</p>
<p>A summary is shown below. Click here to see the full results:<br>
<a href="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}">${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}</a></p>
<div style="background-color: #f8f9fa; padding: 15px; border-left: 4px solid #d73a49; margin: 20px 0;">
<strong>Repository:</strong> ${{ github.repository }}<br>
<strong>Scan Date:</strong> ${{ github.event.repository.updated_at }}<br>
<strong>Drupal Vulnerabilities:</strong> ${{ steps.audit.outputs.drupal_count }}<br>
<strong>Non-Drupal Vulnerabilities:</strong> ${{ steps.audit.outputs.non_drupal_count }}
</div>
${{ steps.audit.outputs.drupal_count > 0 && '<h3 style="color: #d73a49;">🎯 Drupal Package Vulnerabilities (PRIORITY)</h3>' || '' }}
${{ steps.audit.outputs.drupal_count > 0 && '<div style="background-color: #f6f8fa; padding: 15px; border-radius: 5px; font-family: monospace; font-size: 14px; line-height: 1.4;">' || '' }}
${{ steps.audit.outputs.drupal_details }}
${{ steps.audit.outputs.drupal_count > 0 && '</div>' || '' }}
${{ steps.audit.outputs.non_drupal_count > 0 && '<h3 style="color: #f66a0a;">ℹ️ Non-Drupal Package Vulnerabilities</h3>' || '' }}
${{ steps.audit.outputs.non_drupal_count > 0 && '<div style="background-color: #f6f8fa; padding: 15px; border-radius: 5px; font-family: monospace; font-size: 14px; line-height: 1.4;">' || '' }}
${{ steps.audit.outputs.non_drupal_details }}
${{ steps.audit.outputs.non_drupal_count > 0 && '</div>' || '' }}
<div style="margin-top: 30px; padding: 15px; background-color: #e3f2fd; border-radius: 5px;">
<strong>Next Steps:</strong>
<ol>
<li>Review the vulnerabilities above</li>
<li>Assess impact on client's custom code</li>
<li>Contact client with next steps and timeline:
<ul>
<li>Highly Critical / Critical: Same-day</li>
<li>Moderately Critical: Next Day</li>
</ul>
</li>
<li>Alert teammates and request assistance</li>
</ol>
</div>
</body>
</html>