Api Key Exposure in Feathersjs with Oracle Db
Api Key Exposure in Feathersjs with Oracle Db — how this specific combination creates or exposes the vulnerability
FeathersJS is a framework for creating JavaScript APIs with services that map to database rows. When using an Oracle DB adapter, developers often store connection credentials and potentially API keys in service configuration files or in environment variables referenced by those files. If these configurations are inadvertently exposed through an API endpoint—such as a misconfigured service that returns full database connection objects or logs sensitive parameters—an API key exposure vulnerability occurs.
The risk is compounded when the FeathersJS service does not enforce strict serialization rules. By default, Feathers may return database rows as plain objects. If the row objects include fields that contain API keys or secrets—perhaps stored temporarily for Oracle wallet authentication or token exchange—and those fields are not explicitly filtered, the keys can leak to unauthenticated clients during find, get, or custom method calls.
Oracle DB specific risks include improper handling of external credentials stored in client-accessible configuration or logs. For example, if a Feathers service uses an Oracle connection pool initialized with credentials retrieved from a secure vault, but the service also exposes a debug or introspection endpoint that echoes the pool configuration, the API key used for database authentication could be revealed. Attackers scanning the API with tools that perform black-box testing, such as automated scanners that run 12 parallel security checks, may identify these exposures as part of the unauthenticated attack surface assessment, flagging them under Data Exposure and Authentication checks.
Real-world scenarios include logging Oracle bind variables that contain keys, or returning stack traces that include connection strings when Oracle driver errors are not properly sanitized. Because FeathersJS can integrate with multiple transports (REST, Socket.io), inconsistent handling across channels may lead to keys being exposed over WebSocket connections as well. The exposure is not inherent to FeathersJS or Oracle DB individually, but arises from insecure configuration management, improper serialization, and insufficient input validation that allows an attacker to coax sensitive data out through crafted requests.
middleBrick scans perform unauthenticated testing across 12 security checks including Data Exposure and Authentication, and can surface such issues by correlating OpenAPI specs with runtime behavior, helping teams detect accidental key leakage before it is exploited.
Oracle Db-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on ensuring that Oracle DB credentials and any API keys are never serialized into API responses and are properly isolated from client-facing data paths. Below are concrete, realistic code examples for a FeathersJS service using the Oracle DB adapter.
1. Secure Oracle Connection Initialization
Store credentials outside of service definitions and load them via environment variables. Use Oracle wallet or external configuration without embedding keys in code.
// config/oracle.js
module.exports = {
user: process.env.ORACLE_USER,
password: process.env.ORACLE_PASSWORD,
connectString: process.env.ORACLE_CONNECT_STRING,
options: {
wallet: {
location: process.env.WALLET_LOCATION,
password: process.env.WALLET_PASSWORD
}
}
};
Initialize the pool in a separate module and import it where needed, avoiding direct exposure through Feathers service getters.
// db/oraclePool.js
const oracledb = require('oraccledb');
const oracleConfig = require('../config/oracle');
async function getPool() {
if (!global.__oraclePool) {
await oracledb.createPool({
user: oracleConfig.user,
password: oracleConfig.password,
connectString: oracleConfig.connectString,
poolMax: 10
});
global.__oraclePool = oracledb.getPool();
}
return global.__oraclePool;
}
module.exports = { getPool };
2. Feathers Service with Data Sanitization
Define a custom Feathers hook that removes sensitive Oracle-related fields before sending results to the client.
// hooks/sanitize.js
module.exports = function sanitizeSensitiveFields() {
return async context => {
if (context.result && Array.isArray(context.result.data)) {
context.result.data = context.result.data.map(row => {
// Explicitly remove fields that may contain API keys or Oracle wallet tokens
const { api_key, wallet_token, ...safeRow } = row;
return safeRow;
});
} else if (context.result && context.result.data) {
const { api_key, wallet_token, ...safeRow } = context.result.data;
context.result.data = safeRow;
}
return context;
};
};
Apply the hook in your service definition:
// services/records/records.service.js
const { Pool } = require('oracledb');
const { getPool } = require('../../db/oraclePool');
const sanitizeHook = require('../../hooks/sanitize');
module.exports = function (app) {
const service = new (require('feathers-sequelize'))({
name: 'records',
// Oracle-specific initialization would happen in a custom Model class
Model: class RecordsModel {
constructor(options) {
this.app = app;
this.options = options;
}
async getConnection() {
const pool = await getPool();
return pool.getConnection();
}
}
});
service.hooks({
before: {},
after: { all: [sanitizeHook()] },
error: { all: [] }
});
app.use('/records', service);
};
3. Preventing Error Leakage
Ensure Oracle errors do not expose connection strings or internal paths in responses. Intercept and sanitize error objects in an error handling hook.
// hooks/error-handle.js
module.exports = function errorHandlerHook() {
return async context => {
if (context.error && context.error.message) {
// Remove Oracle specific sensitive details
context.error.message = context.error.message
.replace(/(\bconnect string[=:]['"]?)[^'"]+/gi, '$1***')
.replace(/(\bpassword[=:]['"]?)[^'"]+/gi, '$1***');
// Avoid returning stack traces in production
if (process.env.NODE_ENV !== 'development') {
delete context.error.stack;
}
}
return context;
};
};
Register this hook globally or per-service to ensure that any Oracle driver exceptions are stripped of sensitive data before reaching the API consumer.
4. Validate and Restrict Input to Prevent Injection-Based Exposure
Use Feathers hooks to validate query parameters that might be used to construct dynamic Oracle SQL, preventing injection that could lead to key exposure via error messages.
// hooks/validate.js
const { query } = require('feathers-hooks-common');
module.exports = {
before: {
all: [
query({
name: { $notEmpty: true },
$sanitize: {
html: false,
strip: true
}
})
]
}
};