Api Key Exposure in Nestjs with Oracle Db
Api Key Exposure in Nestjs with Oracle Db — how this specific combination creates or exposes the vulnerability
When a NestJS application uses an Oracle Database connection, developers often store database credentials in environment variables or configuration files. If these configurations are accidentally exposed through logging, error messages, or improper middleware, API keys or connection strings for the Oracle Db can be leaked.
In NestJS, services that interact with Oracle Db typically use the oracledb package. If the configuration object containing the user, password, and connection string is passed to frontend code or returned in an API response, the API key is exposed. For example, returning the full Oracle configuration from a controller can disclose sensitive credentials to unauthenticated clients.
Another common scenario occurs during error handling. Unhandled exceptions in NestJS controllers can include stack traces that reveal Oracle connection parameters. Without proper input validation and error masking, an attacker could trigger errors that expose the API key used for database access.
The 12 security checks in middleBrick detect this type of exposure under Data Exposure and Input Validation. The scanner checks whether API endpoints inadvertently return configuration objects or sensitive strings that match patterns associated with database credentials. This is especially critical in unauthenticated scans, where endpoints are probed without prior access to verify whether sensitive information is publicly accessible.
Additionally, middleware that logs incoming requests may inadvertently capture authorization tokens or keys if they are included in headers or query parameters. In a NestJS application using Oracle Db, if these logs are stored or transmitted without protection, the API key is at risk. middleBrick includes checks for unsafe consumption and data exposure to identify such insecure logging practices.
Oracle Db-Specific Remediation in Nestjs — concrete code fixes
To prevent API key exposure when using Oracle Db in NestJS, keep database credentials out of runtime contexts and ensure they are never returned to the client. Use environment variables and a configuration service to manage sensitive data securely.
Secure Configuration Service
Create a dedicated configuration module that loads environment variables at startup and provides sanitized settings. This prevents accidental exposure through controllers or logs.
// config/oracle.config.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class OracleConfig {
readonly user: string;
readonly password: string;
readonly connectionString: string;
constructor() {
this.user = process.env.ORACLE_USER;
this.password = process.env.ORACLE_PASSWORD;
this.connectionString = process.env.ORACLE_CONNECTION_STRING;
}
getConnectionOptions() {
return {
user: this.user,
password: this.password,
connectString: this.connectionString,
};
}
}
Controller Best Practices
Never return configuration objects or raw database credentials from API endpoints. Map database results to safe DTOs and exclude sensitive fields explicitly.
// dto/user.dto.ts
export class UserDto {
id: number;
username: string;
email: string;
}
// user.controller.ts
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { OracleConfig } from '../config/oracle.config';
import { UserDto } from './dto/user.dto';
import { map } from 'rxjs/operators';
@Controller('users')
export class UserController {
constructor(private readonly oracleConfig: OracleConfig) {}
@Get()
async getUsers() {
const connection = await oracledb.getConnection(this.oracleConfig.getConnectionOptions());
const result = await connection.execute(`SELECT id, username, email FROM users`);
return result.rows.map(row => new UserDto(row[0], row[1], row[2]));
}
}
Error Handling and Masking
Implement a global exception filter to prevent stack traces from exposing Oracle connection details. This ensures that any database-related errors do not reveal sensitive information.
// filters/http-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { OracleConfig } from '../config/oracle.config';
@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
constructor(private readonly oracleConfig: OracleConfig) {}
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const status = exception instanceof HttpException ? exception.getStatus() : 500;
// Do not expose Oracle-specific error details
response.status(status).json({
statusCode: status,
message: status >= 500 ? 'Internal server error' : exception['message'],
});
}
}
Environment and Runtime Protection
Ensure that environment variables used by OracleConfig are not accessible through endpoints. Use process-level restrictions and avoid including configuration in logs or responses. middleBrick’s Data Exposure and Unsafe Consumption checks validate that no endpoint returns sensitive configuration patterns.
Valid Oracle Query Execution in NestJS
Use parameterized queries to avoid injection and ensure that credentials are handled securely by the oracledb driver. The connection options should be sourced exclusively from the secure configuration service.
// data/oracle.service.ts
import { Injectable } from '@nestjs/common';
import * as oracledb from 'oracledb';
import { OracleConfig } from '../config/oracle.config';
@Injectable()
export class OracleService {
constructor(private readonly oracleConfig: OracleConfig) {}
async executeQuery(sql: string, binds: any[] = []) {
let connection;
try {
connection = await oracledb.getConnection(this.oracleConfig.getConnectionOptions());
const result = await connection.execute(sql, binds);
return result.rows;
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
// ignore
}
}
}
}
}