Skip to content

Commit

Permalink
Fix all restrict-plus-operands linting issues
Browse files Browse the repository at this point in the history
  • Loading branch information
bkimminich committed Jan 6, 2024
1 parent afbc830 commit 87beace
Show file tree
Hide file tree
Showing 38 changed files with 157 additions and 158 deletions.
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ module.exports = {
// FIXME warnings below this line need to be checked and fixed.
'@typescript-eslint/no-misused-promises': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/restrict-plus-operands': 'off',
'@typescript-eslint/strict-boolean-expressions': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/no-var-requires': 'off'
Expand Down
8 changes: 4 additions & 4 deletions data/datacreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ async function createChallenges () {
await Promise.all(
challenges.map(async ({ name, category, description, difficulty, hint, hintUrl, mitigationUrl, key, disabledEnv, tutorial, tags }: Challenge) => {
const effectiveDisabledEnv = utils.determineDisabledEnv(disabledEnv)
description = description.replace('juice-sh.op', config.get('application.domain'))
description = description.replace('juice-sh.op', config.get<string>('application.domain'))
description = description.replace('&lt;iframe width=&quot;100%&quot; height=&quot;166&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allow=&quot;autoplay&quot; src=&quot;https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/771984076&amp;color=%23ff5500&amp;auto_play=true&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=true&quot;&gt;&lt;/iframe&gt;', entities.encode(config.get('challenges.xssBonusPayload')))
hint = hint.replace(/OWASP Juice Shop's/, `${config.get('application.name')}'s`)
hint = hint.replace(/OWASP Juice Shop's/, `${config.get<string>('application.name')}'s`)

try {
datacache.challenges[key] = await ChallengeModel.create({
Expand Down Expand Up @@ -110,7 +110,7 @@ async function createUsers () {
await Promise.all(
users.map(async ({ username, email, password, customDomain, key, role, deletedFlag, profileImage, securityQuestion, feedback, address, card, totpSecret, lastLoginIp = '' }: User) => {
try {
const completeEmail = customDomain ? email : `${email}@${config.get('application.domain')}`
const completeEmail = customDomain ? email : `${email}@${config.get<string>('application.domain')}`
const user = await UserModel.create({
username,
email: completeEmail,
Expand Down Expand Up @@ -659,7 +659,7 @@ async function createOrders () {
}
]

const adminEmail = 'admin@' + config.get('application.domain')
const adminEmail = 'admin@' + config.get<string>('application.domain')
const orders = [
{
orderId: security.hash(adminEmail).slice(0, 4) + '-' + utils.randomHexString(16),
Expand Down
2 changes: 1 addition & 1 deletion data/static/codefixes/exposedMetricsChallenge_1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
let metricsUpdateLoop: any
const Metrics = metrics.observeMetrics()
app.get('/metrics', security.denyAll(), metrics.serveMetrics())
errorhandler.title = `${config.get('application.name')} (Express ${utils.version('express')})`
errorhandler.title = `${config.get<string>('application.name')} (Express ${utils.version('express')})`

const registerWebsocketEvents = require('./lib/startup/registerWebsocketEvents')
const customizeApplication = require('./lib/startup/customizeApplication')
Expand Down
2 changes: 1 addition & 1 deletion data/static/codefixes/exposedMetricsChallenge_2.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* Serve metrics */
const Metrics = metrics.observeMetrics()
app.get('/metrics', metrics.serveMetrics())
errorhandler.title = `${config.get('application.name')} (Express ${utils.version('express')})`
errorhandler.title = `${config.get<string>('application.name')} (Express ${utils.version('express')})`

const registerWebsocketEvents = require('./lib/startup/registerWebsocketEvents')
const customizeApplication = require('./lib/startup/customizeApplication')
Expand Down
2 changes: 1 addition & 1 deletion data/static/codefixes/exposedMetricsChallenge_3_correct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
let metricsUpdateLoop: any
const Metrics = metrics.observeMetrics()
app.get('/metrics', security.isAdmin(), metrics.serveMetrics())
errorhandler.title = `${config.get('application.name')} (Express ${utils.version('express')})`
errorhandler.title = `${config.get<string>('application.name')} (Express ${utils.version('express')})`

const registerWebsocketEvents = require('./lib/startup/registerWebsocketEvents')
const customizeApplication = require('./lib/startup/customizeApplication')
Expand Down
8 changes: 4 additions & 4 deletions lib/startup/customizeApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as utils from '../utils'
const replace = require('replace')

const customizeApplication = () => {
if (config.get('application.name')) {
if (config.get<string>('application.name')) {
customizeTitle()
}
if (config.get('application.logo')) {
Expand Down Expand Up @@ -80,7 +80,7 @@ const retrieveCustomFile = async (sourceProperty: string, destinationFolder: str
}

const customizeTitle = () => {
const title = `<title>${config.get('application.name')}</title>`
const title = `<title>${config.get<string>('application.name')}</title>`
replace({
regex: /<title>.*<\/title>/,
replacement: title,
Expand All @@ -91,7 +91,7 @@ const customizeTitle = () => {
}

const customizeTheme = () => {
const bodyClass = '"mat-app-background ' + config.get('application.theme') + '-theme"'
const bodyClass = '"mat-app-background ' + config.get<string>('application.theme') + '-theme"'
replace({
regex: /"mat-app-background .*-theme"/,
replacement: bodyClass,
Expand All @@ -102,7 +102,7 @@ const customizeTheme = () => {
}

const customizeCookieConsentBanner = () => {
const contentProperty = '"content": { "message": "' + config.get('application.cookieConsent.message') + '", "dismiss": "' + config.get('application.cookieConsent.dismissText') + '", "link": "' + config.get('application.cookieConsent.linkText') + '", "href": "' + config.get('application.cookieConsent.linkUrl') + '" }'
const contentProperty = '"content": { "message": "' + config.get<string>('application.cookieConsent.message') + '", "dismiss": "' + config.get<string>('application.cookieConsent.dismissText') + '", "link": "' + config.get<string>('application.cookieConsent.linkText') + '", "href": "' + config.get<string>('application.cookieConsent.linkUrl') + '" }'
replace({
regex: /"content": { "message": ".*", "dismiss": ".*", "link": ".*", "href": ".*" }/,
replacement: contentProperty,
Expand Down
2 changes: 1 addition & 1 deletion lib/startup/customizeEasterEgg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const replaceImagePath = (overlay: string) => {
}

const replaceThreeJsTitleTag = () => {
const threeJsTitleTag = '<title>Welcome to Planet ' + config.get('application.easterEggPlanet.name') + '</title>'
const threeJsTitleTag = '<title>Welcome to Planet ' + config.get<string>('application.easterEggPlanet.name') + '</title>'
replace({
regex: /<title>.*<\/title>/,
replacement: threeJsTitleTag,
Expand Down
16 changes: 8 additions & 8 deletions lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,27 +149,27 @@ export const jwtFrom = ({ headers }: { headers: any }) => {
return undefined
}

export const randomHexString = (length: number) => {
export const randomHexString = (length: number): string => {
return crypto.randomBytes(Math.ceil(length / 2)).toString('hex').slice(0, length)
}

export const disableOnContainerEnv = () => {
return (isDocker() || isGitpod() || isHeroku()) && !config.get('challenges.safetyOverride')
export const disableOnContainerEnv = (): boolean => {
return (isDocker() || isGitpod() || isHeroku()) && !(config.get('challenges.safetyOverride'))
}

export const disableOnWindowsEnv = () => {
export const disableOnWindowsEnv = (): boolean => {
return isWindows()
}

export const determineDisabledEnv = (disabledEnv: string | string[] | undefined) => {
if (isDocker()) {
return disabledEnv && (disabledEnv === 'Docker' || disabledEnv.includes('Docker')) ? 'Docker' : null
return disabledEnv != null && (disabledEnv === 'Docker' || disabledEnv?.includes('Docker')) ? 'Docker' : null
} else if (isHeroku()) {
return disabledEnv && (disabledEnv === 'Heroku' || disabledEnv.includes('Heroku')) ? 'Heroku' : null
return disabledEnv != null && (disabledEnv === 'Heroku' || disabledEnv?.includes('Heroku')) ? 'Heroku' : null
} else if (isWindows()) {
return disabledEnv && (disabledEnv === 'Windows' || disabledEnv.includes('Windows')) ? 'Windows' : null
return disabledEnv != null && (disabledEnv === 'Windows' || disabledEnv?.includes('Windows')) ? 'Windows' : null
} else if (isGitpod()) {
return disabledEnv && (disabledEnv === 'Gitpod' || disabledEnv.includes('Gitpod')) ? 'Gitpod' : null
return disabledEnv != null && (disabledEnv === 'Gitpod' || disabledEnv?.includes('Gitpod')) ? 'Gitpod' : null
}
return null
}
Expand Down
2 changes: 1 addition & 1 deletion lib/webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const notify = async (challenge: { key: any, name: any }, cheatScore = -1
issuer: {
hostName: os.hostname(),
os: `${os.type()} (${os.release()})`,
appName: config.get('application.name'),
appName: config.get<string>('application.name'),
config: process.env.NODE_ENV ?? 'default',
version: utils.version()
}
Expand Down
2 changes: 1 addition & 1 deletion models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ const UserModelInit = (sequelize: Sequelize) => { // vuln-code-snippet start wea
if (
user.email &&
user.email.toLowerCase() ===
`acc0unt4nt@${config.get('application.domain')}`.toLowerCase()
`acc0unt4nt@${config.get<string>('application.domain')}`.toLowerCase()
) {
await Promise.reject(
new Error(
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
"colors": "1.4.0",
"compression": "^1.7.4",
"concurrently": "^5.3.0",
"config": "^3.3.7",
"config": "^3.3.9",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dottie": "^2.0.2",
Expand Down Expand Up @@ -192,7 +192,7 @@
"@types/chai-as-promised": "^7.1.3",
"@types/clarinet": "^0.12.1",
"@types/compression": "^1.7.0",
"@types/config": "^3.3.1",
"@types/config": "^3.3.3",
"@types/cookie-parser": "^1.4.2",
"@types/cors": "^2.8.9",
"@types/cross-spawn": "^6.0.2",
Expand Down
2 changes: 1 addition & 1 deletion routes/2fa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function verify (req: Request, res: Response) {
if (!isValid) {
return res.status(401).send()
}
challengeUtils.solveIf(challenges.twoFactorAuthUnsafeSecretStorageChallenge, () => { return user.email === 'wurstbrot@' + config.get('application.domain') })
challengeUtils.solveIf(challenges.twoFactorAuthUnsafeSecretStorageChallenge, () => { return user.email === 'wurstbrot@' + config.get<string>('application.domain') })

const [basket] = await BasketModel.findOrCreate({ where: { UserId: userId } })

Expand Down
2 changes: 1 addition & 1 deletion routes/b2bOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module.exports = function b2bOrder () {
}

function uniqueOrderNumber () {
return security.hash(new Date() + '_B2B')
return security.hash(`${new Date()}_B2B`)
}

function dateTwoWeeksFromNow () {
Expand Down
14 changes: 7 additions & 7 deletions routes/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ module.exports = function login () {
// vuln-code-snippet end loginAdminChallenge loginBenderChallenge loginJimChallenge

function verifyPreLoginChallenges (req: Request) {
challengeUtils.solveIf(challenges.weakPasswordChallenge, () => { return req.body.email === 'admin@' + config.get('application.domain') && req.body.password === 'admin123' })
challengeUtils.solveIf(challenges.loginSupportChallenge, () => { return req.body.email === 'support@' + config.get('application.domain') && req.body.password === 'J6aVjTgOpRs@?5l!Zkq2AYnCE@RF$P' })
challengeUtils.solveIf(challenges.loginRapperChallenge, () => { return req.body.email === 'mc.safesearch@' + config.get('application.domain') && req.body.password === 'Mr. N00dles' })
challengeUtils.solveIf(challenges.loginAmyChallenge, () => { return req.body.email === 'amy@' + config.get('application.domain') && req.body.password === 'K1f.....................' })
challengeUtils.solveIf(challenges.dlpPasswordSprayingChallenge, () => { return req.body.email === 'J12934@' + config.get('application.domain') && req.body.password === '0Y8rMnww$*9VFYE§59-!Fg1L6t&6lB' })
challengeUtils.solveIf(challenges.weakPasswordChallenge, () => { return req.body.email === 'admin@' + config.get<string>('application.domain') && req.body.password === 'admin123' })
challengeUtils.solveIf(challenges.loginSupportChallenge, () => { return req.body.email === 'support@' + config.get<string>('application.domain') && req.body.password === 'J6aVjTgOpRs@?5l!Zkq2AYnCE@RF$P' })
challengeUtils.solveIf(challenges.loginRapperChallenge, () => { return req.body.email === 'mc.safesearch@' + config.get<string>('application.domain') && req.body.password === 'Mr. N00dles' })
challengeUtils.solveIf(challenges.loginAmyChallenge, () => { return req.body.email === 'amy@' + config.get<string>('application.domain') && req.body.password === 'K1f.....................' })
challengeUtils.solveIf(challenges.dlpPasswordSprayingChallenge, () => { return req.body.email === 'J12934@' + config.get<string>('application.domain') && req.body.password === '0Y8rMnww$*9VFYE§59-!Fg1L6t&6lB' })
challengeUtils.solveIf(challenges.oauthUserPasswordChallenge, () => { return req.body.email === '[email protected]' && req.body.password === 'bW9jLmxpYW1nQGhjaW5pbW1pay5ucmVvamI=' })
}

Expand All @@ -72,8 +72,8 @@ module.exports = function login () {
challengeUtils.solveIf(challenges.loginJimChallenge, () => { return user.data.id === users.jim.id })
challengeUtils.solveIf(challenges.loginBenderChallenge, () => { return user.data.id === users.bender.id })
challengeUtils.solveIf(challenges.ghostLoginChallenge, () => { return user.data.id === users.chris.id })
if (challengeUtils.notSolved(challenges.ephemeralAccountantChallenge) && user.data.email === 'acc0unt4nt@' + config.get('application.domain') && user.data.role === 'accounting') {
UserModel.count({ where: { email: 'acc0unt4nt@' + config.get('application.domain') } }).then((count: number) => {
if (challengeUtils.notSolved(challenges.ephemeralAccountantChallenge) && user.data.email === 'acc0unt4nt@' + config.get<string>('application.domain') && user.data.role === 'accounting') {
UserModel.count({ where: { email: 'acc0unt4nt@' + config.get<string>('application.domain') } }).then((count: number) => {
if (count === 0) {
challengeUtils.solve(challenges.ephemeralAccountantChallenge)
}
Expand Down
4 changes: 2 additions & 2 deletions routes/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ exports.observeMetrics = function observeMetrics () {

const versionMetrics = new Prometheus.Gauge({
name: `${app}_version_info`,
help: `Release version of ${config.get('application.name')}.`,
help: `Release version of ${config.get<string>('application.name')}.`,
labelNames: ['version', 'major', 'minor', 'patch']
})

Expand Down Expand Up @@ -118,7 +118,7 @@ exports.observeMetrics = function observeMetrics () {

const orderMetrics = new Prometheus.Gauge({
name: `${app}_orders_placed_total`,
help: `Number of orders placed in ${config.get('application.name')}.`
help: `Number of orders placed in ${config.get<string>('application.name')}.`
})

const userMetrics = new Prometheus.Gauge({
Expand Down
2 changes: 1 addition & 1 deletion routes/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module.exports = function placeOrder () {
res.json({ orderConfirmation: orderId })
})

doc.font('Times-Roman', 40).text(config.get('application.name'), { align: 'center' })
doc.font('Times-Roman', 40).text(config.get<string>('application.name'), { align: 'center' })
doc.moveTo(70, 115).lineTo(540, 115).stroke()
doc.moveTo(70, 120).lineTo(540, 120).stroke()
doc.fontSize(20).moveDown()
Expand Down
6 changes: 3 additions & 3 deletions routes/redirect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ const challenges = require('../data/datacache').challenges

module.exports = function performRedirect () {
return ({ query }: Request, res: Response, next: NextFunction) => {
const toUrl = query.to
const toUrl: string = query.to as string
if (security.isRedirectAllowed(toUrl)) {
challengeUtils.solveIf(challenges.redirectCryptoCurrencyChallenge, () => { return toUrl === 'https://explorer.dash.org/address/Xr556RzuwX6hg5EGpkybbv5RanJoZN17kW' || toUrl === 'https://blockchain.info/address/1AbKfgvw9psQ41NbLi8kufDQTezwG8DRZm' || toUrl === 'https://etherscan.io/address/0x0f933ab9fcaaa782d0279c300d73750e1311eae6' })
challengeUtils.solveIf(challenges.redirectChallenge, () => { return isUnintendedRedirect(toUrl as string) })
res.redirect(toUrl as string)
challengeUtils.solveIf(challenges.redirectChallenge, () => { return isUnintendedRedirect(toUrl) })
res.redirect(toUrl)
} else {
res.status(406)
next(new Error('Unrecognized target URL for redirect: ' + toUrl))
Expand Down
2 changes: 1 addition & 1 deletion routes/userProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ module.exports = function getUserProfile () {
template = template.replace(/_username_/g, username)
}
template = template.replace(/_emailHash_/g, security.hash(user?.email))
template = template.replace(/_title_/g, entities.encode(config.get('application.name')))
template = template.replace(/_title_/g, entities.encode(config.get<string>('application.name')))
template = template.replace(/_favicon_/g, favicon())
template = template.replace(/_bgColor_/g, theme.bgColor)
template = template.replace(/_textColor_/g, theme.textColor)
Expand Down
2 changes: 1 addition & 1 deletion routes/videoHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ exports.promotionVideo = () => {
challengeUtils.solveIf(challenges.videoXssChallenge, () => { return utils.contains(subs, '</script><script>alert(`xss`)</script>') })

const theme = themes[config.get<string>('application.theme')]
template = template.replace(/_title_/g, entities.encode(config.get('application.name')))
template = template.replace(/_title_/g, entities.encode(config.get<string>('application.name')))
template = template.replace(/_favicon_/g, favicon())
template = template.replace(/_bgColor_/g, theme.bgColor)
template = template.replace(/_textColor_/g, theme.textColor)
Expand Down
2 changes: 1 addition & 1 deletion server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ let metricsUpdateLoop: any
const Metrics = metrics.observeMetrics() // vuln-code-snippet neutral-line exposedMetricsChallenge
const customizeEasterEgg = require('./lib/startup/customizeEasterEgg') // vuln-code-snippet hide-line
app.get('/metrics', metrics.serveMetrics()) // vuln-code-snippet vuln-line exposedMetricsChallenge
errorhandler.title = `${config.get('application.name')} (Express ${utils.version('express')})`
errorhandler.title = `${config.get<string>('application.name')} (Express ${utils.version('express')})`

const registerWebsocketEvents = require('./lib/startup/registerWebsocketEvents')
const customizeApplication = require('./lib/startup/customizeApplication')
Expand Down
10 changes: 5 additions & 5 deletions test/api/2faSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe('/rest/2fa/verify', () => {
bid: Joi.number()
})
.expect('json', 'authentication', {
umail: `wurstbrot@${config.get('application.domain')}`
umail: `wurstbrot@${config.get<string>('application.domain')}`
})
})

Expand Down Expand Up @@ -165,7 +165,7 @@ describe('/rest/2fa/verify', () => {
describe('/rest/2fa/status', () => {
it('GET should indicate 2fa is setup for 2fa enabled users', async () => {
const { token } = await login({
email: `wurstbrot@${config.get('application.domain')}`,
email: `wurstbrot@${config.get<string>('application.domain')}`,
password: 'EinBelegtesBrotMitSchinkenSCHINKEN!',
totpSecret: 'IFTXE3SPOEYVURT2MRYGI52TKJ4HC3KH'
})
Expand All @@ -191,7 +191,7 @@ describe('/rest/2fa/status', () => {

it('GET should indicate 2fa is not setup for users with 2fa disabled', async () => {
const { token } = await login({
email: `J12934@${config.get('application.domain')}`,
email: `J12934@${config.get<string>('application.domain')}`,
password: '0Y8rMnww$*9VFYE§59-!Fg1L6t&6lB'
})

Expand All @@ -214,7 +214,7 @@ describe('/rest/2fa/status', () => {
})
.expect('json', {
setup: false,
email: `J12934@${config.get('application.domain')}`
email: `J12934@${config.get<string>('application.domain')}`
})
})

Expand Down Expand Up @@ -360,7 +360,7 @@ describe('/rest/2fa/setup', () => {
})

it('POST should fail if the account has already set up 2fa', async () => {
const email = `wurstbrot@${config.get('application.domain')}`
const email = `wurstbrot@${config.get<string>('application.domain')}`
const password = 'EinBelegtesBrotMitSchinkenSCHINKEN!'
const totpSecret = 'IFTXE3SPOEYVURT2MRYGI52TKJ4HC3KH'

Expand Down
Loading

0 comments on commit 87beace

Please sign in to comment.