GitHub Advanced Security: Configuration, Management, and Reporting Guide
READER BEWARE: THE FOLLOWING WRITTEN ENTIRELY BY AI WITHOUT HUMAN EDITING.
Introduction
GitHub Advanced Security (GHAS) represents GitHub’s comprehensive suite of security tools designed to help development teams identify and remediate security vulnerabilities before they reach production. Whether you’re managing a single repository or an entire enterprise, GHAS provides code scanning, secret scanning, and dependency review capabilities that integrate seamlessly into your development workflow.
This guide covers everything you need to know about GitHub Advanced Security: how to configure and enable its features, manage security policies across your organization, access reporting and analytics, and leverage GitHub’s built-in remediation workflows to efficiently address security findings.
What is GitHub Advanced Security?
GitHub Advanced Security is a collection of security features that help you find, prevent, and fix security vulnerabilities in your code. It includes:
- Code Scanning: Static analysis using CodeQL and third-party tools to find vulnerabilities in your codebase
- Secret Scanning: Detection of accidentally committed credentials, API keys, and other secrets
- Dependency Review: Analysis of pull requests to identify vulnerable dependencies before they’re merged
- Security Overview: Centralized dashboards for tracking security posture across repositories
Licensing and Availability
GitHub Advanced Security availability depends on your GitHub plan:
| Feature | GitHub Free | GitHub Pro | GitHub Team | GitHub Enterprise |
|---|---|---|---|---|
| Code Scanning (Public Repos) | ✅ | ✅ | ✅ | ✅ |
| Code Scanning (Private Repos) | ❌ | ❌ | ❌ | ✅ (GHAS license) |
| Secret Scanning (Public Repos) | ✅ | ✅ | ✅ | ✅ |
| Secret Scanning (Private Repos) | ❌ | ❌ | ❌ | ✅ (GHAS license) |
| Secret Scanning Push Protection | ❌ | ❌ | ❌ | ✅ (GHAS license) |
| Dependency Review | ✅ | ✅ | ✅ | ✅ |
| Security Overview | ❌ | ❌ | ❌ | ✅ |
For public repositories, most features are available for free. For private repositories, you need GitHub Enterprise with a GitHub Advanced Security license.
Code Scanning with CodeQL
Code scanning is GitHub’s static analysis solution that identifies security vulnerabilities and coding errors in your code. The primary engine powering code scanning is CodeQL, GitHub’s semantic code analysis engine.
How CodeQL Works
CodeQL treats code as data, allowing you to write queries that search for specific patterns in your codebase. The process works in three stages:
- Database Creation: CodeQL builds a relational database representing your code structure
- Query Execution: Security queries run against the database to find vulnerabilities
- Alert Generation: Findings are surfaced as alerts in the Security tab
Enabling Code Scanning
Method 1: Default Setup (Recommended for Most Repositories)
GitHub provides a streamlined default setup that works for most repositories:
- Navigate to your repository on GitHub
- Click Settings → Code security and analysis
- Under Code scanning, click Set up → Default
- Review the configuration and click Enable CodeQL
The default setup:
- Automatically detects supported languages
- Runs on push events to the default branch
- Runs on pull requests targeting the default branch
- Uses the
security-extendedquery suite
Method 2: Advanced Setup with Workflow File
For more control over code scanning, create a custom workflow:
# .github/workflows/codeql-analysis.yml
name: "CodeQL Analysis"
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
# Run weekly on Sunday at 4:00 AM UTC
- cron: '0 4 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
timeout-minutes: 360
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'python', 'go' ]
# Supported languages: cpp, csharp, go, java, javascript, python, ruby, swift
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# Override the default queries with a custom suite
queries: security-extended,security-and-quality
# For compiled languages (Java, C++, C#, Go, Swift), add build steps
# Autobuild attempts to build any compiled language
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
CodeQL Configuration Options
Query Suites
CodeQL provides several query suites with different coverage and false positive rates:
| Suite | Description | Use Case |
|---|---|---|
default | Core security queries with low false positive rate | Production scanning |
security-extended | Extended security queries | Comprehensive security scanning |
security-and-quality | Security + code quality queries | Full code analysis |
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript
queries: security-extended
Custom Query Packs
You can use custom CodeQL query packs:
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript
packs: |
codeql/javascript-queries:path/to/custom-queries
my-org/my-security-queries@1.0.0
Configuration File
Create a CodeQL configuration file for complex setups:
# .github/codeql/codeql-config.yml
name: "Custom CodeQL Config"
# Disable default queries and use custom ones
disable-default-queries: false
# Add custom query packs
packs:
javascript:
- codeql/javascript-queries
# Add custom queries from your repository
queries:
- uses: ./custom-queries/javascript
# Exclude paths from analysis
paths-ignore:
- '**/test/**'
- '**/tests/**'
- '**/node_modules/**'
- '**/vendor/**'
- '**/*.test.js'
- '**/*.spec.js'
# Only analyze specific paths
paths:
- src
- lib
Reference the configuration file in your workflow:
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript
config-file: ./.github/codeql/codeql-config.yml
Viewing Code Scanning Results
Code scanning results appear in multiple locations:
- Security Tab: Navigate to Security → Code scanning alerts
- Pull Request Checks: Results appear as check annotations on PRs
- API Access: Use the REST API or GraphQL to programmatically access alerts
Understanding Alert Severity
Alerts are classified by severity:
| Severity | Description | Action Required |
|---|---|---|
| Critical | Severe vulnerabilities requiring immediate attention | Immediate fix required |
| High | Significant security issues | Fix in current sprint |
| Medium | Moderate security concerns | Fix when feasible |
| Low | Minor issues or informational | Consider addressing |
| Error | Analysis errors | Investigate configuration |
| Warning | Potential issues | Review and assess |
| Note | Informational findings | Optional review |
Managing Code Scanning Alerts
Alert States
Alerts can be in the following states:
- Open: Active alert requiring attention
- Closed: Resolved through code changes
- Dismissed: Manually dismissed with a reason
- Fixed: Automatically closed when vulnerable code is removed
Dismissing Alerts
When dismissing an alert, provide a reason:
- False positive: The alert doesn’t represent a real vulnerability
- Won’t fix: The vulnerability is accepted risk
- Used in tests: The code is only used in test scenarios
# Using GitHub CLI to dismiss an alert
gh api repos/{owner}/{repo}/code-scanning/alerts/{alert_number} \
-X PATCH \
-f state=dismissed \
-f dismissed_reason="false positive" \
-f dismissed_comment="This pattern is safe in our context because..."
Code Scanning with Third-Party Tools
GitHub code scanning supports SARIF (Static Analysis Results Interchange Format) uploads from any tool:
# Example: Running ESLint and uploading results
- name: Run ESLint
run: npx eslint . --format @microsoft/sarif --output-file eslint-results.sarif
continue-on-error: true
- name: Upload ESLint SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: eslint-results.sarif
category: eslint
Popular third-party integrations:
- Semgrep:
returntocorp/semgrep-action - Snyk:
snyk/actions - SonarCloud: SonarSource analyzers
- Checkmarx: Checkmarx GitHub Action
Secret Scanning
Secret scanning automatically detects secrets committed to your repository, including API keys, tokens, passwords, and other credentials.
How Secret Scanning Works
GitHub maintains partnerships with over 100 service providers to detect their specific token formats. When a secret is detected:
- Pattern Matching: GitHub scans code for known secret patterns
- Partner Notification: If enabled, the service provider is notified
- Alert Creation: An alert appears in the Security tab
Enabling Secret Scanning
Repository Level
- Navigate to Settings → Code security and analysis
- Under Secret scanning, click Enable
- Optionally enable Push protection
Organization Level
- Navigate to Organization Settings → Code security and analysis
- Enable secret scanning for all repositories:
- All repositories
- New repositories only
- Public repositories only
# Using GitHub API to enable secret scanning
gh api orgs/{org}/repos/{repo} \
-X PATCH \
-f security_and_analysis.secret_scanning.status=enabled \
-f security_and_analysis.secret_scanning_push_protection.status=enabled
Push Protection
Push protection prevents secrets from being pushed to GitHub in the first place:
# When push protection detects a secret, you'll see:
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote:
remote: - GITHUB_PUSH_PROTECTION: push protection detected a secret in commit abc1234
remote: Secret type: GitHub Personal Access Token
remote: Location: config/secrets.js:15
remote:
remote: To push, either remove the secret or use a bypass if you believe this is safe
Bypassing Push Protection
When push protection blocks a push, you have options:
- Remove the secret: The recommended approach
- Request bypass: For legitimate cases (requires admin approval)
- Allow bypass for specific patterns: Configure allowed patterns
# Configure custom patterns that are allowed
# In repository Settings → Code security → Secret scanning → Push protection
# Allowed patterns (example for test/mock tokens):
# - Pattern: test_[a-z0-9]{32}
# - Description: Test tokens for CI/CD
Custom Secret Patterns
Define custom patterns to detect organization-specific secrets:
- Navigate to Organization Settings → Code security → Secret scanning
- Click New pattern
- Define the pattern using regex:
# Example custom pattern for internal API keys
Name: Internal API Key
Pattern: INTERNAL_[A-Z0-9]{24}
Description: Detects internal API keys used in our services
Managing Secret Scanning Alerts
Alert Workflow
# List secret scanning alerts
gh api repos/{owner}/{repo}/secret-scanning/alerts
# Get specific alert details
gh api repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}
# Close an alert
gh api repos/{owner}/{repo}/secret-scanning/alerts/{alert_number} \
-X PATCH \
-f state=resolved \
-f resolution=revoked
Resolution States
- Open: Active alert requiring attention
- Resolved - Revoked: Secret has been revoked/rotated
- Resolved - False Positive: Detection was incorrect
- Resolved - Used in Tests: Secret is only in test code
- Resolved - Won’t Fix: Accepted risk
Secret Scanning Best Practices
- Enable Push Protection: Prevent secrets before they’re committed
- Rotate Immediately: When a secret is detected, rotate it immediately
- Use Environment Variables: Store secrets in environment variables, not code
- Configure .gitignore: Exclude sensitive file patterns
- Use Secret Managers: Integrate with HashiCorp Vault, AWS Secrets Manager, etc.
Dependency Review
Dependency review analyzes pull requests to identify changes to dependencies and highlight any that introduce vulnerabilities.
Enabling Dependency Review
Dependency review works automatically when:
- Dependency Graph is enabled
- Pull requests include changes to manifest files (package.json, Gemfile, requirements.txt, etc.)
# .github/workflows/dependency-review.yml
name: 'Dependency Review'
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
- name: 'Dependency Review'
uses: actions/dependency-review-action@v4
with:
# Fail on any vulnerability with severity >= high
fail-on-severity: high
# Also fail on these license types
deny-licenses: GPL-3.0, AGPL-3.0
# Allow specific packages with known issues
allow-ghsas: GHSA-xxxx-xxxx-xxxx
Configuration Options
- name: 'Dependency Review'
uses: actions/dependency-review-action@v4
with:
# Severity threshold: critical, high, moderate, low
fail-on-severity: moderate
# License checking
allow-licenses: MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause
deny-licenses: GPL-3.0, AGPL-3.0, LGPL-3.0
# Scope filtering
fail-on-scopes: runtime, development
# Vulnerability filtering
allow-ghsas: GHSA-xxxx-xxxx-xxxx, GHSA-yyyy-yyyy-yyyy
# Output configuration
comment-summary-in-pr: always
Understanding Dependency Review Results
When dependency review runs on a PR, it provides:
- Vulnerability Summary: New vulnerabilities introduced by the PR
- License Changes: Changes to dependency licenses
- Manifest Changes: Which files were modified
Results appear as:
- Check run annotations
- PR comments (if configured)
- API-accessible data
Security Overview
Security Overview provides a centralized dashboard for managing security across your organization.
Accessing Security Overview
- Navigate to your organization
- Click Security tab
- Select from available views:
- Overview: High-level security posture
- Risk: Repositories by risk level
- Coverage: Feature enablement status
- CodeQL Pull Request Alerts: Recent PR findings
Dashboard Views
Overview Dashboard
The overview shows:
- Total alerts by severity
- Trend data over time
- Top affected repositories
- Recent activity
Risk View
Filter and sort repositories by:
- Number of open alerts
- Alert severity
- Last activity date
- Security feature coverage
Repository | Critical | High | Medium | Low | Coverage
-------------------|----------|------|--------|-----|----------
api-service | 2 | 5 | 12 | 8 | 100%
web-frontend | 0 | 3 | 8 | 15 | 75%
internal-tools | 1 | 2 | 4 | 3 | 50%
Coverage View
Track security feature adoption:
- Code scanning enabled/disabled
- Secret scanning enabled/disabled
- Dependabot alerts enabled/disabled
- Push protection enabled/disabled
Filtering and Exporting Data
# Export security overview data using GitHub API
gh api orgs/{org}/security-managers
# Get code scanning alerts across org
gh api orgs/{org}/code-scanning/alerts \
--paginate \
-q '.[] | [.repository.name, .state, .rule.severity, .rule.description] | @csv'
# Get secret scanning alerts across org
gh api orgs/{org}/secret-scanning/alerts \
--paginate \
-q '.[] | [.repository.name, .state, .secret_type] | @csv'
Reporting and Analytics
Accessing Security Reports
REST API Endpoints
# Code scanning alerts for a repository
GET /repos/{owner}/{repo}/code-scanning/alerts
# Code scanning alerts for an organization
GET /orgs/{org}/code-scanning/alerts
# Secret scanning alerts for a repository
GET /repos/{owner}/{repo}/secret-scanning/alerts
# Secret scanning alerts for an organization
GET /orgs/{org}/secret-scanning/alerts
# Dependabot alerts for a repository
GET /repos/{owner}/{repo}/dependabot/alerts
# Dependabot alerts for an organization
GET /orgs/{org}/dependabot/alerts
GraphQL Queries
# Query code scanning alerts
query {
repository(owner: "owner", name: "repo") {
vulnerabilityAlerts(first: 100) {
nodes {
createdAt
dismissedAt
securityVulnerability {
severity
package {
name
}
advisory {
summary
}
}
}
}
}
}
Building Custom Reports
Python Script for Security Reporting
#!/usr/bin/env python3
"""
GitHub Advanced Security Reporting Script
Generates comprehensive security reports across repositories
"""
import os
import json
from datetime import datetime, timedelta
from github import Github
import csv
GITHUB_TOKEN = os.environ.get('GITHUB_TOKEN')
ORG_NAME = "your-organization"
def get_code_scanning_alerts(g, org_name):
"""Fetch code scanning alerts across organization"""
alerts = []
org = g.get_organization(org_name)
for repo in org.get_repos():
try:
repo_alerts = repo.get_codescan_alerts()
for alert in repo_alerts:
alerts.append({
'repository': repo.name,
'rule_id': alert.rule.id,
'rule_description': alert.rule.description,
'severity': alert.rule.severity,
'state': alert.state,
'created_at': alert.created_at.isoformat(),
'html_url': alert.html_url
})
except Exception as e:
print(f"Could not fetch alerts for {repo.name}: {e}")
return alerts
def get_secret_scanning_alerts(g, org_name):
"""Fetch secret scanning alerts across organization"""
alerts = []
org = g.get_organization(org_name)
for repo in org.get_repos():
try:
repo_alerts = repo.get_secret_scanning_alerts()
for alert in repo_alerts:
alerts.append({
'repository': repo.name,
'secret_type': alert.secret_type,
'state': alert.state,
'created_at': alert.created_at.isoformat(),
'resolution': alert.resolution,
'html_url': alert.html_url
})
except Exception as e:
print(f"Could not fetch secret alerts for {repo.name}: {e}")
return alerts
def generate_summary_report(code_alerts, secret_alerts):
"""Generate summary statistics"""
# Code scanning summary
code_by_severity = {}
code_by_state = {}
for alert in code_alerts:
severity = alert['severity']
state = alert['state']
code_by_severity[severity] = code_by_severity.get(severity, 0) + 1
code_by_state[state] = code_by_state.get(state, 0) + 1
# Secret scanning summary
secret_by_type = {}
secret_by_state = {}
for alert in secret_alerts:
stype = alert['secret_type']
state = alert['state']
secret_by_type[stype] = secret_by_type.get(stype, 0) + 1
secret_by_state[state] = secret_by_state.get(state, 0) + 1
return {
'generated_at': datetime.now().isoformat(),
'code_scanning': {
'total': len(code_alerts),
'by_severity': code_by_severity,
'by_state': code_by_state
},
'secret_scanning': {
'total': len(secret_alerts),
'by_type': secret_by_type,
'by_state': secret_by_state
}
}
def export_to_csv(alerts, filename):
"""Export alerts to CSV"""
if not alerts:
return
with open(filename, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=alerts[0].keys())
writer.writeheader()
writer.writerows(alerts)
def main():
g = Github(GITHUB_TOKEN)
print(f"Generating security report for {ORG_NAME}...")
# Fetch alerts
code_alerts = get_code_scanning_alerts(g, ORG_NAME)
secret_alerts = get_secret_scanning_alerts(g, ORG_NAME)
# Generate summary
summary = generate_summary_report(code_alerts, secret_alerts)
# Export data
export_to_csv(code_alerts, f'code_scanning_alerts_{datetime.now():%Y%m%d}.csv')
export_to_csv(secret_alerts, f'secret_scanning_alerts_{datetime.now():%Y%m%d}.csv')
with open(f'security_summary_{datetime.now():%Y%m%d}.json', 'w') as f:
json.dump(summary, f, indent=2)
# Print summary
print("\n" + "="*60)
print("SECURITY REPORT SUMMARY")
print("="*60)
print(f"Generated: {summary['generated_at']}")
print(f"\nCode Scanning Alerts: {summary['code_scanning']['total']}")
for severity, count in summary['code_scanning']['by_severity'].items():
print(f" - {severity}: {count}")
print(f"\nSecret Scanning Alerts: {summary['secret_scanning']['total']}")
for state, count in summary['secret_scanning']['by_state'].items():
print(f" - {state}: {count}")
if __name__ == "__main__":
main()
Bash Script for Quick Reports
#!/bin/bash
# quick-security-report.sh - Generate security overview using GitHub CLI
ORG="your-organization"
OUTPUT_DIR="./security-reports"
mkdir -p "$OUTPUT_DIR"
echo "GitHub Advanced Security Report"
echo "Organization: $ORG"
echo "Generated: $(date)"
echo "================================"
# Code scanning summary
echo ""
echo "=== Code Scanning Alerts ==="
gh api "orgs/$ORG/code-scanning/alerts?state=open&per_page=100" \
--jq 'group_by(.rule.severity) |
map({severity: .[0].rule.severity, count: length}) |
.[] | "\(.severity): \(.count)"'
# Secret scanning summary
echo ""
echo "=== Secret Scanning Alerts ==="
gh api "orgs/$ORG/secret-scanning/alerts?state=open&per_page=100" \
--jq 'group_by(.secret_type) |
map({type: .[0].secret_type, count: length}) |
.[] | "\(.type): \(.count)"'
# Repository coverage
echo ""
echo "=== Security Feature Coverage ==="
gh api "orgs/$ORG/repos?per_page=100" \
--jq '.[] | select(.archived == false) |
"\(.name): Code Scanning=\(.security_and_analysis.code_scanning.status // "disabled"),
Secret Scanning=\(.security_and_analysis.secret_scanning.status // "disabled")"'
echo ""
echo "Report complete. Detailed data exported to $OUTPUT_DIR"
Automated Reporting with GitHub Actions
# .github/workflows/security-report.yml
name: Weekly Security Report
on:
schedule:
# Run every Monday at 9 AM UTC
- cron: '0 9 * * 1'
workflow_dispatch:
jobs:
generate-report:
runs-on: ubuntu-latest
permissions:
security-events: read
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Generate Security Report
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Create report directory
mkdir -p reports
# Get code scanning alerts
gh api "repos/${{ github.repository }}/code-scanning/alerts" \
--paginate > reports/code-scanning.json
# Get secret scanning alerts
gh api "repos/${{ github.repository }}/secret-scanning/alerts" \
--paginate > reports/secret-scanning.json
# Generate summary
echo "# Security Report - $(date +%Y-%m-%d)" > reports/summary.md
echo "" >> reports/summary.md
echo "## Code Scanning" >> reports/summary.md
echo "Total alerts: $(jq length reports/code-scanning.json)" >> reports/summary.md
echo "" >> reports/summary.md
echo "## Secret Scanning" >> reports/summary.md
echo "Total alerts: $(jq length reports/secret-scanning.json)" >> reports/summary.md
- name: Upload Report Artifact
uses: actions/upload-artifact@v4
with:
name: security-report-${{ github.run_number }}
path: reports/
- name: Send Report to Slack
if: always()
uses: slackapi/slack-github-action@v1.24.0
with:
payload: |
{
"text": "Weekly Security Report Generated",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Weekly Security Report*\nRepository: ${{ github.repository }}\nGenerated: $(date)"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Remediation Workflows
GitHub provides several features to help remediate security findings efficiently.
Automated Security Updates with Dependabot
Configure Dependabot to automatically create PRs for security updates:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 10
# Group security updates together
groups:
security-updates:
applies-to: security-updates
patterns:
- "*"
# Auto-merge minor and patch security updates
allow:
- dependency-type: "direct"
commit-message:
prefix: "chore(deps):"
include: "scope"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
Auto-merge Security Updates
# .github/workflows/auto-merge-dependabot.yml
name: Auto-merge Dependabot PRs
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: write
pull-requests: write
jobs:
auto-merge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v1
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Auto-merge patch and minor updates
if: |
steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
steps.metadata.outputs.update-type == 'version-update:semver-minor'
run: |
gh pr review --approve "$PR_URL"
gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Code Scanning Autofix
GitHub’s code scanning can suggest fixes for certain vulnerabilities:
- View the code scanning alert
- If available, click Generate fix
- Review the suggested changes
- Create a PR directly from the alert
Currently supported for:
- JavaScript/TypeScript
- Python
- Go
- Ruby (limited)
Remediation PR Template
Create a template for security remediation PRs:
<!-- .github/PULL_REQUEST_TEMPLATE/security_fix.md -->
## Security Fix
### Alert Reference
- Alert URL:
- Alert Type: [Code Scanning / Secret Scanning / Dependabot]
- Severity: [Critical / High / Medium / Low]
### Changes Made
- [ ] Vulnerability has been fixed
- [ ] No new vulnerabilities introduced
- [ ] Tests pass
- [ ] Documentation updated (if applicable)
### Root Cause
[Describe what caused this vulnerability]
### Fix Description
[Describe how the vulnerability was fixed]
### Testing
- [ ] Existing tests pass
- [ ] New tests added for the fix
- [ ] Manually tested the fix
### Checklist
- [ ] I have read the [security guidelines](link-to-guidelines)
- [ ] This PR follows our security best practices
- [ ] The fix has been reviewed by a security team member
Bulk Remediation Scripts
#!/bin/bash
# bulk-dismiss-alerts.sh - Dismiss multiple code scanning alerts
REPO="owner/repo"
REASON="used in tests"
COMMENT="These alerts are in test code and don't affect production"
# Get all open alerts in test directories
ALERTS=$(gh api "repos/$REPO/code-scanning/alerts?state=open&per_page=100" \
--jq '.[] | select(.most_recent_instance.location.path | test("test|spec|__tests__")) | .number')
for alert_number in $ALERTS; do
echo "Dismissing alert #$alert_number..."
gh api "repos/$REPO/code-scanning/alerts/$alert_number" \
-X PATCH \
-f state=dismissed \
-f dismissed_reason="$REASON" \
-f dismissed_comment="$COMMENT"
done
echo "Done! Dismissed $(echo "$ALERTS" | wc -l) alerts."
Organization-Wide Security Policies
Security Policy File
Create a security policy at the organization level:
<!-- .github/SECURITY.md in your .github repository -->
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 2.x.x | :white_check_mark: |
| 1.x.x | :x: |
## Reporting a Vulnerability
We take security vulnerabilities seriously. If you discover a security issue, please report it responsibly.
### How to Report
1. **Do not** create a public GitHub issue
2. Email security@yourcompany.com with:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
### Response Timeline
- **Initial response**: Within 24 hours
- **Status update**: Within 72 hours
- **Resolution target**: 30 days for critical, 90 days for others
### Disclosure Policy
- We will acknowledge receipt within 24 hours
- We will provide regular updates on progress
- We will credit reporters (unless anonymity requested)
- We coordinate disclosure timing with reporters
## Security Features
This organization uses GitHub Advanced Security:
- ✅ Code scanning enabled on all repositories
- ✅ Secret scanning with push protection
- ✅ Dependency review on all pull requests
- ✅ Dependabot security updates enabled
Branch Protection Rules
Configure branch protection to enforce security checks:
# Using GitHub CLI to configure branch protection
gh api "repos/{owner}/{repo}/branches/main/protection" \
-X PUT \
-H "Accept: application/vnd.github+json" \
-f "required_status_checks[strict]=true" \
-f "required_status_checks[contexts][]=CodeQL" \
-f "required_status_checks[contexts][]=dependency-review" \
-f "required_pull_request_reviews[required_approving_review_count]=1" \
-f "required_pull_request_reviews[dismiss_stale_reviews]=true" \
-f "enforce_admins=true" \
-f "restrictions=null"
Repository Rulesets
GitHub rulesets provide more granular control:
# Example ruleset configuration (via UI or API)
name: Security Enforcement
target: branch
enforcement: active
conditions:
ref_name:
include:
- refs/heads/main
- refs/heads/release/*
rules:
- type: required_status_checks
parameters:
required_status_checks:
- context: "CodeQL"
integration_id: 0
- context: "Dependency Review"
integration_id: 0
strict_required_status_checks_policy: true
- type: pull_request
parameters:
required_approving_review_count: 1
dismiss_stale_reviews_on_push: true
require_code_owner_review: true
Best Practices for GHAS Management
Initial Rollout Strategy
Start with Pilot Repositories
- Enable on 3-5 representative repositories
- Learn alert patterns and false positive rates
- Document triage procedures
Triage Existing Alerts
- Prioritize critical and high severity
- Dismiss false positives with clear documentation
- Create remediation plan for legitimate issues
Gradual Expansion
- Roll out to additional repositories in phases
- Use security overview to track progress
- Adjust configurations based on learnings
Full Coverage
- Enable on all repositories
- Enforce through organization policies
- Monitor and maintain continuously
Alert Triage Process
## Alert Triage Workflow
1. **Initial Review** (< 1 hour)
- Verify alert is legitimate (not false positive)
- Assess severity and potential impact
- Assign to appropriate team member
2. **Analysis** (< 1 day)
- Understand the vulnerability context
- Determine exploitability
- Identify affected code paths
3. **Prioritization**
- Critical: Fix within 24 hours
- High: Fix within 1 week
- Medium: Fix within 1 sprint
- Low: Fix as time permits
4. **Remediation**
- Create issue/ticket for tracking
- Develop and test fix
- Submit PR with security fix template
- Request security review
5. **Verification**
- Confirm alert is closed
- Run regression tests
- Update documentation if needed
Maintenance Schedule
# Recommended maintenance cadence
Weekly:
- Review new alerts from security overview
- Triage and assign critical/high severity alerts
- Check Dependabot PR queue
Monthly:
- Review security feature coverage
- Update custom query packs if needed
- Review dismissed alerts for patterns
Quarterly:
- Full security posture review
- Update security policies
- Review and rotate service account tokens
- Training refresher for team
Annually:
- Comprehensive security audit
- GHAS configuration review
- Update incident response procedures
Integration with Development Workflow
# Example PR workflow with security gates
# .github/workflows/pr-security-checks.yml
name: PR Security Checks
on:
pull_request:
branches: [main, develop]
jobs:
security-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run CodeQL Analysis
uses: github/codeql-action/analyze@v3
- name: Dependency Review
uses: actions/dependency-review-action@v4
with:
fail-on-severity: high
- name: Check for Secrets
uses: trufflesecurity/trufflehog@main
with:
path: ./
- name: Security Summary
if: always()
run: |
echo "## Security Check Summary" >> $GITHUB_STEP_SUMMARY
echo "- CodeQL: Complete" >> $GITHUB_STEP_SUMMARY
echo "- Dependency Review: Complete" >> $GITHUB_STEP_SUMMARY
echo "- Secret Scanning: Complete" >> $GITHUB_STEP_SUMMARY
Troubleshooting Common Issues
Code Scanning Not Running
Problem: CodeQL workflow not triggering or failing
Solutions:
- Check workflow syntax
- Verify language detection
- Check for build failures
- Review action logs for specific errors
# Debug CodeQL analysis
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript
debug: true
High False Positive Rate
Problem: Too many alerts that aren’t real vulnerabilities
Solutions:
- Review and adjust query suites
- Add path exclusions for test code
- Use inline suppressions where appropriate
- Report false positives to improve queries
# Exclude test directories
config-file: |
paths-ignore:
- '**/test/**'
- '**/tests/**'
- '**/__tests__/**'
- '**/*.test.*'
- '**/*.spec.*'
Secret Scanning Missing Secrets
Problem: Known secrets not being detected
Solutions:
- Verify secret format matches known patterns
- Create custom patterns for internal secrets
- Check if secret is in excluded paths
- Report to GitHub partner program
Dependency Review Blocking PRs
Problem: PRs blocked by vulnerable dependencies
Solutions:
- Update the vulnerable dependency
- If update not available, assess risk and allow temporarily
- Use
allow-ghsasto bypass specific advisories - Create security exception process
Conclusion
GitHub Advanced Security provides a comprehensive suite of tools for securing your codebase. By properly configuring code scanning, secret scanning, and dependency review, you can identify and remediate vulnerabilities before they reach production.
Key takeaways:
- Enable Progressively: Start with pilot repositories, then expand
- Automate Where Possible: Use Dependabot, auto-merge, and scheduled workflows
- Integrate into Workflow: Make security checks part of the PR process
- Monitor Continuously: Use security overview for ongoing visibility
- Document Everything: Clear policies and procedures improve response times
- Train Your Team: Ensure everyone understands how to use and respond to GHAS
The investment in setting up and maintaining GitHub Advanced Security pays dividends through:
- Reduced vulnerability exposure
- Faster security remediation
- Better compliance posture
- Improved developer security awareness
Start your GitHub Advanced Security journey today by enabling features on a pilot repository and building from there.