reverted helmet interceptor

This commit is contained in:
gsmithun4 2024-08-09 14:55:42 +05:30
parent 394be5ff34
commit 8d9d86cf2c
6 changed files with 122 additions and 107 deletions

22
CODEOWNERS Normal file
View file

@ -0,0 +1,22 @@
# Code owners for specific package.json and package-lock.json files
/server/package.json @shah21 @gsmithun4 @adishm98
/server/package-lock.json @shah21 @gsmithun4 @adishm98
/frontend/package.json @shah21 @gsmithun4 @adishm98
/frontend/package-lock.json @shah21 @gsmithun4 @adishm98
/marketplace/package.json @shah21 @gsmithun4 @adishm98
/marketplace/package-lock.json @shah21 @gsmithun4 @adishm98
/cypress/package.json @shah21 @gsmithun4 @adishm98
/cypress/package-lock.json @shah21 @gsmithun4 @adishm98
/plugins/package.json @shah21 @gsmithun4 @adishm98
/plugins/package-lock.json @shah21 @gsmithun4 @adishm98
/package.json @shah21 @gsmithun4 @adishm98
/package-lock.json @shah21 @gsmithun4 @adishm98
# Server service files
/server/src/services/email.service.ts @shah21 @gsmithun4
/server/src/mails @shah21 @gsmithun4

View file

@ -45,10 +45,8 @@ import { ImportExportResourcesModule } from './modules/import_export_resources/i
import { UserResourcePermissionsModule } from '@module/user_resource_permissions/user_resource_permissions.module';
import { PermissionsModule } from '@module/permissions/permissions.module';
import { GetConnection } from './helpers/getconnection';
import { APP_INTERCEPTOR } from '@nestjs/core/constants';
import { HelmetInterceptor } from './interceptors/helmet.interceptor';
import { CustomHeadersInterceptor } from './interceptors/custom-headers.interceptors';
import { InstanceSettingsModule } from '@instance-settings/module';
import { StaticFileServerModule } from '@module/static_file_server/static_file_server.module';
const imports = [
ScheduleModule.forRoot(),
@ -109,6 +107,7 @@ const imports = [
CopilotModule,
OrganizationConstantModule,
TooljetDbModule,
StaticFileServerModule
];
if (process.env.SERVE_CLIENT !== 'false' && process.env.NODE_ENV === 'production') {
@ -146,14 +145,6 @@ if (process.env.ENABLE_TOOLJET_DB === 'true') {
EmailService,
SeedsService,
GetConnection,
{
provide: APP_INTERCEPTOR,
useClass: HelmetInterceptor,
},
{
provide: APP_INTERCEPTOR,
useClass: CustomHeadersInterceptor,
},
],
})
export class AppModule implements OnModuleInit {

View file

@ -1,17 +0,0 @@
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class CustomHeadersInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map((data) => {
const response = context.switchToHttp().getResponse();
response.setHeader('Permissions-Policy', 'geolocation=(self), camera=(), microphone=()');
response.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
return data;
})
);
}
}

View file

@ -1,74 +0,0 @@
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import * as helmet from 'helmet';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class HelmetInterceptor implements NestInterceptor {
private readonly helmet: ReturnType<typeof helmet>;
constructor(private configService: ConfigService) {
const host = new URL(this.configService.get('TOOLJET_HOST'));
const domain = host.hostname;
this.helmet = helmet({
contentSecurityPolicy: {
useDefaults: true,
directives: {
upgradeInsecureRequests: null,
'img-src': ['*', 'data:', 'blob:'],
'script-src': [
'maps.googleapis.com',
'storage.googleapis.com',
'apis.google.com',
'accounts.google.com',
"'self'",
"'unsafe-inline'",
"'unsafe-eval'",
'blob:',
'https://unpkg.com/@babel/standalone@7.17.9/babel.min.js',
'https://unpkg.com/react@16.7.0/umd/react.production.min.js',
'https://unpkg.com/react-dom@16.7.0/umd/react-dom.production.min.js',
'cdn.skypack.dev',
'cdn.jsdelivr.net',
'https://esm.sh',
'www.googletagmanager.com',
],
'default-src': [
'maps.googleapis.com',
'storage.googleapis.com',
'apis.google.com',
'accounts.google.com',
'*.sentry.io',
"'self'",
'blob:',
'www.googletagmanager.com',
],
'connect-src': ['ws://' + domain, "'self'", '*'],
'frame-ancestors': ['*'],
'frame-src': ['*'],
},
},
frameguard:
this.configService.get('DISABLE_APP_EMBED') !== 'true' ||
this.configService.get('ENABLE_PRIVATE_APP_EMBED') === 'true'
? false
: { action: 'deny' },
hidePoweredBy: true,
referrerPolicy: {
policy: 'no-referrer',
},
});
}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const httpContext = context.switchToHttp();
const request = httpContext.getRequest();
const response = httpContext.getResponse();
return new Observable((subscriber) => {
this.helmet(request, response, () => {
next.handle().subscribe(subscriber);
});
});
}
}

