Skip to content

Commit b5634ac

Browse files
authored
Merge pull request #1575 from rocket-admin/backend_security_report
refactor: improve code formatting and add escapeRegex method for safer regex usage
2 parents 14d2da6 + c15d3c5 commit b5634ac

File tree

5 files changed

+729
-726
lines changed

5 files changed

+729
-726
lines changed

autoadmin-ws-server/src/services/token-validator.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export async function validateConnectionToken(connectionToken: string): Promise<
2121

2222
try {
2323
const checkUrl = `${config.checkConnectionTokenUrl}?token=${connectionToken}`;
24-
logger.info({ url: checkUrl }, 'Validating connection token');
2524

2625
const response = await fetch(checkUrl);
2726

backend/src/entities/visualizations/saved-db-query/utils/check-query-is-safe.util.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ export function validateQuerySafety(query: string, connectionType: ConnectionTyp
249249

250250
function normalizeQuery(query: string): string {
251251
return query
252+
.replace(/\/\*!(\d+)?\s*([\s\S]*?)\*\//g, ' $2 ')
253+
.replace(/#.*$/gm, '')
252254
.replace(/--.*$/gm, '')
253255
.replace(/\/\*[\s\S]*?\*\//g, '')
254256
.replace(/\s+/g, ' ')

backend/src/main.ts

Lines changed: 77 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -15,91 +15,89 @@ import { Constants } from './helpers/constants/constants.js';
1515
import { requiredEnvironmentVariablesValidator } from './helpers/validators/required-environment-variables.validator.js';
1616

1717
async function bootstrap() {
18-
try {
19-
requiredEnvironmentVariablesValidator();
20-
const appOptions: NestApplicationOptions = {
21-
rawBody: true,
22-
logger: new WinstonLogger(),
23-
};
24-
25-
const app = await NestFactory.create<NestExpressApplication>(ApplicationModule, appOptions);
26-
app.useLogger(app.get(WinstonLogger));
27-
app.set('query parser', 'extended');
28-
29-
Sentry.init({
30-
dsn: process.env.SENTRY_DSN,
31-
tracesSampleRate: 1.0,
32-
});
33-
34-
const globalPrefix = process.env.GLOBAL_PREFIX || '/';
35-
app.setGlobalPrefix(globalPrefix);
36-
37-
app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger)));
38-
39-
app.use(helmet());
40-
41-
app.use(cookieParser());
42-
43-
app.enableCors({
44-
origin: [
45-
'https://app.autoadmin.org',
46-
'http://localhost:4200',
47-
'https://app.rocketadmin.org',
48-
'https://saas.rocketadmin.com',
49-
'https://app-beta.rocketadmin.com',
50-
Constants.APP_DOMAIN_ADDRESS,
51-
],
52-
methods: 'GET,PUT,PATCH,POST,DELETE',
53-
credentials: true,
54-
preflightContinue: false,
55-
optionsSuccessStatus: 204,
56-
});
57-
58-
app.use(cookieParser());
59-
60-
app.use(bodyParser.json({ limit: '10mb' }));
61-
app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));
62-
63-
const config = new DocumentBuilder()
64-
.setTitle('Rocketadmin')
65-
.setDescription('The Rocketadmin API description')
66-
.setVersion('1.0')
67-
.addTag('rocketadmin')
68-
.setBasePath(globalPrefix)
69-
.addApiKey({
70-
type: 'apiKey',
71-
name: 'x-api-key',
72-
in: 'header',
73-
})
74-
.addCookieAuth(Constants.JWT_COOKIE_KEY_NAME)
75-
.build();
76-
const document = SwaggerModule.createDocument(app, config);
77-
SwaggerModule.setup('docs', app, document);
78-
79-
app.useGlobalPipes(
80-
new ValidationPipe({
81-
exceptionFactory(validationErrors: ValidationError[] = []) {
82-
return new ValidationException(validationErrors);
83-
},
84-
}),
85-
);
86-
87-
await app.listen(3000);
88-
} catch (e) {
89-
console.error(`Failed to initialize, due to ${e}`);
90-
process.exit(1);
91-
}
18+
try {
19+
requiredEnvironmentVariablesValidator();
20+
const appOptions: NestApplicationOptions = {
21+
rawBody: true,
22+
logger: new WinstonLogger(),
23+
};
24+
25+
const app = await NestFactory.create<NestExpressApplication>(ApplicationModule, appOptions);
26+
app.useLogger(app.get(WinstonLogger));
27+
app.set('query parser', 'extended');
28+
29+
Sentry.init({
30+
dsn: process.env.SENTRY_DSN,
31+
tracesSampleRate: 1.0,
32+
});
33+
34+
const globalPrefix = process.env.GLOBAL_PREFIX || '/';
35+
app.setGlobalPrefix(globalPrefix);
36+
37+
app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger)));
38+
39+
app.use(helmet());
40+
41+
app.enableCors({
42+
origin: [
43+
'https://app.autoadmin.org',
44+
'http://localhost:4200',
45+
'https://app.rocketadmin.org',
46+
'https://saas.rocketadmin.com',
47+
'https://app-beta.rocketadmin.com',
48+
Constants.APP_DOMAIN_ADDRESS,
49+
],
50+
methods: 'GET,PUT,PATCH,POST,DELETE',
51+
credentials: true,
52+
preflightContinue: false,
53+
optionsSuccessStatus: 204,
54+
});
55+
56+
app.use(cookieParser());
57+
58+
app.use(bodyParser.json({ limit: '10mb' }));
59+
app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));
60+
61+
const config = new DocumentBuilder()
62+
.setTitle('Rocketadmin')
63+
.setDescription('The Rocketadmin API description')
64+
.setVersion('1.0')
65+
.addTag('rocketadmin')
66+
.setBasePath(globalPrefix)
67+
.addApiKey({
68+
type: 'apiKey',
69+
name: 'x-api-key',
70+
in: 'header',
71+
})
72+
.addCookieAuth(Constants.JWT_COOKIE_KEY_NAME)
73+
.build();
74+
const document = SwaggerModule.createDocument(app, config);
75+
SwaggerModule.setup('docs', app, document);
76+
77+
app.useGlobalPipes(
78+
new ValidationPipe({
79+
exceptionFactory(validationErrors: ValidationError[] = []) {
80+
return new ValidationException(validationErrors);
81+
},
82+
}),
83+
);
84+
85+
await app.listen(3000);
86+
} catch (e) {
87+
console.error(`Failed to initialize, due to ${e}`);
88+
process.exit(1);
89+
}
9290
}
9391

