From f63bc1bae46f756b7659f3fbeb53101eb91d93e3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 22 Aug 2025 15:00:53 +0000
Subject: [PATCH 1/2] Initial plan
From 91599f853c806f8b5f97eb9fa2437a71a8cdc5d8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 22 Aug 2025 15:14:01 +0000
Subject: [PATCH 2/2] Add 10 Sonar-detectable issues with AI CodeFix potential
Co-authored-by: AlexRage <16222524+AlexRage@users.noreply.github.com>
---
lib/insecurity.ts | 17 +++++++++++
lib/utils.ts | 50 +++++++++++++++++++++++++++++++-
routes/search.ts | 73 +++++++++++++++++++++++++++++++++++++++++++++++
server.ts | 15 ++++++++++
4 files changed, 154 insertions(+), 1 deletion(-)
diff --git a/lib/insecurity.ts b/lib/insecurity.ts
index 0e4e3d99389..88b103eed95 100644
--- a/lib/insecurity.ts
+++ b/lib/insecurity.ts
@@ -43,6 +43,17 @@ interface IAuthenticatedUsers {
export const hash = (data: string) => crypto.createHash('md5').update(data).digest('hex')
export const hmac = (data: string) => crypto.createHmac('sha256', 'pa4qacea4VK9t9nGv7yZtwmj').update(data).digest('hex')
+// SONAR ISSUE 9: Code smell - hard-coded credentials and sensitive data
+export const defaultDatabaseConfig = {
+ host: 'localhost',
+ port: 3306,
+ username: 'admin',
+ password: 'Password123!', // Hard-coded password
+ database: 'juice_shop',
+ apiKey: 'sk_test_abc123def456ghi789', // Hard-coded API key
+ secretKey: 'supersecretkey123' // Hard-coded secret
+}
+
export const cutOffPoisonNullByte = (str: string) => {
const nullByte = '%00'
if (utils.contains(str, nullByte)) {
@@ -51,6 +62,12 @@ export const cutOffPoisonNullByte = (str: string) => {
return str
}
+// SONAR ISSUE 2: Security vulnerability - XSS risk (unescaped HTML output)
+export const renderUserComment = (userInput: string) => {
+ // Vulnerable: Direct HTML rendering without escaping
+ return '
'
+}
+
export const isAuthorized = () => expressJwt(({ secret: publicKey }) as any)
export const denyAll = () => expressJwt({ secret: '' + Math.random() } as any)
export const authorize = (user = {}) => jwt.sign(user, privateKey, { expiresIn: '6h', algorithm: 'RS256' })
diff --git a/lib/utils.ts b/lib/utils.ts
index 29f4ca0a24f..747f8e1e4c8 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -3,9 +3,13 @@
* SPDX-License-Identifier: MIT
*/
+// SONAR ISSUE 3: Code smell - unused imports and variables
+import path from 'path'
+import fs from 'fs'
+
/* jslint node: true */
import packageJson from '../package.json'
-import fs from 'fs'
+import fs from 'fs' // SONAR ISSUE 3: Duplicate import
import logger from './logger'
import config from 'config'
import jsSHA from 'jssha'
@@ -22,6 +26,10 @@ export { default as isWindows } from './is-windows'
// import isGitpod from 'is-gitpod') // FIXME Roll back to this when https://github.com/dword-design/is-gitpod/issues/94 is resolve
const isGitpod = () => false
+// SONAR ISSUE 3: Unused variables
+const unusedVariable = 'this variable is never used'
+const anotherUnusedVariable = 42
+
const months = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
export const queryResultToJson = (
@@ -223,12 +231,52 @@ export const getErrorMessage = (error: unknown) => {
return String(error)
}
+// SONAR ISSUE 6: Code smell - overly complex conditional expression
+export const validateUserAccess = (user: any, resource: any, permissions: any) => {
+ if (user && user.isActive && user.role && (user.role === 'admin' || user.role === 'moderator') && resource && resource.isPublic !== false && permissions && permissions.read === true && (permissions.write === true || permissions.admin === true) && user.lastLogin && new Date().getTime() - new Date(user.lastLogin).getTime() < 86400000 && user.accountStatus !== 'suspended' && user.accountStatus !== 'banned') {
+ return true
+ }
+ return false
+}
+
export const matchesSystemIniFile = (text: string) => {
const match = text.match(/; for 16-bit app support/gi)
return match !== null && match.length >= 1
}
+// SONAR ISSUE 8: Bug - empty catch block (suppresses exceptions)
+export const parseJsonSafely = (jsonString: string) => {
+ try {
+ return JSON.parse(jsonString)
+ } catch (error) {
+ // Empty catch block - this suppresses all errors
+ }
+ return null
+}
+
export const matchesEtcPasswdFile = (text: string) => {
const match = text.match(/(\w*:\w*:\d*:\d*:\w*:.*)|(Note that this file is consulted directly)/gi)
return match !== null && match.length >= 1
}
+
+// SONAR ISSUE 5: Bug - potential null pointer dereference
+export const processUserData = (user: any) => {
+ // Vulnerable: No null check before accessing properties
+ return user.name.toUpperCase() + ' - ' + user.email.toLowerCase()
+}
+
+// SONAR ISSUE 10: Performance issue - inefficient string concatenation in loop
+export const buildLargeString = (items: string[]) => {
+ let result = ''
+ for (let i = 0; i < items.length; i++) {
+ result = result + items[i] + ', ' // Inefficient string concatenation
+ }
+ return result
+}
+
+// SONAR ISSUE 1: Security vulnerability - SQL injection risk (hard-coded SQL)
+export const getUserById = (userId: string) => {
+ // Vulnerable: Direct string concatenation in SQL query
+ const query = "SELECT * FROM users WHERE id = '" + userId + "'"
+ return query
+}
diff --git a/routes/search.ts b/routes/search.ts
index 7a5d8fe8458..0ece68df55c 100644
--- a/routes/search.ts
+++ b/routes/search.ts
@@ -72,3 +72,76 @@ module.exports = function searchProducts () {
}
}
// vuln-code-snippet end unionSqlInjectionChallenge dbSchemaChallenge
+
+// SONAR ISSUE 7: Code smell - function too long and complex (exceeds recommended lines/complexity)
+function massiveComplexFunction (data: any) {
+ let result = 0
+ let tempVar1 = ''
+ let tempVar2 = 0
+ let tempVar3: any[] = []
+
+ // First section - validation logic
+ if (data && typeof data === 'object') {
+ if (data.hasOwnProperty('items') && Array.isArray(data.items)) {
+ for (let i = 0; i < data.items.length; i++) {
+ if (data.items[i] && data.items[i].value) {
+ if (typeof data.items[i].value === 'number') {
+ result += data.items[i].value
+ } else if (typeof data.items[i].value === 'string') {
+ tempVar1 += data.items[i].value
+ }
+ }
+ }
+ }
+ }
+
+ // Second section - processing logic
+ if (data.metadata) {
+ for (let key in data.metadata) {
+ if (data.metadata.hasOwnProperty(key)) {
+ if (key.startsWith('temp_')) {
+ tempVar2 += 1
+ } else if (key.startsWith('data_')) {
+ tempVar3.push(data.metadata[key])
+ }
+ }
+ }
+ }
+
+ // Third section - calculation logic
+ let multiplier = 1
+ if (tempVar2 > 0) {
+ multiplier = tempVar2 * 2
+ }
+
+ if (tempVar3.length > 0) {
+ for (let item of tempVar3) {
+ if (item && item.coefficient) {
+ multiplier *= item.coefficient
+ }
+ }
+ }
+
+ // Fourth section - formatting logic
+ let finalResult = result * multiplier
+ if (tempVar1.length > 0) {
+ finalResult = finalResult + tempVar1.length
+ }
+
+ // Fifth section - validation and return
+ if (finalResult < 0) {
+ finalResult = 0
+ } else if (finalResult > 1000000) {
+ finalResult = 1000000
+ }
+
+ return {
+ result: finalResult,
+ metadata: {
+ stringLength: tempVar1.length,
+ itemCount: tempVar2,
+ dataItems: tempVar3.length,
+ multiplier: multiplier
+ }
+ }
+}
diff --git a/server.ts b/server.ts
index c2689cc8d39..06a206424e9 100644
--- a/server.ts
+++ b/server.ts
@@ -151,6 +151,21 @@ const collectDurationPromise = (name: string, func: (...args: any) => Promise Promise) => {
+ return async (...args: any) => {
+ const end = startupGauge.startTimer({ task: name })
+ try {
+ const res = await func(...args)
+ end()
+ return res
+ } catch (err) {
+ console.error('Error in timed startup function: ' + name, err)
+ throw err
+ }
+ }
+}
+
/* Sets view engine to hbs */
app.set('view engine', 'hbs')