Skip to content

Commit 24e1c3c

Browse files
authored
Merge pull request #16 from quantumdark/check-results-on-failure
Improve the scan polling and security findings checking logic
2 parents 8789eb2 + 8c680f3 commit 24e1c3c

2 files changed

Lines changed: 225 additions & 141 deletions

File tree

main.js

Lines changed: 84 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ function get_security_findings(dt_results_api_key, mobile_app_id, results_since,
6464
});
6565
}
6666
function check_severity_findings(dt_results_api_key, mobile_app_id, results_since, severity_level, check_scope) {
67+
var _a;
6768
return __awaiter(this, void 0, void 0, function* () {
6869
const severity_checks = {
6970
HIGH: ["HIGH"],
@@ -83,11 +84,14 @@ function check_severity_findings(dt_results_api_key, mobile_app_id, results_sinc
8384
throw new Error(`Error fetching security findings for ${severity} severity: HTTP ${findings_response.status}`);
8485
}
8586
const findings_data = yield findings_response.json();
86-
const count = findings_data.total_count || 0;
87-
total_findings += count;
88-
if (count > 0) {
89-
return { has_findings: true, total_count: total_findings };
87+
const count = parseInt((_a = findings_data.pagination_information) === null || _a === void 0 ? void 0 : _a.total_count, 10) || 0;
88+
if (count === 0) {
89+
console.log(`Found ${count} ${severity} severity findings (results_since: ${effective_results_since})`);
9090
}
91+
total_findings += count;
92+
}
93+
if (total_findings > 0) {
94+
return { has_findings: true, total_count: total_findings };
9195
}
9296
return { has_findings: false, total_count: 0 };
9397
});
@@ -278,8 +282,14 @@ function run() {
278282
if (warn_on_severity) {
279283
console.log(`Warning on vulnerabilities with minimum severity: ${warn_on_severity}`);
280284
}
281-
if (wait_for_static_scan_only === 'true') {
282-
console.log('WAIT_FOR_STATIC_SCAN_ONLY is enabled: will wait for static_scan completion');
285+
if (wait_for_static_scan_only === "true") {
286+
console.log("WAIT_FOR_STATIC_SCAN_ONLY is enabled: will wait for static_scan completion");
287+
}
288+
if (severity_check_scope.toUpperCase() === "ALL_ISSUES") {
289+
console.log("SEVERITY_CHECK_SCOPE is set to ALL_ISSUES: checking all open issues in the mobile app");
290+
}
291+
else {
292+
console.log("SEVERITY_CHECK_SCOPE is set to CURRENT_SCAN: checking only issues from the current scan");
283293
}
284294
for (const scan of scan_info) {
285295
const { mobile_app_id, scan_id } = scan;
@@ -290,7 +300,9 @@ function run() {
290300
// Poll for scan completion with 23-second intervals
291301
const pollInterval = 23000; // 23 seconds
292302
const startTime = Date.now();
293-
console.log(`Waiting for scan ${scan_id} to complete...`);
303+
let status_data = null;
304+
let scan_completed = false;
305+
let scan_failed = false;
294306
while (Date.now() - startTime < maxWaitTime) {
295307
try {
296308
const status_response = yield check_scan_status(dt_results_api_key, mobile_app_id, scan_id);
@@ -303,10 +315,10 @@ function run() {
303315
yield new Promise((resolve) => setTimeout(resolve, pollInterval));
304316
continue;
305317
}
306-
const status_data = yield status_response.json();
318+
status_data = yield status_response.json();
307319
// Check status based on WAIT_FOR_STATIC_SCAN_ONLY parameter
308320
let scan_status;
309-
if (wait_for_static_scan_only === 'true') {
321+
if (wait_for_static_scan_only === "true") {
310322
if ((_a = status_data.static_scan) === null || _a === void 0 ? void 0 : _a.status) {
311323
scan_status = status_data.static_scan.status;
312324
}
@@ -328,67 +340,86 @@ function run() {
328340
yield new Promise((resolve) => setTimeout(resolve, pollInterval));
329341
continue;
330342
}
331-
console.log(`Scan ${scan_id} completed, checking for security findings...`);
332-
// Use start_date from status_data as results_since
333-
const results_since = status_data.start_date;
334-
if (!results_since) {
335-
console.log(`No start_date found in scan data for ${scan_id}`);
336-
break;
343+
console.log(`Scan ${scan_id} completed`);
344+
scan_completed = true;
345+
break;
346+
}
347+
catch (error) {
348+
console.log(`Error checking scan status for ${scan_id}: ${error.message}`);
349+
yield new Promise((resolve) => setTimeout(resolve, pollInterval));
350+
}
351+
}
352+
if (Date.now() - startTime >= maxWaitTime) {
353+
console.log(`Timeout waiting for scan results for scan ${scan_id}`);
354+
}
355+
// Check for security findings with retry logic (max 3 attempts)
356+
const maxAttempts = 3;
357+
const retryInterval = 5000; // 5 seconds
358+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
359+
if (scan_failed &&
360+
severity_check_scope.toUpperCase() === "CURRENT_SCAN") {
361+
// Skip findings check if scan failed in CURRENT_SCAN mode
362+
break;
363+
}
364+
try {
365+
let results_since;
366+
if (severity_check_scope.toUpperCase() === "ALL_ISSUES") {
367+
results_since = "";
368+
}
369+
else {
370+
if (!status_data || !status_data.start_date) {
371+
console.log(`No start_date found in scan data for ${scan_id}`);
372+
break;
373+
}
374+
results_since = status_data.start_date;
337375
}
338376
// Check for blocking vulnerabilities first
339377
if (block_on_severity) {
340-
try {
341-
const { has_findings, total_count } = yield check_severity_findings(dt_results_api_key, mobile_app_id, results_since, block_on_severity, severity_check_scope);
342-
if (has_findings) {
343-
const scope_description = severity_check_scope.toUpperCase() === "ALL_ISSUES"
344-
? "in the mobile app"
345-
: "in this scan";
346-
console.log(`Found ${total_count} security findings ${scope_description} at or above ${block_on_severity} severity level`);
347-
core.setFailed(`Build blocked due to ${total_count} security findings ${scope_description} at or above ${block_on_severity} severity level`);
348-
return;
349-
}
378+
const { has_findings, total_count } = yield check_severity_findings(dt_results_api_key, mobile_app_id, results_since, block_on_severity, severity_check_scope);
379+
if (has_findings) {
350380
const scope_description = severity_check_scope.toUpperCase() === "ALL_ISSUES"
351381
? "in the mobile app"
352-
: `for scan ${scan_id}`;
353-
console.log(`No security findings found at or above ${block_on_severity} severity level ${scope_description}`);
354-
}
355-
catch (error) {
356-
console.log(`Error checking security findings for scan ${scan_id}: ${error.message}`);
357-
break;
382+
: "in this scan";
383+
console.log(`Found ${total_count} security findings ${scope_description} at or above ${block_on_severity} severity level`);
384+
core.setFailed(`Build blocked due to ${total_count} security findings ${scope_description} at or above ${block_on_severity} severity level`);
385+
return;
358386
}
387+
const scope_description = severity_check_scope.toUpperCase() === "ALL_ISSUES"
388+
? "in the mobile app"
389+
: `for scan ${scan_id}`;
390+
console.log(`No security findings found at or above ${block_on_severity} severity level ${scope_description}`);
359391
}
360392
// Check for warning vulnerabilities
361393
if (warn_on_severity) {
362-
try {
363-
const { has_findings, total_count } = yield check_severity_findings(dt_results_api_key, mobile_app_id, results_since, warn_on_severity, severity_check_scope);
364-
if (has_findings) {
365-
const scope_description = severity_check_scope.toUpperCase() === "ALL_ISSUES"
366-
? "in the mobile app"
367-
: `for scan ${scan_id}`;
368-
console.log(`⚠️ WARNING: Found ${total_count} security findings ${scope_description} at or above ${warn_on_severity} severity level`);
369-
console.log(`⚠️ These findings do not block the build, but should be reviewed and addressed.`);
370-
}
371-
else {
372-
const scope_description = severity_check_scope.toUpperCase() === "ALL_ISSUES"
373-
? "in the mobile app"
374-
: `for scan ${scan_id}`;
375-
console.log(`No security findings found at or above ${warn_on_severity} severity level ${scope_description}`);
376-
}
394+
const { has_findings, total_count } = yield check_severity_findings(dt_results_api_key, mobile_app_id, results_since, warn_on_severity, severity_check_scope);
395+
if (has_findings) {
396+
const scope_description = severity_check_scope.toUpperCase() === "ALL_ISSUES"
397+
? "in the mobile app"
398+
: `for scan ${scan_id}`;
399+
console.log(`⚠️ WARNING: Found ${total_count} security findings ${scope_description} at or above ${warn_on_severity} severity level`);
400+
console.log(`⚠️ These findings do not block the build, but should be reviewed and addressed.`);
377401
}
378-
catch (error) {
379-
console.log(`Error checking security findings for warnings for scan ${scan_id}: ${error.message}`);
402+
else {
403+
const scope_description = severity_check_scope.toUpperCase() === "ALL_ISSUES"
404+
? "in the mobile app"
405+
: `for scan ${scan_id}`;
406+
console.log(`No security findings found at or above ${warn_on_severity} severity level ${scope_description}`);
380407
}
381408
}
409+
// Successfully checked findings, exit retry loop
382410
break;
383411
}
384412
catch (error) {
385-
console.log(`Error checking scan status for ${scan_id}: ${error.message}`);
386-
yield new Promise((resolve) => setTimeout(resolve, pollInterval));
413+
console.log(`Error checking security findings for ${scan_id} (attempt ${attempt}/${maxAttempts}): ${error.message}`);
414+
if (attempt < maxAttempts) {
415+
console.log(`Retrying in ${retryInterval / 1000} seconds...`);
416+
yield new Promise((resolve) => setTimeout(resolve, retryInterval));
417+
}
418+
else {
419+
console.log(`Failed to check security findings after ${maxAttempts} attempts`);
420+
}
387421
}
388422
}
389-
if (Date.now() - startTime >= maxWaitTime) {
390-
console.log(`Timeout waiting for scan results for scan ${scan_id}`);
391-
}
392423
}
393424
core.setOutput("responses", output);
394425
core.setOutput("response", output[0]); // keep the `response` output as the response of the first file upload to maintain compatibility

0 commit comments

Comments
 (0)