9492
const temp = process.exit;
9593

9694
process.exit = () => {
97-
console.trace();
98-
process.exit = temp;
99-
process.exit();
95+
console.trace();
96+
process.exit = temp;
97+
process.exit();
10098
};
10199

102100
bootstrap().catch((e) => {
103-
console.error(`Bootstrap promise failed with error: ${e}`);
104-
process.exit(1);
101+
console.error(`Bootstrap promise failed with error: ${e}`);
102+
process.exit(1);
105103
});
Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,45 @@
11
import { BadRequestException, Injectable } from '@nestjs/common';
22
import axios from 'axios';
3+
import { isTest } from '../../helpers/app/is-test.js';
4+
import { isSaaS } from '../../helpers/app/is-saas.js';
35

46
interface TurnstileVerifyResponse {
5-
success: boolean;
6-
'error-codes'?: string[];
7-
challenge_ts?: string;
8-
hostname?: string;
7+
success: boolean;
8+
'error-codes'?: string[];
9+
challenge_ts?: string;
10+
hostname?: string;
911
}
1012

1113
@Injectable()
1214
export class TurnstileService {
13-
private readonly verifyUrl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
15+
private readonly verifyUrl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
1416

15-
async verifyToken(token: string): Promise<boolean> {
16-
const secretKey = process.env.TURNSTILE_SECRET_KEY;
17+
async verifyToken(token: string): Promise<boolean> {
18+
const secretKey = process.env.TURNSTILE_SECRET_KEY;
1719

18-
if (!secretKey) {
19-
console.warn('Turnstile secret key is not configured. Skipping verification.');
20-
return true;
21-
}
20+
if (isTest() || !isSaaS()) {
21+
return true;
22+
}
2223

23-
if (!token || typeof token !== 'string') {
24-
throw new BadRequestException('Turnstile token is required.');
25-
}
24+
if (!token || typeof token !== 'string') {
25+
throw new BadRequestException('Turnstile token is required.');
26+
}
2627

27-
const formData = new URLSearchParams();
28-
formData.append('secret', secretKey);
29-
formData.append('response', token);
28+
const formData = new URLSearchParams();
29+
formData.append('secret', secretKey);
30+
formData.append('response', token);
3031

31-
const response = await axios.post<TurnstileVerifyResponse>(this.verifyUrl, formData.toString(), {
32-
headers: {
33-
'Content-Type': 'application/x-www-form-urlencoded',
34-
},
35-
});
32+
const response = await axios.post<TurnstileVerifyResponse>(this.verifyUrl, formData.toString(), {
33+
headers: {
34+
'Content-Type': 'application/x-www-form-urlencoded',
35+
},
36+
});
3637

37-
if (!response.data.success) {
38-
const errorCodes = response.data['error-codes']?.join(', ') || 'Unknown error';
39-
throw new BadRequestException(`Turnstile verification failed: ${errorCodes}`);
40-
}
38+
if (!response.data.success) {
39+
const errorCodes = response.data['error-codes']?.join(', ') || 'Unknown error';
40+
throw new BadRequestException(`Turnstile verification failed: ${errorCodes}`);
41+
}
4142

42-
return true;
43-
}
43+
return true;
44+
}
4445
}

0 commit comments

Comments
 (0)