Panther medium experimental python
GitHub Commits Skipping Workflows
Detects commits from cross-fork scenarios that contain workflow skip directives, which bypass GitHub Actions workflows. These skip patterns ([skip ci], [ci skip], [no ci], [skip actions], [actions skip], skip-checks:true) can be used to avoid security checks and CI/CD processes. This rule only alerts on commits to public forkable repositories.
Detection Logic
import re
from panther_github_helpers import github_reference_url, github_webhook_alert_context
SKIP_PATTERNS = [
r"\[skip ci\]",
r"\[ci skip\]",
r"\[no ci\]",
r"\[skip actions\]",
r"\[actions skip\]",
r"skip-checks:\s*true",
]
COMPILED_PATTERNS = [re.compile(pattern, re.IGNORECASE) for pattern in SKIP_PATTERNS]
def rule(event):
if not event.get("pusher"):
return False
repo = event.get("repository", {})
if repo.get("private") or not repo.get("allow_forking"):
return False
messages = event.deep_walk("commits", "message")
if not isinstance(messages, list):
messages = [messages]
for message in messages:
if _has_skip_pattern(message):
return True
return False
def _has_skip_pattern(message):
if not message:
return False
return any(pattern.search(message) for pattern in COMPILED_PATTERNS)
def title(event):
repo_name = event.deep_get("repository", "full_name", default="<UNKNOWN_REPO>")
head_commit = event.deep_get("head_commit", default={})
commit_sha = head_commit.get("id", "<NO_SHA>")[:8]
return f"Cross-fork workflow skip commit detected in {repo_name} ({commit_sha})"
def alert_context(event):
context = github_webhook_alert_context(event)
skip_commits = []
commits = event.get("commits", [{}])
for commit in commits:
commit_message = commit.get("message", "")
if _has_skip_pattern(commit_message):
matched_patterns = [
SKIP_PATTERNS[i]
for i, pattern in enumerate(COMPILED_PATTERNS)
if pattern.search(commit_message)
]
skip_commits.append(
{
"id": commit.get("id"),
"message": commit_message,
"author": commit.get("author", {}).get("name"),
"matched_patterns": matched_patterns,
}
)
context["skip_commits"] = skip_commits
return context
def reference(event):
if reference_url := github_reference_url(event):
return reference_url
return "DEFAULT" Field Validations
Loading…
Comments (0)
Loading comments...