Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/detect-bounty-issue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Detect Bounty Issue on PR Merge

on:
pull_request:
types: [closed]

jobs:
detect-bounty:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
Comment on lines +7 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add explicit permissions block following least-privilege principle.

The workflow does not define explicit permissions for GITHUB_TOKEN. Following security best practices, you should limit permissions to only what's required.

As per coding guidelines, apply this diff to add minimal permissions:

 jobs:
   detect-bounty:
     if: github.event.pull_request.merged == true
     runs-on: ubuntu-latest
+    permissions:
+      issues: read
+      pull-requests: read
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
jobs:
detect-bounty:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
jobs:
detect-bounty:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
permissions:
issues: read
pull-requests: read
🤖 Prompt for AI Agents
.github/workflows/detect-bounty-issue.yml lines 7-10: the workflow lacks an
explicit permissions block for GITHUB_TOKEN; add a top-level permissions section
to follow least-privilege. Add a permissions block (at workflow root, above
jobs) granting only the scopes required (for example: issues: write and
contents: read) and remove any broader defaults so the workflow can
create/update issues but nothing else.


steps:
- name: Check for linked bounty issue
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const pr = context.payload.pull_request;
const body = pr.body || "";

const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi);
if (!matches) {
console.log("No linked issues found");
return;
}
Comment on lines +21 to +25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

❓ Verification inconclusive

Script executed:

#!/bin/bash
# Find the specific file and read it
find . -name "detect-bounty-issue.yml" -o -name "*.yml" -path "*github/workflows*" | head -5

Repository: OWASP-BLT/BLT


Repository: OWASP-BLT/BLT
Exit code: 0

stdout:

./.github/workflows/add-changes-requested-label.yml
./.github/workflows/add-comment-count-label.yml
./.github/workflows/add-files-changed-label.yml
./.github/workflows/add-last-active-label.yml
./.github/workflows/add-migrations-label.yml

Script executed:

fd "detect-bounty-issue" --type f

Repository: OWASP-BLT/BLT


Repository: OWASP-BLT/BLT
Exit code: 0


Script executed:

find . -path "*workflows*" -name "*.yml" -o -path "*workflows*" -name "*.yaml" 2>/dev/null | head -10

Repository: OWASP-BLT/BLT


Repository: OWASP-BLT/BLT
Exit code: 0

stdout:

./.github/workflows/add-changes-requested-label.yml
./.github/workflows/add-comment-count-label.yml
./.github/workflows/add-files-changed-label.yml
./.github/workflows/add-last-active-label.yml
./.github/workflows/add-migrations-label.yml
./.github/workflows/assign-issues.yml
./.github/workflows/assign-new-issues-to-copilot.yml
./.github/workflows/auto-approve-dependabot.yml
./.github/workflows/auto-fix-main-precommit.yml
./.github/workflows/auto-fix-pr-precommit.yml

Script executed:

find . -name "*detect*bounty*" -o -name "*bounty*issue*" 2>/dev/null

Repository: OWASP-BLT/BLT


Repository: OWASP-BLT/BLT
Exit code: 0

stdout:

./.github/workflows/detect-bounty-issue.yml

Script executed:

grep -r "const matches = body.match" .github/workflows/ 2>/dev/null | head -5

Repository: OWASP-BLT/BLT


Repository: OWASP-BLT/BLT
Exit code: 0

stdout:

.github/workflows/detect-bounty-issue.yml:            const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi);

Script executed:

cat ./.github/workflows/detect-bounty-issue.yml 2>/dev/null || echo "File not found"

Repository: OWASP-BLT/BLT


Repository: OWASP-BLT/BLT
Exit code: 0

stdout:

name: Detect Bounty Issue on PR Merge

on:
  pull_request:
    types: [closed]

