GitHub Malicious Commit Content
Description
Detects malicious patterns in GitHub commit content including commit messages, author names, and author emails. These fields can contain injection payloads that may be executed by vulnerable CI/CD workflows or git hooks. This rule is particularly important as commit metadata is often trusted and may be processed unsafely. Based on patterns from the Nx vulnerability (GHSA-cxm3-wv7p-598c).
Query · python
from panther_github_helpers import (
contains_bash_injection_pattern,
get_matched_bash_patterns,
github_reference_url,
github_webhook_alert_context,
)
def rule(event):
# Check for push events with commits
if not (event.get("commits") or event.get("head_commit")):
return False
# Check head_commit fields (single commit in push)
if head_commit := event.get("head_commit"):
fields_to_check = [
head_commit.get("message"),
head_commit.get("author", {}).get("email"),
head_commit.get("author", {}).get("name"),
]
for field in fields_to_check:
if contains_bash_injection_pattern(field):
return True
# Check all commits in the push
for commit in event.get("commits", []):
commit_fields = [
commit.get("message"),
commit.get("author", {}).get("email"),
commit.get("author", {}).get("name"),
]
for field in commit_fields:
if contains_bash_injection_pattern(field):
return True
return False
def title(event):
repo_name = event.deep_get("repository", "full_name", default="<UNKNOWN_REPO>")
ref = event.get("ref", "<UNKNOWN_REF>")
return f"Malicious pattern detected in commit content in {repo_name} on {ref}"
def alert_context(event):
context = github_webhook_alert_context(event)
context["malicious_commits"] = []
# Analyze head_commit
if head_commit := event.get("head_commit"):
commit_analysis = _analyze_commit(head_commit)
if commit_analysis["has_malicious_patterns"]:
context["malicious_commits"].append(commit_analysis)
# Analyze all commits
for commit in event.get("commits", []):
commit_analysis = _analyze_commit(commit)
if commit_analysis["has_malicious_patterns"]:
context["malicious_commits"].append(commit_analysis)
return context
def _analyze_commit(commit):
"""Analyze a single commit for malicious patterns."""
analysis = {
"commit_id": commit.get("id"),
"message": commit.get("message"),
"author": commit.get("author", {}).get("name"),
"author_email": commit.get("author", {}).get("email"),
"timestamp": commit.get("timestamp"),
"url": commit.get("url"),
"has_malicious_patterns": False,
"field_analysis": {},
}
# Check message
if message := commit.get("message"):
patterns = get_matched_bash_patterns(message)
if patterns:
analysis["has_malicious_patterns"] = True
analysis["field_analysis"]["message"] = {
"value": message,
"matched_patterns": patterns,
}
# Check author email
if author_email := commit.get("author", {}).get("email"):
patterns = get_matched_bash_patterns(author_email)
if patterns:
analysis["has_malicious_patterns"] = True
analysis["field_analysis"]["author_email"] = {
"value": author_email,
"matched_patterns": patterns,
}
# Check author name
if author_name := commit.get("author", {}).get("name"):
patterns = get_matched_bash_patterns(author_name)
if patterns:
analysis["has_malicious_patterns"] = True
analysis["field_analysis"]["author_name"] = {
"value": author_name,
"matched_patterns": patterns,
}
return analysis
def reference(event):
# Try to get the compare URL
if compare_url := event.get("compare"):
return compare_url
# Try head commit URL
if head_commit_url := event.deep_get("head_commit", "url"):
return head_commit_url
if reference_url := github_reference_url(event):
return reference_url
return "DEFAULT"
Analyst notes
- Immediately investigate the commits identified with malicious patterns
- Check if the author account may be compromised
- Review all workflows and git hooks that process commit messages or author information
- Look for signs of code execution in CI/CD logs
- Revert malicious commits if confirmed
- Reset credentials if the author account is compromised
- Review repository access logs for suspicious activity
- Consider temporarily disabling vulnerable workflows
- Implement input sanitization for commit metadata processing
- Contact the repository owner and security team