sofya.transcription
Version:
a JavaScript library that provides a robust and flexible solution for real-time audio transcription. It is designed to transcribe audio streams and can be easily integrated into web applications.
157 lines • 6.26 kB
JavaScript
;
/**
* Security validation utilities for WebSocket connections.
* Provides protection against injection attacks and ensures URL safety.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketSecurityValidator = void 0;
/**
* Malicious patterns to detect in query parameter values
*/
var MALICIOUS_PATTERNS = [
/[\x00\n\r\t]/, // Control characters
/<script/i, // XSS attempts
/javascript:/i, // JS protocol
/on\w+\s*=/i, // Event handlers (onClick, etc)
/[';"]\.*?(DROP|DELETE|INSERT|UPDATE|UNION|SELECT)/i // SQL injection
];
/**
* Sensitive keys that should trigger security warnings
*/
var SENSITIVE_KEYS = [
'token', 'password', 'secret', 'api_key', 'apikey',
'auth', 'credential', 'pass', 'key', 'bearer'
];
/**
* Internal parameters that always take precedence
*/
var INTERNAL_PARAMS = [
'transcription_language',
'translation_language'
];
/**
* Validation limits
*/
var LIMITS = {
keyPattern: /^[a-zA-Z0-9_-]+$/,
maxValueLength: 1000,
maxUrlLength: 2000
};
/**
* WebSocket security validator class
*/
var WebSocketSecurityValidator = /** @class */ (function () {
function WebSocketSecurityValidator() {
this.rules = {
keyPattern: LIMITS.keyPattern,
maxValueLength: LIMITS.maxValueLength,
maxUrlLength: LIMITS.maxUrlLength,
internalParams: INTERNAL_PARAMS,
sensitiveKeys: SENSITIVE_KEYS
};
}
/**
* Validates a query parameter key
* @param key - The key to validate
* @throws Error if key format is invalid
*/
WebSocketSecurityValidator.prototype.validateQueryParamKey = function (key) {
if (!this.rules.keyPattern.test(key)) {
throw new Error("Invalid queryParam key: \"".concat(key, "\". Keys must match ").concat(this.rules.keyPattern.toString()));
}
};
/**
* Validates a query parameter value
* @param key - The parameter key (for error messages)
* @param value - The value to validate
* @throws Error if value is too long or contains malicious patterns
*/
WebSocketSecurityValidator.prototype.validateQueryParamValue = function (key, value) {
// Check length
if (value.length > this.rules.maxValueLength) {
throw new Error("queryParam value for key \"".concat(key, "\" exceeds ").concat(this.rules.maxValueLength, " characters"));
}
// Check for malicious patterns
for (var _i = 0, MALICIOUS_PATTERNS_1 = MALICIOUS_PATTERNS; _i < MALICIOUS_PATTERNS_1.length; _i++) {
var pattern = MALICIOUS_PATTERNS_1[_i];
if (pattern.test(value)) {
throw new Error("Malicious pattern detected in queryParam value for key \"".concat(key, "\""));
}
}
};
/**
* Warns if sensitive keys are detected in query parameters
* @param keys - Array of parameter keys to check
*/
WebSocketSecurityValidator.prototype.warnSensitiveKeys = function (keys) {
var _this = this;
var foundSensitiveKeys = keys.filter(function (key) {
return _this.rules.sensitiveKeys.some(function (sensitive) {
return key.toLowerCase().includes(sensitive);
});
});
if (foundSensitiveKeys.length > 0) {
console.warn('⚠️ Security Warning: Potentially sensitive data detected in queryParams. ' +
'Query parameters are visible in logs. Consider using protocols instead.');
}
};
/**
* Checks if the final WebSocket URL exceeds maximum length
* @param url - The URL to check
* @throws Error if URL is too long
*/
WebSocketSecurityValidator.prototype.checkUrlLength = function (url) {
if (url.length > this.rules.maxUrlLength) {
throw new Error("WebSocket URL exceeds ".concat(this.rules.maxUrlLength, " characters (current: ").concat(url.length, "). ") +
'Reduce queryParams or use protocols.');
}
};
/**
* Detects collision between custom params and internal params
* @param customParams - Custom query parameters
* @returns Object with validated params (internal params removed) and collision warnings
*/
WebSocketSecurityValidator.prototype.detectCollisions = function (customParams) {
var validatedParams = {};
var collisions = [];
for (var _i = 0, _a = Object.entries(customParams); _i < _a.length; _i++) {
var _b = _a[_i], key = _b[0], value = _b[1];
if (this.rules.internalParams.includes(key)) {
collisions.push(key);
}
else {
validatedParams[key] = value;
}
}
// Warn about collisions
if (collisions.length > 0) {
collisions.forEach(function (key) {
var suggestion = key === 'transcription_language' ? 'config.language' : 'config.translation_lang';
console.warn("Custom queryParams ".concat(key, " ignored - use ").concat(suggestion, " instead."));
});
}
return { validatedParams: validatedParams, collisions: collisions };
};
/**
* Validates all query parameters
* @param queryParams - Query parameters to validate
* @returns Validated parameters (with internal params removed)
* @throws Error if any validation fails
*/
WebSocketSecurityValidator.prototype.validateQueryParams = function (queryParams) {
// Warn about sensitive keys
this.warnSensitiveKeys(Object.keys(queryParams));
// Detect and handle collisions
var validatedParams = this.detectCollisions(queryParams).validatedParams;
// Validate each key-value pair
for (var _i = 0, _a = Object.entries(validatedParams); _i < _a.length; _i++) {
var _b = _a[_i], key = _b[0], value = _b[1];
this.validateQueryParamKey(key);
this.validateQueryParamValue(key, value);
}
return validatedParams;
};
return WebSocketSecurityValidator;
}());
exports.WebSocketSecurityValidator = WebSocketSecurityValidator;
//# sourceMappingURL=websocketSecurity.js.map