From 43e096520117d85d2d4b2684db926f0d3bc4ed57 Mon Sep 17 00:00:00 2001 From: aconite33 Date: Mon, 30 Mar 2026 14:19:27 -0600 Subject: [PATCH 1/7] ci: add CLA workflow --- .github/workflows/cla.yml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/cla.yml diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml new file mode 100644 index 0000000..05a0594 --- /dev/null +++ b/.github/workflows/cla.yml @@ -0,0 +1,39 @@ +name: "CLA Assistant" +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened, closed, synchronize] + +permissions: + actions: write + contents: write + pull-requests: write + statuses: write + +jobs: + CLAAssistant: + runs-on: ubuntu-latest + steps: + - name: Generate token from GitHub App + id: app-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: blacklanternsecurity + repositories: CLA + + - name: "CLA Assistant" + if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' + uses: contributor-assistant/github-action@v2.6.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PERSONAL_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }} + with: + path-to-signatures: "signatures/version1/cla.json" + path-to-document: "https://github.com/blacklanternsecurity/CLA/blob/main/ICLA.md" + branch: "main" + allowlist: "dependabot[bot],github-actions[bot],renovate[bot]" + remote-organization-name: "blacklanternsecurity" + remote-repository-name: "CLA" From 4c3af4d611a1c99da39be3243ae3d30f526238dc Mon Sep 17 00:00:00 2001 From: aconite33 Date: Mon, 30 Mar 2026 16:38:30 -0600 Subject: [PATCH 2/7] ci: add org members to CLA allowlist --- .github/workflows/cla.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 05a0594..825a076 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -34,6 +34,6 @@ jobs: path-to-signatures: "signatures/version1/cla.json" path-to-document: "https://github.com/blacklanternsecurity/CLA/blob/main/ICLA.md" branch: "main" - allowlist: "dependabot[bot],github-actions[bot],renovate[bot]" + allowlist: "dependabot[bot],github-actions[bot],renovate[bot],aconite33,adeemm,ausmaster,bbot-deploy,blsaccess,blscode,en0f,GabKodes,holsick,jackpas23,kerrymilan,kevinoriley,liquidsec,lunarcowboy,MarcusAmes,Mercury0,MrBlackout20,Nasaltron,oversiemulated,pentestpop,pjhartlieb,RReski,shart123456,SpamFaux,stryker2k2,Sw3d1shPh1sh,TheFunky1Markimark,theo2612,TheTechromancer,TMDeal" remote-organization-name: "blacklanternsecurity" remote-repository-name: "CLA" From 5e001b2438fca9f48e9a4e8673da519a4928cf39 Mon Sep 17 00:00:00 2001 From: aconite33 Date: Mon, 30 Mar 2026 16:43:15 -0600 Subject: [PATCH 3/7] ci: use dynamic org membership check for CLA --- .github/workflows/cla.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 825a076..462636a 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -24,8 +24,23 @@ jobs: owner: blacklanternsecurity repositories: CLA + - name: Check org membership + id: membership + if: github.event_name == 'pull_request_target' + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + run: | + AUTHOR="${{ github.event.pull_request.user.login }}" + if gh api "orgs/blacklanternsecurity/members/$AUTHOR" > /dev/null 2>&1; then + echo "is_member=true" >> "$GITHUB_OUTPUT" + else + echo "is_member=false" >> "$GITHUB_OUTPUT" + fi + - name: "CLA Assistant" - if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' + if: | + (steps.membership.outputs.is_member != 'true') && + ((github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target') uses: contributor-assistant/github-action@v2.6.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -34,6 +49,6 @@ jobs: path-to-signatures: "signatures/version1/cla.json" path-to-document: "https://github.com/blacklanternsecurity/CLA/blob/main/ICLA.md" branch: "main" - allowlist: "dependabot[bot],github-actions[bot],renovate[bot],aconite33,adeemm,ausmaster,bbot-deploy,blsaccess,blscode,en0f,GabKodes,holsick,jackpas23,kerrymilan,kevinoriley,liquidsec,lunarcowboy,MarcusAmes,Mercury0,MrBlackout20,Nasaltron,oversiemulated,pentestpop,pjhartlieb,RReski,shart123456,SpamFaux,stryker2k2,Sw3d1shPh1sh,TheFunky1Markimark,theo2612,TheTechromancer,TMDeal" + allowlist: "dependabot[bot],github-actions[bot],renovate[bot]" remote-organization-name: "blacklanternsecurity" remote-repository-name: "CLA" From f1d92b969b4080ccd158463535d1fa8b48650d28 Mon Sep 17 00:00:00 2001 From: aconite33 Date: Mon, 30 Mar 2026 21:18:35 -0600 Subject: [PATCH 4/7] fix: use org-scoped app token for reliable CLA membership check --- .github/workflows/cla.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 462636a..8300a05 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -22,21 +22,34 @@ jobs: app-id: ${{ secrets.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} owner: blacklanternsecurity - repositories: CLA - name: Check org membership id: membership - if: github.event_name == 'pull_request_target' env: GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | - AUTHOR="${{ github.event.pull_request.user.login }}" - if gh api "orgs/blacklanternsecurity/members/$AUTHOR" > /dev/null 2>&1; then + if [ "${{ github.event_name }}" = "pull_request_target" ]; then + AUTHOR="${{ github.event.pull_request.user.login }}" + else + PR_NUM="${{ github.event.issue.number }}" + AUTHOR=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUM" --jq '.user.login' 2>/dev/null) + fi + if [ -n "$AUTHOR" ] && gh api "orgs/blacklanternsecurity/members/$AUTHOR" > /dev/null 2>&1; then echo "is_member=true" >> "$GITHUB_OUTPUT" else echo "is_member=false" >> "$GITHUB_OUTPUT" fi + - name: Skip CLA for org members + if: steps.membership.outputs.is_member == 'true' && github.event_name == 'pull_request_target' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh api --method POST "repos/${{ github.repository }}/statuses/${{ github.event.pull_request.head.sha }}" \ + -f state=success \ + -f context="CLAAssistant" \ + -f description="CLA check skipped — author is an org member" + - name: "CLA Assistant" if: | (steps.membership.outputs.is_member != 'true') && From 9b932b3f42d42161eeb53ba96e15ac890f9252a9 Mon Sep 17 00:00:00 2001 From: aconite33 Date: Tue, 31 Mar 2026 08:30:30 -0600 Subject: [PATCH 5/7] fix: disable lock-pullrequest-aftermerge in CLA workflow --- .github/workflows/cla.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 8300a05..bb9c379 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -65,3 +65,4 @@ jobs: allowlist: "dependabot[bot],github-actions[bot],renovate[bot]" remote-organization-name: "blacklanternsecurity" remote-repository-name: "CLA" + lock-pullrequest-aftermerge: "false" From 828879a2541e6a0a3c1f6154a04bb8883bd5de33 Mon Sep 17 00:00:00 2001 From: aconite33 Date: Wed, 1 Apr 2026 13:53:00 -0600 Subject: [PATCH 6/7] update CLA workflow: API-based bot detection, check all committers, reduce permissions --- .github/workflows/cla.yml | 59 +++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index bb9c379..3fadea2 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -6,8 +6,6 @@ on: types: [opened, closed, synchronize] permissions: - actions: write - contents: write pull-requests: write statuses: write @@ -23,36 +21,67 @@ jobs: private-key: ${{ secrets.APP_PRIVATE_KEY }} owner: blacklanternsecurity - - name: Check org membership - id: membership + - name: Check all committers against org and allowlist + id: cla-check env: GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | if [ "${{ github.event_name }}" = "pull_request_target" ]; then - AUTHOR="${{ github.event.pull_request.user.login }}" + PR_NUM="${{ github.event.pull_request.number }}" else PR_NUM="${{ github.event.issue.number }}" - AUTHOR=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUM" --jq '.user.login' 2>/dev/null) - fi - if [ -n "$AUTHOR" ] && gh api "orgs/blacklanternsecurity/members/$AUTHOR" > /dev/null 2>&1; then - echo "is_member=true" >> "$GITHUB_OUTPUT" - else - echo "is_member=false" >> "$GITHUB_OUTPUT" fi - - name: Skip CLA for org members - if: steps.membership.outputs.is_member == 'true' && github.event_name == 'pull_request_target' + COMMITTERS=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUM/commits" --paginate --jq '.[].author.login' | sort -u) + ALL_EXEMPT=true + + for LOGIN in $COMMITTERS; do + # treat commits with no associated GitHub login as non-exempt + if [ -z "$LOGIN" ] || [ "$LOGIN" = "null" ]; then + echo "Unknown committer (no GitHub login) — not exempt" + ALL_EXEMPT=false + break + fi + + EXEMPT=false + + # check if account type is Bot (GitHub App accounts) + AUTHOR_TYPE=$(gh api "users/${LOGIN}" --jq '.type' 2>/dev/null || echo "Unknown") + if [ "$AUTHOR_TYPE" = "Bot" ]; then + echo "$LOGIN is a Bot account — exempt" + EXEMPT=true + fi + + # check org membership + if [ "$EXEMPT" = "false" ]; then + if gh api "orgs/blacklanternsecurity/members/$LOGIN" > /dev/null 2>&1; then + echo "$LOGIN is an org member — exempt" + EXEMPT=true + fi + fi + + if [ "$EXEMPT" = "false" ]; then + echo "$LOGIN is not exempt — CLA required" + ALL_EXEMPT=false + break + fi + done + + echo "all_exempt=$ALL_EXEMPT" >> "$GITHUB_OUTPUT" + + - name: Skip CLA when all committers are exempt + if: steps.cla-check.outputs.all_exempt == 'true' && github.event_name == 'pull_request_target' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh api --method POST "repos/${{ github.repository }}/statuses/${{ github.event.pull_request.head.sha }}" \ -f state=success \ -f context="CLAAssistant" \ - -f description="CLA check skipped — author is an org member" + -f description="CLA check skipped — all committers are org members or bots" - name: "CLA Assistant" if: | - (steps.membership.outputs.is_member != 'true') && + (steps.cla-check.outputs.all_exempt != 'true') && ((github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target') uses: contributor-assistant/github-action@v2.6.1 env: From 6a7aa49ca4195a3b59cc5b8a073af74cf968658c Mon Sep 17 00:00:00 2001 From: aconite33 Date: Wed, 1 Apr 2026 13:53:13 -0600 Subject: [PATCH 7/7] update CLA workflow: API-based bot detection, check all committers, reduce permissions