jobs:
  detect-bounty:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest

    steps:
      - name: Check for linked bounty issue
        uses: actions/github-script@v6
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const pr = context.payload.pull_request;
            const body = pr.body || "";

            const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi);
            if (!matches) {
              console.log("No linked issues found");
              return;
            }

            for (const ref of matches) {
              const issueNumber = ref.match(/#(\d+)/)[1];
              const issue = await github.rest.issues.get({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issueNumber,
              });

              const hasBounty = issue.data.labels.some(
                label => label.name.includes("$")
              );

              if (hasBounty) {
                console.log(
                  `Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}`
                );
              }
            }

Add missing GitHub closing keywords to issue reference detection.

GitHub's official closing keywords are: close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved. The current regex pattern only includes 6 of these 9 keywords and is missing "resolve", "resolves", and "resolved".

Update the regex to include all supported variants:

-            const matches = body.match(/(close|closes|closed|fix|fixes|fixed)\s+#(\d+)/gi);
+            const matches = body.match(/(close[sd]?|fix(e[sd])?|resolve[sd]?)\s*#(\d+)/gi);

This adds the missing keywords and makes whitespace optional (GitHub's linking parser is generally flexible with spacing).

🤖 Prompt for AI Agents
.github/workflows/detect-bounty-issue.yml around lines 21 to 25: the regex that
finds issue-closing keywords is missing the "resolve/resolves/resolved" variants
and doesn't allow optional whitespace before the issue number; update the
pattern to include resolve, resolves, resolved and allow an optional space (e.g.
\s* ) between the keyword and the # so it matches all GitHub closing keywords
and flexible spacing.


for (const ref of matches) {
const issueNumber = ref.match(/#(\d+)/)[1];
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The issueNumber variable is passed as a string to the github.rest.issues.get API call, which expects an integer for the issue_number parameter, causing the call to fail.
Severity: CRITICAL | Confidence: High

🔍 Detailed Analysis

The issueNumber variable is extracted from a regex match, resulting in a string value. This string is then passed directly as the issue_number parameter to the github.rest.issues.get() API call. The GitHub REST API and its Octokit client wrapper expect this parameter to be an integer, not a string. Passing the incorrect type will cause the API call to fail, which will break the bounty detection workflow. Evidence from a similar, existing workflow shows the use of parseInt() to correctly cast the value to an integer before making the API call, confirming this is a required step.

💡 Suggested Fix

Convert the issueNumber variable to an integer before passing it to the github.rest.issues.get() API call. You can achieve this by changing line 32 to issue_number: parseInt(issueNumber). This ensures the API receives the expected data type.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: .github/workflows/detect-bounty-issue.yml#L32

Potential issue: The `issueNumber` variable is extracted from a regex match, resulting
in a string value. This string is then passed directly as the `issue_number` parameter
to the `github.rest.issues.get()` API call. The GitHub REST API and its Octokit client
wrapper expect this parameter to be an integer, not a string. Passing the incorrect type
will cause the API call to fail, which will break the bounty detection workflow.
Evidence from a similar, existing workflow shows the use of `parseInt()` to correctly
cast the value to an integer before making the API call, confirming this is a required
step.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 7655094

});
Comment on lines +27 to +33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for issue API calls.

The workflow will fail if any referenced issue cannot be fetched (e.g., issue doesn't exist, API rate limit, permission issues). The workflow should handle errors gracefully and continue checking remaining issues.

Apply this diff to add error handling:

             for (const ref of matches) {
               const issueNumber = ref.match(/#(\d+)/)[1];
-              const issue = await github.rest.issues.get({
-                owner: context.repo.owner,
-                repo: context.repo.repo,
-                issue_number: issueNumber,
-              });
+              try {
+                const issue = await github.rest.issues.get({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: issueNumber,
+                });
             
-              const hasBounty = issue.data.labels.some(
-                label => label.name.includes("$")
-              );
+                const hasBounty = issue.data.labels.some(
+                  label => label.name.includes("$")
+                );
             
-              if (hasBounty) {
-                console.log(
-                  `Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}`
-                );
-              }
+                if (hasBounty) {
+                  console.log(
+                    `Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}`
+                  );
+                }
+              } catch (error) {
+                console.log(`Failed to fetch issue #${issueNumber}: ${error.message}`);
+              }
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const ref of matches) {
const issueNumber = ref.match(/#(\d+)/)[1];
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
for (const ref of matches) {
const issueNumber = ref.match(/#(\d+)/)[1];
try {
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
const hasBounty = issue.data.labels.some(
label => label.name.includes("$")
);
if (hasBounty) {
console.log(
`Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}`
);
}
} catch (error) {
console.log(`Failed to fetch issue #${issueNumber}: ${error.message}`);
}
}
🤖 Prompt for AI Agents
In .github/workflows/detect-bounty-issue.yml around lines 27 to 33, the call to
github.rest.issues.get assumes every referenced issue exists and will throw on
not-found, rate limits, or permission errors; wrap the API call in a try/catch,
validate the regex match before accessing group 1, and on error log a warning
(or set a flag) and continue to the next ref instead of letting the workflow
fail; ensure the rest of the loop uses a safely scoped issue variable (skip
processing when the fetch failed).


const hasBounty = issue.data.labels.some(
label => label.name.includes("$")
);

if (hasBounty) {
console.log(
`Bounty issue detected: #${issueNumber} | Labels: ${issue.data.labels.map(l => l.name).join(", ")}`
);
}
}
Comment on lines +9 to +44

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}
Loading