Skip to content

Commit a9bc5fe

Browse files
authored
fix(security): resolve all CodeQL security findings (#2806)
* fix(security): resolve all CodeQL security findings - Path injection (ocp-sticker.service.ts): Validate lang against allowed values - Type confusion (spark.service.ts): Add nullish coalescing for Map.get() - Missing permissions (api-*.yaml): Add explicit 'contents: read' permissions - Polynomial ReDoS (gs.service.ts): Replace regex with simple string search - Incomplete sanitization (olkypay.service.ts): Use replaceAll instead of replace Resolves 9 CodeQL alerts * fix(gs): use bounded quantifier for ORDER BY detection Replace .includes('order by') with bounded regex /order\s{1,100}by/i: - Prevents ReDoS via bounded quantifier {1,100} - Maintains support for tabs and multiple spaces between ORDER and BY - Original .includes() only matched single space
1 parent dd53c04 commit a9bc5fe

7 files changed

Lines changed: 23 additions & 6 deletions

File tree

.github/workflows/api-dev.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ on:
55
branches: [develop]
66
workflow_dispatch:
77

8+
permissions:
9+
contents: read
10+
811
env:
912
AZURE_WEBAPP_NAME: app-dfx-api-dev
1013
AZURE_WEBAPP_PACKAGE_PATH: '.'

.github/workflows/api-pr.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ on:
77
- develop
88
workflow_dispatch:
99

10+
permissions:
11+
contents: read
12+
1013
env:
1114
NODE_VERSION: '20.x'
1215

.github/workflows/api-prd.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ on:
55
branches: [master]
66
workflow_dispatch:
77

8+
permissions:
9+
contents: read
10+
811
env:
912
AZURE_WEBAPP_NAME: app-dfx-api-prd
1013
AZURE_WEBAPP_PACKAGE_PATH: '.'

src/integration/bank/services/olkypay.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export class OlkypayService {
133133
case TransactionType.RECEIVED:
134134
return {
135135
name: tx.line1.split(' Recu ')[1]?.split(' [ Adresse débiteur : ')[0],
136-
addressLine1: tx.line1.split(' [ Adresse débiteur : ')[1]?.replace(']', ''),
136+
addressLine1: tx.line1.split(' [ Adresse débiteur : ')[1]?.replaceAll(']', ''),
137137
};
138138
}
139139

src/integration/blockchain/spark/spark.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export class SparkService extends BlockchainService {
9797

9898
private getAddressPrefix(address: string): string {
9999
const separatorIndex = address.lastIndexOf('1');
100-
if (separatorIndex === -1) return this.NETWORK_PREFIXES.get(SparkNetwork.MAINNET);
100+
if (separatorIndex === -1) return this.NETWORK_PREFIXES.get(SparkNetwork.MAINNET) ?? 'sp';
101101

102102
return address.substring(0, separatorIndex);
103103
}

src/subdomains/core/payment-link/services/ocp-sticker.service.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Injectable, UnauthorizedException } from '@nestjs/common';
1+
import { BadRequestException, Injectable, UnauthorizedException } from '@nestjs/common';
22
import { readFileSync } from 'fs';
33
import { I18nService } from 'nestjs-i18n';
44
import { join } from 'path';
@@ -11,6 +11,8 @@ import { PaymentLink } from '../entities/payment-link.entity';
1111
import { StickerQrMode, StickerType } from '../enums';
1212
import { PaymentLinkService } from './payment-link.service';
1313

14+
const ALLOWED_LANGUAGES = ['en', 'de', 'fr', 'it'];
15+
1416
@Injectable()
1517
export class OCPStickerService {
1618
constructor(
@@ -201,6 +203,11 @@ export class OCPStickerService {
201203
mode = StickerQrMode.CUSTOMER,
202204
userId?: number,
203205
): Promise<Buffer> {
206+
const sanitizedLang = lang.toLowerCase();
207+
if (!ALLOWED_LANGUAGES.includes(sanitizedLang)) {
208+
throw new BadRequestException(`Invalid language: ${lang}. Allowed: ${ALLOWED_LANGUAGES.join(', ')}`);
209+
}
210+
204211
const links = await this.fetchPaymentLinks(routeIdOrLabel, externalIds, ids);
205212

206213
const posUrls: Map<string, string> = new Map();
@@ -216,8 +223,8 @@ export class OCPStickerService {
216223
// Bitcoin Focus OCP Sticker
217224
const stickerFileName =
218225
mode === StickerQrMode.POS
219-
? `ocp-bitcoin-focus-sticker-pos_${lang.toLowerCase()}.png`
220-
: `ocp-bitcoin-focus-sticker_${lang.toLowerCase()}.png`;
226+
? `ocp-bitcoin-focus-sticker-pos_${sanitizedLang}.png`
227+
: `ocp-bitcoin-focus-sticker_${sanitizedLang}.png`;
221228
const stickerPath = join(process.cwd(), 'assets', stickerFileName);
222229
const stickerBuffer = readFileSync(stickerPath);
223230

src/subdomains/generic/gs/gs.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,8 @@ export class GsService {
12971297
}
12981298

12991299
// MSSQL requires ORDER BY for OFFSET/FETCH - add dummy order if missing
1300-
const hasOrderBy = /\border\s+by\b/i.test(sql);
1300+
// Using bounded quantifier {1,100} to prevent ReDoS while supporting tabs/multiple spaces
1301+
const hasOrderBy = /order\s{1,100}by/i.test(sql);
13011302
const orderByClause = hasOrderBy ? '' : ' ORDER BY (SELECT NULL)';
13021303

13031304
return `${sql.trim().replace(/;*$/, '')}${orderByClause} OFFSET 0 ROWS FETCH NEXT ${

0 commit comments

Comments
 (0)