@olane/o-server 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/interfaces/server-config.interface.d.ts +47 -1
- package/dist/src/interfaces/server-config.interface.d.ts.map +1 -1
- package/dist/src/middleware/error-handler.d.ts +9 -0
- package/dist/src/middleware/error-handler.d.ts.map +1 -1
- package/dist/src/middleware/error-handler.js +49 -3
- package/dist/src/middleware/jwt-auth.d.ts +54 -0
- package/dist/src/middleware/jwt-auth.d.ts.map +1 -0
- package/dist/src/middleware/jwt-auth.js +145 -0
- package/dist/src/o-server.d.ts.map +1 -1
- package/dist/src/o-server.js +53 -23
- package/dist/src/validation/address-validator.d.ts +13 -0
- package/dist/src/validation/address-validator.d.ts.map +1 -0
- package/dist/src/validation/address-validator.js +40 -0
- package/dist/src/validation/index.d.ts +17 -0
- package/dist/src/validation/index.d.ts.map +1 -0
- package/dist/src/validation/index.js +16 -0
- package/dist/src/validation/method-validator.d.ts +13 -0
- package/dist/src/validation/method-validator.d.ts.map +1 -0
- package/dist/src/validation/method-validator.js +36 -0
- package/dist/src/validation/params-sanitizer.d.ts +15 -0
- package/dist/src/validation/params-sanitizer.d.ts.map +1 -0
- package/dist/src/validation/params-sanitizer.js +51 -0
- package/dist/src/validation/request-validator.d.ts +53 -0
- package/dist/src/validation/request-validator.d.ts.map +1 -0
- package/dist/src/validation/request-validator.js +53 -0
- package/dist/src/validation/validation-error.d.ts +11 -0
- package/dist/src/validation/validation-error.d.ts.map +1 -0
- package/dist/src/validation/validation-error.js +12 -0
- package/dist/test/ai.spec.d.ts +0 -1
- package/dist/test/ai.spec.js +20 -13
- package/dist/test/error-security.spec.d.ts +2 -0
- package/dist/test/error-security.spec.d.ts.map +1 -0
- package/dist/test/error-security.spec.js +134 -0
- package/dist/test/input-validation.spec.d.ts +14 -0
- package/dist/test/input-validation.spec.d.ts.map +1 -0
- package/dist/test/input-validation.spec.js +487 -0
- package/dist/test/jwt-auth.spec.d.ts +2 -0
- package/dist/test/jwt-auth.spec.d.ts.map +1 -0
- package/dist/test/jwt-auth.spec.js +397 -0
- package/package.json +10 -4
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively sanitizes parameters by removing dangerous properties
|
|
3
|
+
* that could lead to prototype pollution attacks
|
|
4
|
+
*
|
|
5
|
+
* Security features:
|
|
6
|
+
* - Removes __proto__, constructor, and prototype properties
|
|
7
|
+
* - Recursive traversal for nested objects
|
|
8
|
+
* - Array handling
|
|
9
|
+
* - Preserves safe nested structures
|
|
10
|
+
*
|
|
11
|
+
* @param params - The parameters to sanitize (can be any type)
|
|
12
|
+
* @returns Sanitized copy of the parameters
|
|
13
|
+
*/
|
|
14
|
+
export declare function sanitizeParams(params: any): any;
|
|
15
|
+
//# sourceMappingURL=params-sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"params-sanitizer.d.ts","sourceRoot":"","sources":["../../../src/validation/params-sanitizer.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAyC/C"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dangerous property names that should be removed to prevent prototype pollution
|
|
3
|
+
*/
|
|
4
|
+
const DANGEROUS_KEYS = ['__proto__', 'constructor', 'prototype'];
|
|
5
|
+
/**
|
|
6
|
+
* Recursively sanitizes parameters by removing dangerous properties
|
|
7
|
+
* that could lead to prototype pollution attacks
|
|
8
|
+
*
|
|
9
|
+
* Security features:
|
|
10
|
+
* - Removes __proto__, constructor, and prototype properties
|
|
11
|
+
* - Recursive traversal for nested objects
|
|
12
|
+
* - Array handling
|
|
13
|
+
* - Preserves safe nested structures
|
|
14
|
+
*
|
|
15
|
+
* @param params - The parameters to sanitize (can be any type)
|
|
16
|
+
* @returns Sanitized copy of the parameters
|
|
17
|
+
*/
|
|
18
|
+
export function sanitizeParams(params) {
|
|
19
|
+
// Handle null and undefined
|
|
20
|
+
if (params === null || params === undefined) {
|
|
21
|
+
return params;
|
|
22
|
+
}
|
|
23
|
+
// Handle primitives (string, number, boolean)
|
|
24
|
+
if (typeof params !== 'object') {
|
|
25
|
+
return params;
|
|
26
|
+
}
|
|
27
|
+
// Handle arrays - recursively sanitize each element
|
|
28
|
+
if (Array.isArray(params)) {
|
|
29
|
+
return params.map((item) => sanitizeParams(item));
|
|
30
|
+
}
|
|
31
|
+
// Handle objects - create sanitized copy
|
|
32
|
+
const sanitized = {};
|
|
33
|
+
for (const key in params) {
|
|
34
|
+
// Skip if not own property
|
|
35
|
+
if (!Object.prototype.hasOwnProperty.call(params, key)) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// Skip dangerous keys (case-sensitive check)
|
|
39
|
+
if (DANGEROUS_KEYS.includes(key)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
// Also check case-insensitive variants to be extra safe
|
|
43
|
+
const lowerKey = key.toLowerCase();
|
|
44
|
+
if (DANGEROUS_KEYS.some((dk) => dk.toLowerCase() === lowerKey)) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// Recursively sanitize the value
|
|
48
|
+
sanitized[key] = sanitizeParams(params[key]);
|
|
49
|
+
}
|
|
50
|
+
return sanitized;
|
|
51
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Schema for POST /use endpoint
|
|
4
|
+
* Validates the main node.use() request format
|
|
5
|
+
*/
|
|
6
|
+
export declare const useRequestSchema: z.ZodObject<{
|
|
7
|
+
address: z.ZodString;
|
|
8
|
+
method: z.ZodString;
|
|
9
|
+
params: z.ZodOptional<z.ZodAny>;
|
|
10
|
+
id: z.ZodOptional<z.ZodString>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
address: string;
|
|
13
|
+
method: string;
|
|
14
|
+
params?: any;
|
|
15
|
+
id?: string | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
address: string;
|
|
18
|
+
method: string;
|
|
19
|
+
params?: any;
|
|
20
|
+
id?: string | undefined;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Schema for POST /:address/:method endpoint
|
|
24
|
+
* This endpoint accepts any body as params
|
|
25
|
+
*/
|
|
26
|
+
export declare const convenienceRequestSchema: z.ZodAny;
|
|
27
|
+
/**
|
|
28
|
+
* Schema for POST /use/stream endpoint
|
|
29
|
+
* Similar to useRequestSchema but without id
|
|
30
|
+
*/
|
|
31
|
+
export declare const streamRequestSchema: z.ZodObject<{
|
|
32
|
+
address: z.ZodString;
|
|
33
|
+
method: z.ZodString;
|
|
34
|
+
params: z.ZodOptional<z.ZodAny>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
address: string;
|
|
37
|
+
method: string;
|
|
38
|
+
params?: any;
|
|
39
|
+
}, {
|
|
40
|
+
address: string;
|
|
41
|
+
method: string;
|
|
42
|
+
params?: any;
|
|
43
|
+
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Validates request data against a Zod schema
|
|
46
|
+
*
|
|
47
|
+
* @param data - The data to validate
|
|
48
|
+
* @param schema - The Zod schema to validate against
|
|
49
|
+
* @returns The validated and parsed data
|
|
50
|
+
* @throws {ValidationError} If validation fails
|
|
51
|
+
*/
|
|
52
|
+
export declare function validateRequest<T>(data: unknown, schema: z.ZodSchema<T>): T;
|
|
53
|
+
//# sourceMappingURL=request-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-validator.d.ts","sourceRoot":"","sources":["../../../src/validation/request-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAK3B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,wBAAwB,UAAU,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAqB3E"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ValidationError } from './validation-error.js';
|
|
3
|
+
/**
|
|
4
|
+
* Schema for POST /use endpoint
|
|
5
|
+
* Validates the main node.use() request format
|
|
6
|
+
*/
|
|
7
|
+
export const useRequestSchema = z.object({
|
|
8
|
+
address: z.string().min(1, 'address is required'),
|
|
9
|
+
method: z.string().min(1, 'method is required'),
|
|
10
|
+
params: z.any().optional(),
|
|
11
|
+
id: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* Schema for POST /:address/:method endpoint
|
|
15
|
+
* This endpoint accepts any body as params
|
|
16
|
+
*/
|
|
17
|
+
export const convenienceRequestSchema = z.any();
|
|
18
|
+
/**
|
|
19
|
+
* Schema for POST /use/stream endpoint
|
|
20
|
+
* Similar to useRequestSchema but without id
|
|
21
|
+
*/
|
|
22
|
+
export const streamRequestSchema = z.object({
|
|
23
|
+
address: z.string().min(1, 'address is required'),
|
|
24
|
+
method: z.string().min(1, 'method is required'),
|
|
25
|
+
params: z.any().optional(),
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Validates request data against a Zod schema
|
|
29
|
+
*
|
|
30
|
+
* @param data - The data to validate
|
|
31
|
+
* @param schema - The Zod schema to validate against
|
|
32
|
+
* @returns The validated and parsed data
|
|
33
|
+
* @throws {ValidationError} If validation fails
|
|
34
|
+
*/
|
|
35
|
+
export function validateRequest(data, schema) {
|
|
36
|
+
try {
|
|
37
|
+
return schema.parse(data);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error instanceof z.ZodError) {
|
|
41
|
+
// Format Zod errors into a readable message
|
|
42
|
+
const message = error.errors
|
|
43
|
+
.map((e) => {
|
|
44
|
+
const path = e.path.join('.');
|
|
45
|
+
return path ? `${path}: ${e.message}` : e.message;
|
|
46
|
+
})
|
|
47
|
+
.join(', ');
|
|
48
|
+
throw new ValidationError(`Invalid request: ${message}`, 'INVALID_PARAMS');
|
|
49
|
+
}
|
|
50
|
+
// Re-throw non-Zod errors
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { OlaneError } from '../middleware/error-handler.js';
|
|
2
|
+
/**
|
|
3
|
+
* Custom error class for validation failures
|
|
4
|
+
* Extends Error and implements OlaneError interface for consistency
|
|
5
|
+
*/
|
|
6
|
+
export declare class ValidationError extends Error implements OlaneError {
|
|
7
|
+
code: string;
|
|
8
|
+
status: number;
|
|
9
|
+
constructor(message: string, code: string);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=validation-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-error.d.ts","sourceRoot":"","sources":["../../../src/validation/validation-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAE5D;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,KAAM,YAAW,UAAU;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAM1C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error class for validation failures
|
|
3
|
+
* Extends Error and implements OlaneError interface for consistency
|
|
4
|
+
*/
|
|
5
|
+
export class ValidationError extends Error {
|
|
6
|
+
constructor(message, code) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'ValidationError';
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.status = 400; // All validation errors are 400 Bad Request
|
|
11
|
+
}
|
|
12
|
+
}
|
package/dist/test/ai.spec.d.ts
CHANGED
package/dist/test/ai.spec.js
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Disabled: o-server should not depend on o-lane
|
|
3
|
+
// This test was likely copied from another package
|
|
4
|
+
/*
|
|
1
5
|
import { NodeState, oAddress } from '@olane/o-core';
|
|
2
6
|
import { oLaneTool } from '@olane/o-lane';
|
|
3
7
|
import { expect } from 'chai';
|
|
8
|
+
|
|
4
9
|
describe('in-process @memory', () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
});
|
|
11
|
-
await node.start();
|
|
12
|
-
expect(node.state).to.equal(NodeState.RUNNING);
|
|
13
|
-
const transports = node.transports;
|
|
14
|
-
// expect(transports.length).to.equal(1);
|
|
15
|
-
// expect(transports[0].toString()).to.contain('/memory');
|
|
16
|
-
await node.stop();
|
|
17
|
-
expect(node.state).to.equal(NodeState.STOPPED);
|
|
10
|
+
it('should be able to start a single node with no leader', async () => {
|
|
11
|
+
const node = new oLaneTool({
|
|
12
|
+
address: new oAddress('o://test'),
|
|
13
|
+
leader: null,
|
|
14
|
+
parent: null,
|
|
18
15
|
});
|
|
16
|
+
|
|
17
|
+
await node.start();
|
|
18
|
+
expect(node.state).to.equal(NodeState.RUNNING);
|
|
19
|
+
const transports = node.transports;
|
|
20
|
+
// expect(transports.length).to.equal(1);
|
|
21
|
+
// expect(transports[0].toString()).to.contain('/memory');
|
|
22
|
+
await node.stop();
|
|
23
|
+
expect(node.state).to.equal(NodeState.STOPPED);
|
|
24
|
+
});
|
|
19
25
|
});
|
|
26
|
+
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-security.spec.d.ts","sourceRoot":"","sources":["../../test/error-security.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { sanitizeErrorMessage } from '../src/middleware/error-handler.js';
|
|
2
|
+
import { expect } from 'aegir/chai';
|
|
3
|
+
// Test the sanitizeErrorMessage function directly
|
|
4
|
+
// This avoids the complexity of full end-to-end tests with oLaneTool
|
|
5
|
+
describe('Error Sanitization', () => {
|
|
6
|
+
let originalNodeEnv;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
originalNodeEnv = process.env.NODE_ENV;
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
process.env.NODE_ENV = originalNodeEnv;
|
|
12
|
+
});
|
|
13
|
+
describe('Production Mode', () => {
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
process.env.NODE_ENV = 'production';
|
|
16
|
+
});
|
|
17
|
+
it('should use generic message for NODE_NOT_FOUND in production', () => {
|
|
18
|
+
const result = sanitizeErrorMessage('NODE_NOT_FOUND', 'Detailed error: node at o://internal/secret not found');
|
|
19
|
+
expect(result).to.equal('The requested resource was not found');
|
|
20
|
+
expect(result).to.not.contain('internal');
|
|
21
|
+
expect(result).to.not.contain('secret');
|
|
22
|
+
});
|
|
23
|
+
it('should use generic message for TOOL_NOT_FOUND in production', () => {
|
|
24
|
+
const result = sanitizeErrorMessage('TOOL_NOT_FOUND', 'Tool implementation at /var/app/tools/secret-tool.js not found');
|
|
25
|
+
expect(result).to.equal('The requested tool was not found');
|
|
26
|
+
expect(result).to.not.contain('/var/app');
|
|
27
|
+
expect(result).to.not.contain('secret-tool');
|
|
28
|
+
});
|
|
29
|
+
it('should use generic message for INVALID_PARAMS in production', () => {
|
|
30
|
+
const result = sanitizeErrorMessage('INVALID_PARAMS', 'Invalid param: user_id must be UUID, got admin-password-123');
|
|
31
|
+
expect(result).to.equal('Invalid parameters provided');
|
|
32
|
+
expect(result).to.not.contain('admin-password');
|
|
33
|
+
expect(result).to.not.contain('UUID');
|
|
34
|
+
});
|
|
35
|
+
it('should use generic message for TIMEOUT in production', () => {
|
|
36
|
+
const result = sanitizeErrorMessage('TIMEOUT', 'Timeout connecting to database at 192.168.1.100:5432');
|
|
37
|
+
expect(result).to.equal('The request timed out');
|
|
38
|
+
expect(result).to.not.contain('192.168');
|
|
39
|
+
expect(result).to.not.contain('5432');
|
|
40
|
+
});
|
|
41
|
+
it('should use generic message for EXECUTION_ERROR in production', () => {
|
|
42
|
+
const result = sanitizeErrorMessage('EXECUTION_ERROR', 'Failed to execute: API key "sk-secret-123" is invalid');
|
|
43
|
+
expect(result).to.equal('An error occurred while processing your request');
|
|
44
|
+
expect(result).to.not.contain('API key');
|
|
45
|
+
expect(result).to.not.contain('sk-secret');
|
|
46
|
+
});
|
|
47
|
+
it('should use generic message for unknown error codes in production', () => {
|
|
48
|
+
const result = sanitizeErrorMessage('CUSTOM_ERROR', 'Custom error with sensitive data: password=secret123');
|
|
49
|
+
expect(result).to.equal('An internal error occurred');
|
|
50
|
+
expect(result).to.not.contain('password');
|
|
51
|
+
expect(result).to.not.contain('secret');
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe('Development Mode', () => {
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
process.env.NODE_ENV = 'development';
|
|
57
|
+
});
|
|
58
|
+
it('should preserve original message for NODE_NOT_FOUND in development', () => {
|
|
59
|
+
const originalMessage = 'Detailed error: node at o://internal/debug not found';
|
|
60
|
+
const result = sanitizeErrorMessage('NODE_NOT_FOUND', originalMessage);
|
|
61
|
+
expect(result).to.equal(originalMessage);
|
|
62
|
+
expect(result).to.contain('internal');
|
|
63
|
+
expect(result).to.contain('debug');
|
|
64
|
+
});
|
|
65
|
+
it('should preserve original message for TOOL_NOT_FOUND in development', () => {
|
|
66
|
+
const originalMessage = 'Tool implementation at /var/app/tools/test-tool.js not found';
|
|
67
|
+
const result = sanitizeErrorMessage('TOOL_NOT_FOUND', originalMessage);
|
|
68
|
+
expect(result).to.equal(originalMessage);
|
|
69
|
+
expect(result).to.contain('/var/app');
|
|
70
|
+
expect(result).to.contain('test-tool');
|
|
71
|
+
});
|
|
72
|
+
it('should preserve original message for INVALID_PARAMS in development', () => {
|
|
73
|
+
const originalMessage = 'Invalid param: user_id must be UUID, got test-123';
|
|
74
|
+
const result = sanitizeErrorMessage('INVALID_PARAMS', originalMessage);
|
|
75
|
+
expect(result).to.equal(originalMessage);
|
|
76
|
+
expect(result).to.contain('UUID');
|
|
77
|
+
expect(result).to.contain('test-123');
|
|
78
|
+
});
|
|
79
|
+
it('should preserve original message for TIMEOUT in development', () => {
|
|
80
|
+
const originalMessage = 'Timeout connecting to database at localhost:5432';
|
|
81
|
+
const result = sanitizeErrorMessage('TIMEOUT', originalMessage);
|
|
82
|
+
expect(result).to.equal(originalMessage);
|
|
83
|
+
expect(result).to.contain('localhost');
|
|
84
|
+
expect(result).to.contain('5432');
|
|
85
|
+
});
|
|
86
|
+
it('should preserve original message for EXECUTION_ERROR in development', () => {
|
|
87
|
+
const originalMessage = 'Failed to execute: connection pool exhausted';
|
|
88
|
+
const result = sanitizeErrorMessage('EXECUTION_ERROR', originalMessage);
|
|
89
|
+
expect(result).to.equal(originalMessage);
|
|
90
|
+
expect(result).to.contain('connection pool');
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe('Stack Trace Handling', () => {
|
|
94
|
+
it('should verify details are undefined in production mode', () => {
|
|
95
|
+
process.env.NODE_ENV = 'production';
|
|
96
|
+
// Simulate what happens in o-server.ts line 207
|
|
97
|
+
const error = new Error('Test error');
|
|
98
|
+
const stackTrace = error.stack;
|
|
99
|
+
const details = process.env.NODE_ENV === 'development'
|
|
100
|
+
? stackTrace
|
|
101
|
+
: undefined;
|
|
102
|
+
expect(details).to.be.undefined;
|
|
103
|
+
});
|
|
104
|
+
it('should verify details include stack trace in development mode', () => {
|
|
105
|
+
process.env.NODE_ENV = 'development';
|
|
106
|
+
const error = new Error('Test error');
|
|
107
|
+
const stackTrace = error.stack;
|
|
108
|
+
const details = process.env.NODE_ENV === 'development'
|
|
109
|
+
? stackTrace
|
|
110
|
+
: undefined;
|
|
111
|
+
expect(details).to.exist;
|
|
112
|
+
expect(details).to.contain('Error: Test error');
|
|
113
|
+
expect(details).to.contain('at');
|
|
114
|
+
});
|
|
115
|
+
it('should verify error.details takes precedence over error.stack', () => {
|
|
116
|
+
process.env.NODE_ENV = 'development';
|
|
117
|
+
const error = new Error('Test error');
|
|
118
|
+
error.details = 'Custom debug information';
|
|
119
|
+
const details = process.env.NODE_ENV === 'development'
|
|
120
|
+
? (error.details || error.stack)
|
|
121
|
+
: undefined;
|
|
122
|
+
expect(details).to.equal('Custom debug information');
|
|
123
|
+
});
|
|
124
|
+
it('should verify both details and stack are filtered in production', () => {
|
|
125
|
+
process.env.NODE_ENV = 'production';
|
|
126
|
+
const error = new Error('Test error');
|
|
127
|
+
error.details = 'Sensitive information: API_KEY=sk-secret-123';
|
|
128
|
+
const details = process.env.NODE_ENV === 'development'
|
|
129
|
+
? (error.details || error.stack)
|
|
130
|
+
: undefined;
|
|
131
|
+
expect(details).to.be.undefined;
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Validation & Sanitization Tests
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive test suite covering:
|
|
5
|
+
* - Address validation (path traversal, format, control chars)
|
|
6
|
+
* - Method validation (private methods, prototype pollution)
|
|
7
|
+
* - Parameter sanitization (recursive dangerous property removal)
|
|
8
|
+
* - Request schema validation (Zod-based)
|
|
9
|
+
* - Integration tests (SQL injection, NoSQL injection, XSS, prototype pollution)
|
|
10
|
+
*
|
|
11
|
+
* Part of Phase 1 Security - Wave 2 (Input Validation)
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=input-validation.spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-validation.spec.d.ts","sourceRoot":"","sources":["../../test/input-validation.spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|