Query Details

Pull Request Policy By Pass

Query

id: 63cd5f0b-ab93-4461-b2bc-525c3a6482b7
name: 'GitHub Pull Request Policy Bypassing - Historic allow list'
description: |
  'This detection builds an allow list of historic PR policy bypasses and compares to recent history, flagging pull request bypasses that are not manually in the allow list and not historically included in the allow list.'
severity: High
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Execution
relevantTechniques:
  - T1098
query: |
  let starttime = 14d;
  let endtime = 2d;
  // Add GitHub user names to Authorized Bypassers to ignore policy bypasses by certain authorized users
  let AuthorizedBypassers = dynamic(['GitHub1', 'GitHub2']);
  let historicBypassers = GitHubAuditLogPolling_CL
  | where TimeGenerated between (ago(starttime) .. ago(endtime))
  | where action_s == "protected_branch.policy_override"
  | distinct actor_s;
  GitHubAuditLogPolling_CL
  | where TimeGenerated >= ago(endtime)
  | where action_s == "protected_branch.policy_override"
  | where actor_s !in (historicBypassers) and actor_s !in (AuthorizedBypassers)
  | extend date_time = unixtime_milliseconds_todatetime(_timestamp_d)
  | extend organization = split(repo_s, "/")[0]
  | extend repository = split(repo_s, "/")[1]
  | project TimeGenerated = date_time, AccountCustomEntity = actor_s, organization = org_s, repository, branch = branch_s, action = action_s
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountCustomEntity
version: 1.0.0

Explanation

This query is designed to detect instances where GitHub pull request policies have been bypassed. It creates an allow list of historic bypasses and compares it to recent history. If a pull request bypass is not manually in the allow list and is not historically included in the allow list, it will be flagged. The severity of this detection is high. The query is run daily and looks at data from the past day. The query uses the GitHubAuditLogPolling_CL table to gather the necessary data. It also allows for the addition of authorized users to ignore their bypasses. The query maps the detected accounts to the "Account" entity type using the "FullName" field.

Details

Thomas Naunheim profile picture

Thomas Naunheim

Released: January 29, 2022

Tables

GitHubAuditLogPolling_CL

Keywords

GitHub,PullRequest,Policy,Bypassing,Historic,AllowList,Detection,PR,Bypasses,AuthorizedBypassers,GitHub1,GitHub2,historicBypassers,GitHubAuditLogPolling_CL,TimeGenerated,ago,startime,endtime,action_s,protected_branch.policy_override,actor_s,distinct,unixtime_milliseconds_todatetime,_timestamp_d,organization,repo_s,split,project,AccountCustomEntity,actor_s,org_s,repository,branch_s,action_s,entityMappings,Account,FullName

Operators

letwheredistinctextendinsplitproject

Actions