Skip to content

Commit 2e607fe

Browse files
Merge pull request #724 from AlexNPavel/fix-security-scanner-findings
Fix security scanner findings: XSS, SSRF, and unsafe jQuery pattern
2 parents 2cf290b + 201c7a1 commit 2e607fe

4 files changed

Lines changed: 27 additions & 5 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
.dccache
1212
python-env
13+
__pycache__/
1314

1415
.scannerwork/
1516
coverage.out

cmd/release-controller-api/http_compare.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"fmt"
5+
"html"
56
"net/http"
67
"strings"
78
"text/template"
@@ -160,7 +161,7 @@ func (c *Controller) httpDashboardCompare(w http.ResponseWriter, req *http.Reque
160161
unsupported = append(unsupported, toRelease)
161162
}
162163
if len(unsupported) > 0 {
163-
fmt.Fprintf(w, `<p class="alert alert-danger">%s</p>`, fmt.Sprintf("Unable to locate release(s): %s", template.HTMLEscapeString(strings.Join(unsupported, ", "))))
164+
fmt.Fprintf(w, `<p class="alert alert-danger">%s</p>`, fmt.Sprintf("Unable to locate release(s): %s", html.EscapeString(strings.Join(unsupported, ", "))))
164165
}
165166
}
166167
}

cmd/release-controller-api/static/js/jquery.dataTables.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,13 @@
6464
{
6565
// When creating with `new`, create a new DataTable, returning the API instance
6666
if (this instanceof DataTable) {
67-
return $(selector).DataTable(options);
67+
// Use jQuery.find() which only accepts CSS selectors, not HTML
68+
if (typeof selector === 'string') {
69+
return jQuery(document).find(selector).DataTable(options);
70+
}
71+
// Non-string input: DOM element or jQuery object - safe to wrap
72+
var safeTarget = selector.jquery ? selector : jQuery.fn.init.call(jQuery(), selector);
73+
return safeTarget.DataTable(options);
6874
}
6975
else {
7076
// Argument switching

hack/bot_comments_cleaner.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import argparse
2+
import re
3+
from urllib.parse import quote
24
import requests
35

46
BOT_USERNAME = 'openshift-crt-jira-release-controller'
57
JIRA_URL = 'https://issues.redhat.com/'
8+
ISSUE_KEY_PATTERN = re.compile(r'^[A-Z][A-Z0-9_]+-\d+$')
9+
COMMENT_ID_PATTERN = re.compile(r'^\d+$')
610

711
def main():
812
parser = argparse.ArgumentParser(description="JIRA Issue Comment Management CLI Tool")
@@ -49,7 +53,11 @@ def main():
4953
comment_count = sum(1 for comment in comments if TARGET_COMMENT in comment.get('body', ''))
5054

5155
if comment_count > 1:
52-
issue_comment_counts[issue['key']] = comment_count
56+
key = issue['key']
57+
if not ISSUE_KEY_PATTERN.match(key):
58+
print(f"Skipping issue with invalid key format: {key}")
59+
continue
60+
issue_comment_counts[key] = comment_count
5361

5462
print("Issues with the target comment appearing more than once:")
5563
for issue_key, comment_count in issue_comment_counts.items():
@@ -66,7 +74,10 @@ def main():
6674
break
6775

6876
def delete_comments(issue_key, headers, SUB_TARGET_COMMENT):
69-
issue_url = f'{JIRA_URL}/rest/api/2/issue/{issue_key}?fields=comment'
77+
if not ISSUE_KEY_PATTERN.match(issue_key):
78+
print(f"Skipping issue with invalid key format: {issue_key}")
79+
return
80+
issue_url = f'{JIRA_URL}/rest/api/2/issue/{quote(issue_key, safe="")}?fields=comment'
7081
response = requests.get(issue_url, headers=headers)
7182

7283
if response.status_code == 200:
@@ -79,7 +90,10 @@ def delete_comments(issue_key, headers, SUB_TARGET_COMMENT):
7990

8091
for matching_comments in matching_401_comments:
8192
comment_id = matching_comments.get('id')
82-
comment_delete_url = f'{JIRA_URL}/rest/api/2/issue/{issue_key}/comment/{comment_id}'
93+
if not comment_id or not COMMENT_ID_PATTERN.match(str(comment_id)):
94+
print(f"Skipping comment with invalid ID format: {comment_id}")
95+
continue
96+
comment_delete_url = f'{JIRA_URL}/rest/api/2/issue/{quote(issue_key, safe="")}/comment/{quote(str(comment_id), safe="")}'
8397
response = requests.delete(comment_delete_url, headers=headers)
8498
if response.status_code == 204:
8599
print(f"Deleted comment {comment_id} from issue {issue_key}")

0 commit comments

Comments
 (0)