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 '
' + userInput + '
' +} + 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')