View file

@ -11,6 +11,7 @@ import { RequestMethod, ValidationPipe, VersioningType, VERSION_NEUTRAL } from '
import { ConfigService } from '@nestjs/config';
import { bootstrap as globalAgentBootstrap } from 'global-agent';
import { join } from 'path';
import * as helmet from 'helmet';
const fs = require('fs');
@ -39,6 +40,72 @@ function replaceSubpathPlaceHoldersInStaticAssets() {
}
}
function setSecurityHeaders(app, configService) {
const tooljetHost = configService.get('TOOLJET_HOST');
const host = new URL(tooljetHost);
const domain = host.hostname;
app.enableCors({
origin: configService.get('ENABLE_CORS') === 'true' || tooljetHost,
credentials: true,
});
app.use(helmet({
contentSecurityPolicy: {
useDefaults: true,
directives: {
upgradeInsecureRequests: null,
'img-src': ['*', 'data:', 'blob:'],
'script-src': [
'maps.googleapis.com',
'storage.googleapis.com',
'apis.google.com',
'accounts.google.com',
"'self'",
"'unsafe-inline'",
"'unsafe-eval'",
'blob:',
'https://unpkg.com/@babel/standalone@7.17.9/babel.min.js',
'https://unpkg.com/react@16.7.0/umd/react.production.min.js',
'https://unpkg.com/react-dom@16.7.0/umd/react-dom.production.min.js',
'cdn.skypack.dev',
'cdn.jsdelivr.net',
'https://esm.sh',
'www.googletagmanager.com',
],
'default-src': [
'maps.googleapis.com',
'storage.googleapis.com',
'apis.google.com',
'accounts.google.com',
'*.sentry.io',
"'self'",
'blob:',
'www.googletagmanager.com',
],
'connect-src': ['ws://' + domain, "'self'", '*'],
'frame-ancestors': ['*'],
'frame-src': ['*'],
},
},
frameguard:
configService.get('DISABLE_APP_EMBED') !== 'true' ||
configService.get('ENABLE_PRIVATE_APP_EMBED') === 'true'
? false
: { action: 'deny' },
hidePoweredBy: true,
referrerPolicy: {
policy: 'no-referrer',
},
}));
app.use((req, res, next) => {
res.setHeader('Permissions-Policy', 'geolocation=(self), camera=(), microphone=()');
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
return next();
});
}
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
bufferLogs: true,
@ -64,20 +131,17 @@ async function bootstrap() {
app.setGlobalPrefix(UrlPrefix + 'api', {
exclude: pathsToExclude,
});
app.enableCors({
origin: process.env.ENABLE_CORS === 'true' || process.env.TOOLJET_HOST,
credentials: true,
});
app.use(compression());
app.use(cookieParser());
app.use(json({ limit: '50mb' }));
app.use(urlencoded({ extended: true, limit: '50mb', parameterLimit: 1000000 }));
app.useStaticAssets(join(__dirname, 'assets'), { prefix: (UrlPrefix ? UrlPrefix : '/') + 'assets' });
app.enableVersioning({
type: VersioningType.URI,
defaultVersion: VERSION_NEUTRAL,
});
setSecurityHeaders(app, configService);
const listen_addr = process.env.LISTEN_ADDR || '::';
const port = parseInt(process.env.PORT) || 3000;

View file

@ -0,0 +1,29 @@
import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
const hasSubPath = process.env.SUB_PATH !== undefined;
const UrlPrefix = hasSubPath ? process.env.SUB_PATH : '';
const imports = [
ServeStaticModule.forRoot({
rootPath: join(__dirname, 'assets'),
serveRoot: (UrlPrefix ? UrlPrefix : '/../../../') + 'assets',
})
]
if (process.env.SERVE_CLIENT !== 'false' && process.env.NODE_ENV === 'production') {
imports.unshift(
ServeStaticModule.forRoot({
// Have to remove trailing slash of SUB_PATH.
serveRoot: process.env.SUB_PATH === undefined ? '' : process.env.SUB_PATH.replace(/\/$/, ''),
rootPath: join(__dirname, '../../../../../', 'frontend/build'),
})
)
}
@Module({
imports
})
export class StaticFileServerModule {}