Skip to content

Commit a159395

Browse files
committed
fix: prevent 'merge' branch detection from GitHub virtual refs
- Use GITHUB_HEAD_REF for PR events instead of GITHUB_REF (refs/pull/123/merge) - GITHUB_REF contains virtual merge refs like 'refs/pull/123/merge' for PR events - GITHUB_HEAD_REF contains the actual source branch name for PRs - Added detection for virtual merge refs and skip them explicitly - Added comprehensive tests for both PR and push branch detection scenarios - Resolves issue with scans showing branch='merge' and virtual commit messages
1 parent 90415cb commit a159395

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

socketsecurity/core/git_interface.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,21 @@ def __init__(self, path: str):
111111
gitlab_branch = os.getenv('CI_COMMIT_BRANCH') or os.getenv('CI_MERGE_REQUEST_SOURCE_BRANCH_NAME')
112112

113113
# GitHub Actions variables
114-
github_ref = os.getenv('GITHUB_REF') # e.g., 'refs/heads/main'
114+
github_ref = os.getenv('GITHUB_REF') # e.g., 'refs/heads/main' or 'refs/pull/123/merge'
115+
github_head_ref = os.getenv('GITHUB_HEAD_REF') # PR source branch name
115116
github_branch = None
116-
if github_ref and github_ref.startswith('refs/heads/'):
117+
118+
# For PR events, use GITHUB_HEAD_REF (actual branch name), not GITHUB_REF (virtual merge ref)
119+
if github_event_name == 'pull_request' and github_head_ref:
120+
github_branch = github_head_ref
121+
log.debug(f"GitHub PR event - using GITHUB_HEAD_REF: {github_branch}")
122+
elif github_ref and github_ref.startswith('refs/heads/'):
117123
github_branch = github_ref.replace('refs/heads/', '')
124+
log.debug(f"GitHub push event - using GITHUB_REF: {github_branch}")
125+
elif github_ref and github_ref.startswith('refs/pull/') and github_ref.endswith('/merge'):
126+
# Fallback: if we somehow miss the PR detection above, don't use the virtual merge ref
127+
log.debug(f"GitHub virtual merge ref detected, skipping: {github_ref}")
128+
github_branch = None
118129

119130
# Bitbucket Pipelines variables
120131
bitbucket_branch = os.getenv('BITBUCKET_BRANCH')

tests/core/test_git_interface.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,3 +812,52 @@ def test_github_push_event_uses_github_sha(self, git_instance, caplog):
812812
debug_messages = [record.message for record in caplog.records if record.levelname == "DEBUG"]
813813
virtual_commit_logs = [msg for msg in debug_messages if "ignoring GITHUB_SHA (virtual merge commit)" in msg]
814814
assert len(virtual_commit_logs) == 0, f"Should not ignore GITHUB_SHA for push events: {debug_messages}"
815+
816+
def test_github_pr_branch_detection_uses_head_ref(self, git_instance, caplog):
817+
"""
818+
Test that GitHub PR events use GITHUB_HEAD_REF for branch name, not virtual merge ref.
819+
820+
GitHub sets GITHUB_REF=refs/pull/123/merge for PR events, but we should use
821+
GITHUB_HEAD_REF which contains the actual source branch name.
822+
"""
823+
with caplog.at_level(logging.DEBUG):
824+
# Simulate GitHub PR environment with virtual merge ref
825+
with patch.dict(os.environ, {
826+
'GITHUB_EVENT_NAME': 'pull_request',
827+
'GITHUB_REF': 'refs/pull/123/merge', # Virtual merge ref
828+
'GITHUB_HEAD_REF': 'feature-branch', # Actual branch name
829+
'GITHUB_SHA': 'abc123virtual', # Virtual merge commit (ignored)
830+
}, clear=True):
831+
# Create new Git instance to trigger branch detection logic
832+
git_instance_new = Git(git_instance.path)
833+
834+
# Should use GITHUB_HEAD_REF for branch name
835+
assert git_instance_new.branch == 'feature-branch'
836+
837+
# Should log that GITHUB_HEAD_REF is being used
838+
debug_messages = [record.message for record in caplog.records if record.levelname == "DEBUG"]
839+
head_ref_logs = [msg for msg in debug_messages if "using GITHUB_HEAD_REF: feature-branch" in msg]
840+
assert len(head_ref_logs) >= 1, f"Expected GITHUB_HEAD_REF log, got: {debug_messages}"
841+
842+
def test_github_push_branch_detection_uses_ref(self, git_instance, caplog):
843+
"""
844+
Test that GitHub push events use GITHUB_REF for branch name.
845+
"""
846+
with caplog.at_level(logging.DEBUG):
847+
# Simulate GitHub push environment
848+
with patch.dict(os.environ, {
849+
'GITHUB_EVENT_NAME': 'push',
850+
'GITHUB_REF': 'refs/heads/main', # Normal branch ref
851+
'GITHUB_HEAD_REF': '', # Not set for push events
852+
'GITHUB_SHA': git_instance.commit.hexsha, # Real commit
853+
}, clear=True):
854+
# Create new Git instance to trigger branch detection logic
855+
git_instance_new = Git(git_instance.path)
856+
857+
# Should use GITHUB_REF for branch name
858+
assert git_instance_new.branch == 'main'
859+
860+
# Should log that GITHUB_REF is being used
861+
debug_messages = [record.message for record in caplog.records if record.levelname == "DEBUG"]
862+
ref_logs = [msg for msg in debug_messages if "using GITHUB_REF: main" in msg]
863+
assert len(ref_logs) >= 1, f"Expected GITHUB_REF log, got: {debug_messages}"

0 commit comments

Comments
 (0)