observability-toolkit 1.8.0 → 1.8.4
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/README.md +81 -3
- package/dist/backends/index.d.ts +119 -0
- package/dist/backends/index.d.ts.map +1 -1
- package/dist/backends/index.js +57 -0
- package/dist/backends/index.js.map +1 -1
- package/dist/backends/index.test.d.ts +5 -0
- package/dist/backends/index.test.d.ts.map +1 -0
- package/dist/backends/index.test.js +156 -0
- package/dist/backends/index.test.js.map +1 -0
- package/dist/backends/local-jsonl-boolean-search.test.js +8 -27
- package/dist/backends/local-jsonl-boolean-search.test.js.map +1 -1
- package/dist/backends/local-jsonl-logs.test.d.ts +2 -0
- package/dist/backends/local-jsonl-logs.test.d.ts.map +1 -0
- package/dist/backends/local-jsonl-logs.test.js +603 -0
- package/dist/backends/local-jsonl-logs.test.js.map +1 -0
- package/dist/backends/local-jsonl-traces.test.d.ts +2 -0
- package/dist/backends/local-jsonl-traces.test.d.ts.map +1 -0
- package/dist/backends/local-jsonl-traces.test.js +1723 -0
- package/dist/backends/local-jsonl-traces.test.js.map +1 -0
- package/dist/backends/local-jsonl.d.ts +4 -1
- package/dist/backends/local-jsonl.d.ts.map +1 -1
- package/dist/backends/local-jsonl.js +185 -1
- package/dist/backends/local-jsonl.js.map +1 -1
- package/dist/backends/local-jsonl.test.js +723 -46
- package/dist/backends/local-jsonl.test.js.map +1 -1
- package/dist/backends/signoz-api.d.ts +32 -0
- package/dist/backends/signoz-api.d.ts.map +1 -1
- package/dist/backends/signoz-api.js +231 -33
- package/dist/backends/signoz-api.js.map +1 -1
- package/dist/backends/signoz-api.test.js +410 -63
- package/dist/backends/signoz-api.test.js.map +1 -1
- package/dist/lib/constants.d.ts +59 -0
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +252 -6
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/constants.test.js +357 -21
- package/dist/lib/constants.test.js.map +1 -1
- package/dist/lib/edge-cases.test.d.ts +11 -0
- package/dist/lib/edge-cases.test.d.ts.map +1 -0
- package/dist/lib/edge-cases.test.js +634 -0
- package/dist/lib/edge-cases.test.js.map +1 -0
- package/dist/lib/error-sanitizer.d.ts +57 -0
- package/dist/lib/error-sanitizer.d.ts.map +1 -0
- package/dist/lib/error-sanitizer.js +207 -0
- package/dist/lib/error-sanitizer.js.map +1 -0
- package/dist/lib/error-sanitizer.test.d.ts +8 -0
- package/dist/lib/error-sanitizer.test.d.ts.map +1 -0
- package/dist/lib/error-sanitizer.test.js +369 -0
- package/dist/lib/error-sanitizer.test.js.map +1 -0
- package/dist/lib/file-utils.d.ts +134 -0
- package/dist/lib/file-utils.d.ts.map +1 -1
- package/dist/lib/file-utils.js +395 -9
- package/dist/lib/file-utils.js.map +1 -1
- package/dist/lib/file-utils.test.js +444 -3
- package/dist/lib/file-utils.test.js.map +1 -1
- package/dist/lib/indexer.d.ts +9 -1
- package/dist/lib/indexer.d.ts.map +1 -1
- package/dist/lib/indexer.js +51 -2
- package/dist/lib/indexer.js.map +1 -1
- package/dist/lib/indexer.test.js +138 -20
- package/dist/lib/indexer.test.js.map +1 -1
- package/dist/lib/input-validator.d.ts +103 -0
- package/dist/lib/input-validator.d.ts.map +1 -0
- package/dist/lib/input-validator.js +250 -0
- package/dist/lib/input-validator.js.map +1 -0
- package/dist/lib/input-validator.test.d.ts +2 -0
- package/dist/lib/input-validator.test.d.ts.map +1 -0
- package/dist/lib/input-validator.test.js +287 -0
- package/dist/lib/input-validator.test.js.map +1 -0
- package/dist/lib/query-sanitizer.d.ts +143 -0
- package/dist/lib/query-sanitizer.d.ts.map +1 -0
- package/dist/lib/query-sanitizer.js +261 -0
- package/dist/lib/query-sanitizer.js.map +1 -0
- package/dist/lib/query-sanitizer.test.d.ts +5 -0
- package/dist/lib/query-sanitizer.test.d.ts.map +1 -0
- package/dist/lib/query-sanitizer.test.js +400 -0
- package/dist/lib/query-sanitizer.test.js.map +1 -0
- package/dist/lib/server-utils.d.ts +80 -0
- package/dist/lib/server-utils.d.ts.map +1 -0
- package/dist/lib/server-utils.js +141 -0
- package/dist/lib/server-utils.js.map +1 -0
- package/dist/lib/shared-schemas.d.ts +59 -0
- package/dist/lib/shared-schemas.d.ts.map +1 -0
- package/dist/lib/shared-schemas.js +58 -0
- package/dist/lib/shared-schemas.js.map +1 -0
- package/dist/lib/shared-schemas.test.d.ts +5 -0
- package/dist/lib/shared-schemas.test.d.ts.map +1 -0
- package/dist/lib/shared-schemas.test.js +106 -0
- package/dist/lib/shared-schemas.test.js.map +1 -0
- package/dist/lib/toon-encoder.d.ts +21 -0
- package/dist/lib/toon-encoder.d.ts.map +1 -0
- package/dist/lib/toon-encoder.js +46 -0
- package/dist/lib/toon-encoder.js.map +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +155 -81
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +363 -0
- package/dist/server.test.js.map +1 -1
- package/dist/test-helpers/env-utils.d.ts +65 -0
- package/dist/test-helpers/env-utils.d.ts.map +1 -0
- package/dist/test-helpers/env-utils.js +94 -0
- package/dist/test-helpers/env-utils.js.map +1 -0
- package/dist/test-helpers/file-utils.d.ts +93 -0
- package/dist/test-helpers/file-utils.d.ts.map +1 -0
- package/dist/test-helpers/file-utils.js +206 -0
- package/dist/test-helpers/file-utils.js.map +1 -0
- package/dist/test-helpers/index.d.ts +10 -0
- package/dist/test-helpers/index.d.ts.map +1 -0
- package/dist/test-helpers/index.js +28 -0
- package/dist/test-helpers/index.js.map +1 -0
- package/dist/test-helpers/mock-backends.d.ts +139 -0
- package/dist/test-helpers/mock-backends.d.ts.map +1 -0
- package/dist/test-helpers/mock-backends.js +227 -0
- package/dist/test-helpers/mock-backends.js.map +1 -0
- package/dist/test-helpers/mock-backends.test.d.ts +5 -0
- package/dist/test-helpers/mock-backends.test.d.ts.map +1 -0
- package/dist/test-helpers/mock-backends.test.js +368 -0
- package/dist/test-helpers/mock-backends.test.js.map +1 -0
- package/dist/test-helpers/schema-validators.d.ts +32 -0
- package/dist/test-helpers/schema-validators.d.ts.map +1 -0
- package/dist/test-helpers/schema-validators.js +125 -0
- package/dist/test-helpers/schema-validators.js.map +1 -0
- package/dist/test-helpers/test-data-builders.d.ts +223 -0
- package/dist/test-helpers/test-data-builders.d.ts.map +1 -0
- package/dist/test-helpers/test-data-builders.js +288 -0
- package/dist/test-helpers/test-data-builders.js.map +1 -0
- package/dist/test-helpers/test-data-builders.test.d.ts +2 -0
- package/dist/test-helpers/test-data-builders.test.d.ts.map +1 -0
- package/dist/test-helpers/test-data-builders.test.js +306 -0
- package/dist/test-helpers/test-data-builders.test.js.map +1 -0
- package/dist/test-helpers/tool-validators.d.ts +28 -0
- package/dist/test-helpers/tool-validators.d.ts.map +1 -0
- package/dist/test-helpers/tool-validators.js +56 -0
- package/dist/test-helpers/tool-validators.js.map +1 -0
- package/dist/tools/context-stats.d.ts +1 -0
- package/dist/tools/context-stats.d.ts.map +1 -1
- package/dist/tools/context-stats.js +9 -5
- package/dist/tools/context-stats.js.map +1 -1
- package/dist/tools/context-stats.test.js +24 -10
- package/dist/tools/context-stats.test.js.map +1 -1
- package/dist/tools/get-trace-url.js +2 -2
- package/dist/tools/get-trace-url.js.map +1 -1
- package/dist/tools/health-check.js +2 -2
- package/dist/tools/health-check.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/query-evaluations.d.ts +186 -0
- package/dist/tools/query-evaluations.d.ts.map +1 -0
- package/dist/tools/query-evaluations.js +351 -0
- package/dist/tools/query-evaluations.js.map +1 -0
- package/dist/tools/query-evaluations.test.d.ts +5 -0
- package/dist/tools/query-evaluations.test.d.ts.map +1 -0
- package/dist/tools/query-evaluations.test.js +733 -0
- package/dist/tools/query-evaluations.test.js.map +1 -0
- package/dist/tools/query-llm-events.d.ts +24 -18
- package/dist/tools/query-llm-events.d.ts.map +1 -1
- package/dist/tools/query-llm-events.js +103 -60
- package/dist/tools/query-llm-events.js.map +1 -1
- package/dist/tools/query-llm-events.test.js +271 -9
- package/dist/tools/query-llm-events.test.js.map +1 -1
- package/dist/tools/query-logs.d.ts +28 -20
- package/dist/tools/query-logs.d.ts.map +1 -1
- package/dist/tools/query-logs.js +85 -61
- package/dist/tools/query-logs.js.map +1 -1
- package/dist/tools/query-logs.test.js +74 -145
- package/dist/tools/query-logs.test.js.map +1 -1
- package/dist/tools/query-metrics.d.ts +20 -20
- package/dist/tools/query-metrics.d.ts.map +1 -1
- package/dist/tools/query-metrics.js +109 -61
- package/dist/tools/query-metrics.js.map +1 -1
- package/dist/tools/query-metrics.test.js +26 -61
- package/dist/tools/query-metrics.test.js.map +1 -1
- package/dist/tools/query-traces.d.ts +24 -22
- package/dist/tools/query-traces.d.ts.map +1 -1
- package/dist/tools/query-traces.js +95 -70
- package/dist/tools/query-traces.js.map +1 -1
- package/dist/tools/query-traces.test.js +294 -90
- package/dist/tools/query-traces.test.js.map +1 -1
- package/dist/tools/setup-claudeignore.js +7 -7
- package/dist/tools/setup-claudeignore.js.map +1 -1
- package/dist/tools/setup-claudeignore.test.js +4 -25
- package/dist/tools/setup-claudeignore.test.js.map +1 -1
- package/package.json +3 -4
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for error-sanitizer.ts
|
|
3
|
+
*
|
|
4
|
+
* Verifies that error messages are properly sanitized to prevent
|
|
5
|
+
* information disclosure (HIGH severity security issue).
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
8
|
+
import assert from 'node:assert';
|
|
9
|
+
import { sanitizeErrorMessage, sanitizeErrorForResponse, sanitizePath, } from './error-sanitizer.js';
|
|
10
|
+
describe('error-sanitizer', () => {
|
|
11
|
+
describe('sanitizeErrorMessage', () => {
|
|
12
|
+
describe('safe error patterns pass through', () => {
|
|
13
|
+
it('passes through validation errors', () => {
|
|
14
|
+
const message = 'Invalid limit: must be a positive number';
|
|
15
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
16
|
+
});
|
|
17
|
+
it('passes through format errors', () => {
|
|
18
|
+
const message = 'Invalid date format: expected YYYY-MM-DD';
|
|
19
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
20
|
+
});
|
|
21
|
+
it('passes through rate limit errors', () => {
|
|
22
|
+
const message = 'Rate limit exceeded. Please wait.';
|
|
23
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
24
|
+
});
|
|
25
|
+
it('passes through unknown tool errors', () => {
|
|
26
|
+
const message = 'Unknown tool: query-foo';
|
|
27
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
28
|
+
});
|
|
29
|
+
it('passes through backend errors', () => {
|
|
30
|
+
const message = 'No backend available';
|
|
31
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
32
|
+
});
|
|
33
|
+
it('passes through metricName required errors', () => {
|
|
34
|
+
const message = 'metricName is required for SigNoz queries';
|
|
35
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
36
|
+
});
|
|
37
|
+
it('passes through circuit breaker errors', () => {
|
|
38
|
+
const message = 'Circuit breaker open - API unavailable';
|
|
39
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
40
|
+
});
|
|
41
|
+
it('passes through SigNoz config errors', () => {
|
|
42
|
+
const message = 'SigNoz Query URL not configured';
|
|
43
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
44
|
+
});
|
|
45
|
+
it('passes through date range errors', () => {
|
|
46
|
+
const message = 'Date range of 400 days exceeds maximum of 365 days';
|
|
47
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
48
|
+
});
|
|
49
|
+
it('passes through pattern errors', () => {
|
|
50
|
+
const message = 'Pattern length of 300 exceeds maximum of 200';
|
|
51
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
52
|
+
});
|
|
53
|
+
it('passes through startDate errors', () => {
|
|
54
|
+
const message = 'startDate 2024-02-01 cannot be after endDate 2024-01-01';
|
|
55
|
+
assert.strictEqual(sanitizeErrorMessage(message), message);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe('removes Unix file paths', () => {
|
|
59
|
+
it('removes /Users/... paths', () => {
|
|
60
|
+
const message = 'ENOENT: no such file at /Users/john/.claude/config';
|
|
61
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
62
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
63
|
+
assert.ok(sanitized.includes('[path]'));
|
|
64
|
+
});
|
|
65
|
+
it('removes /home/... paths', () => {
|
|
66
|
+
const message = 'Cannot read /home/user/.claude/telemetry/traces.jsonl';
|
|
67
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
68
|
+
assert.ok(!sanitized.includes('/home/user'));
|
|
69
|
+
assert.ok(sanitized.includes('[path]'));
|
|
70
|
+
});
|
|
71
|
+
it('removes /var/... paths', () => {
|
|
72
|
+
const message = 'Permission denied: /var/log/app.log';
|
|
73
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
74
|
+
assert.ok(!sanitized.includes('/var/log'));
|
|
75
|
+
assert.ok(sanitized.includes('[path]'));
|
|
76
|
+
});
|
|
77
|
+
it('removes /opt/... paths', () => {
|
|
78
|
+
const message = 'Module not found at /opt/node/modules/foo';
|
|
79
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
80
|
+
assert.ok(!sanitized.includes('/opt/node'));
|
|
81
|
+
assert.ok(sanitized.includes('[path]'));
|
|
82
|
+
});
|
|
83
|
+
it('removes /tmp/... paths', () => {
|
|
84
|
+
const message = 'Temp file error: /tmp/cache-12345';
|
|
85
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
86
|
+
assert.ok(!sanitized.includes('/tmp/cache'));
|
|
87
|
+
assert.ok(sanitized.includes('[path]'));
|
|
88
|
+
});
|
|
89
|
+
it('removes multiple paths in same message', () => {
|
|
90
|
+
const message = 'Cannot copy /Users/john/src to /home/deploy/app';
|
|
91
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
92
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
93
|
+
assert.ok(!sanitized.includes('/home/deploy'));
|
|
94
|
+
assert.ok(sanitized.includes('[path]'));
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe('removes Windows file paths', () => {
|
|
98
|
+
it('removes C:\\ paths', () => {
|
|
99
|
+
const message = 'ENOENT: no such file at C:\\Users\\john\\.claude\\config';
|
|
100
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
101
|
+
assert.ok(!sanitized.includes('C:\\Users\\john'));
|
|
102
|
+
assert.ok(sanitized.includes('[path]'));
|
|
103
|
+
});
|
|
104
|
+
it('removes D:\\ paths', () => {
|
|
105
|
+
const message = 'Cannot read D:\\Projects\\app\\config.json';
|
|
106
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
107
|
+
assert.ok(!sanitized.includes('D:\\Projects'));
|
|
108
|
+
assert.ok(sanitized.includes('[path]'));
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
describe('removes home directory paths', () => {
|
|
112
|
+
it('removes ~/... paths', () => {
|
|
113
|
+
const message = 'Config not found at ~/.claude/config.json';
|
|
114
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
115
|
+
assert.ok(!sanitized.includes('~/.claude/config'));
|
|
116
|
+
assert.ok(sanitized.includes('[path]'));
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('removes Node.js internal paths', () => {
|
|
120
|
+
it('removes node:internal paths', () => {
|
|
121
|
+
const message = 'Error at node:internal/modules/cjs/loader:1234:56';
|
|
122
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
123
|
+
assert.ok(!sanitized.includes('node:internal'));
|
|
124
|
+
assert.ok(sanitized.includes('[internal]'));
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
describe('handles Error objects', () => {
|
|
128
|
+
it('extracts and sanitizes message from Error', () => {
|
|
129
|
+
const error = new Error('Cannot read /Users/john/.claude/data');
|
|
130
|
+
const sanitized = sanitizeErrorMessage(error);
|
|
131
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
132
|
+
assert.ok(sanitized.includes('[path]'));
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
describe('sanitizeErrorForResponse', () => {
|
|
137
|
+
describe('in non-production mode', () => {
|
|
138
|
+
it('returns Error: prefix with sanitized message', () => {
|
|
139
|
+
const error = new Error('Cannot read /Users/john/.claude/data');
|
|
140
|
+
const sanitized = sanitizeErrorForResponse(error);
|
|
141
|
+
assert.ok(sanitized.startsWith('Error:'));
|
|
142
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
143
|
+
});
|
|
144
|
+
it('handles non-Error values', () => {
|
|
145
|
+
const sanitized = sanitizeErrorForResponse('string error /Users/john');
|
|
146
|
+
assert.ok(sanitized.includes('[path]'));
|
|
147
|
+
});
|
|
148
|
+
it('handles null/undefined gracefully', () => {
|
|
149
|
+
const sanitized = sanitizeErrorForResponse(null);
|
|
150
|
+
assert.strictEqual(typeof sanitized, 'string');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe('in production mode', () => {
|
|
154
|
+
const originalNodeEnv = process.env.NODE_ENV;
|
|
155
|
+
beforeEach(() => {
|
|
156
|
+
process.env.NODE_ENV = 'production';
|
|
157
|
+
});
|
|
158
|
+
afterEach(() => {
|
|
159
|
+
process.env.NODE_ENV = originalNodeEnv;
|
|
160
|
+
});
|
|
161
|
+
it('removes stack traces', () => {
|
|
162
|
+
const error = new Error('Test error');
|
|
163
|
+
error.stack = 'Error: Test error\n at Function.something (/Users/john/app/file.js:123:45)';
|
|
164
|
+
const sanitized = sanitizeErrorForResponse(error, true);
|
|
165
|
+
assert.ok(!sanitized.includes('at Function'));
|
|
166
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
167
|
+
});
|
|
168
|
+
it('returns generic message for suspicious errors', () => {
|
|
169
|
+
const error = new Error('Some error with /suspicious/path/here');
|
|
170
|
+
const sanitized = sanitizeErrorForResponse(error);
|
|
171
|
+
// In production with suspicious paths, returns generic message
|
|
172
|
+
assert.ok(sanitized.includes('Error:'));
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
describe('NODE_ENV defaults to production-safe behavior', () => {
|
|
176
|
+
const originalNodeEnv = process.env.NODE_ENV;
|
|
177
|
+
afterEach(() => {
|
|
178
|
+
if (originalNodeEnv === undefined) {
|
|
179
|
+
delete process.env.NODE_ENV;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
process.env.NODE_ENV = originalNodeEnv;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
it('excludes stack traces when NODE_ENV is not set', () => {
|
|
186
|
+
delete process.env.NODE_ENV;
|
|
187
|
+
const error = new Error('Test error');
|
|
188
|
+
error.stack = 'Error: Test error\n at Function.something (/Users/john/app/file.js:123:45)';
|
|
189
|
+
const sanitized = sanitizeErrorForResponse(error, true);
|
|
190
|
+
// Should NOT include stack trace when NODE_ENV is not set (production-safe default)
|
|
191
|
+
assert.ok(!sanitized.includes('Stack trace:'));
|
|
192
|
+
assert.ok(!sanitized.includes('at Function'));
|
|
193
|
+
});
|
|
194
|
+
it('excludes stack traces when NODE_ENV is empty string', () => {
|
|
195
|
+
process.env.NODE_ENV = '';
|
|
196
|
+
const error = new Error('Test error');
|
|
197
|
+
error.stack = 'Error: Test error\n at Function.something (/Users/john/app/file.js:123:45)';
|
|
198
|
+
const sanitized = sanitizeErrorForResponse(error, true);
|
|
199
|
+
// Empty string should be treated as production-safe
|
|
200
|
+
assert.ok(!sanitized.includes('Stack trace:'));
|
|
201
|
+
assert.ok(!sanitized.includes('at Function'));
|
|
202
|
+
});
|
|
203
|
+
it('excludes stack traces when NODE_ENV is staging', () => {
|
|
204
|
+
process.env.NODE_ENV = 'staging';
|
|
205
|
+
const error = new Error('Test error');
|
|
206
|
+
error.stack = 'Error: Test error\n at Function.something (/Users/john/app/file.js:123:45)';
|
|
207
|
+
const sanitized = sanitizeErrorForResponse(error, true);
|
|
208
|
+
// staging should be treated as production-safe
|
|
209
|
+
assert.ok(!sanitized.includes('Stack trace:'));
|
|
210
|
+
assert.ok(!sanitized.includes('at Function'));
|
|
211
|
+
});
|
|
212
|
+
it('excludes stack traces when NODE_ENV is any unknown value', () => {
|
|
213
|
+
process.env.NODE_ENV = 'docker-container';
|
|
214
|
+
const error = new Error('Test error');
|
|
215
|
+
error.stack = 'Error: Test error\n at Function.something (/Users/john/app/file.js:123:45)';
|
|
216
|
+
const sanitized = sanitizeErrorForResponse(error, true);
|
|
217
|
+
// Unknown values should be treated as production-safe
|
|
218
|
+
assert.ok(!sanitized.includes('Stack trace:'));
|
|
219
|
+
assert.ok(!sanitized.includes('at Function'));
|
|
220
|
+
});
|
|
221
|
+
it('includes sanitized stack traces only in development mode', () => {
|
|
222
|
+
process.env.NODE_ENV = 'development';
|
|
223
|
+
const error = new Error('Test error');
|
|
224
|
+
error.stack = 'Error: Test error\n at Function.something (/Users/john/app/file.js:123:45)';
|
|
225
|
+
const sanitized = sanitizeErrorForResponse(error, true);
|
|
226
|
+
// Should include stack trace in development mode
|
|
227
|
+
assert.ok(sanitized.includes('Stack trace:'));
|
|
228
|
+
// But paths should still be sanitized
|
|
229
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
230
|
+
assert.ok(sanitized.includes('[path]'));
|
|
231
|
+
});
|
|
232
|
+
it('includes sanitized stack traces in test mode', () => {
|
|
233
|
+
process.env.NODE_ENV = 'test';
|
|
234
|
+
const error = new Error('Test error');
|
|
235
|
+
error.stack = 'Error: Test error\n at Function.something (/Users/john/app/file.js:123:45)';
|
|
236
|
+
const sanitized = sanitizeErrorForResponse(error, true);
|
|
237
|
+
// Should include stack trace in test mode
|
|
238
|
+
assert.ok(sanitized.includes('Stack trace:'));
|
|
239
|
+
// But paths should still be sanitized
|
|
240
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
241
|
+
assert.ok(sanitized.includes('[path]'));
|
|
242
|
+
});
|
|
243
|
+
it('respects includeStack=false even in development', () => {
|
|
244
|
+
process.env.NODE_ENV = 'development';
|
|
245
|
+
const error = new Error('Test error');
|
|
246
|
+
error.stack = 'Error: Test error\n at Function.something (/Users/john/app/file.js:123:45)';
|
|
247
|
+
const sanitized = sanitizeErrorForResponse(error, false);
|
|
248
|
+
// Should NOT include stack trace when includeStack is false
|
|
249
|
+
assert.ok(!sanitized.includes('Stack trace:'));
|
|
250
|
+
assert.ok(!sanitized.includes('at Function'));
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
describe('sanitizePath', () => {
|
|
255
|
+
describe('replaces home directory with ~', () => {
|
|
256
|
+
const originalHome = process.env.HOME;
|
|
257
|
+
beforeEach(() => {
|
|
258
|
+
process.env.HOME = '/Users/testuser';
|
|
259
|
+
});
|
|
260
|
+
afterEach(() => {
|
|
261
|
+
process.env.HOME = originalHome;
|
|
262
|
+
});
|
|
263
|
+
it('replaces HOME with ~', () => {
|
|
264
|
+
const path = '/Users/testuser/.claude/telemetry';
|
|
265
|
+
const sanitized = sanitizePath(path);
|
|
266
|
+
assert.strictEqual(sanitized, '~/.claude/telemetry');
|
|
267
|
+
});
|
|
268
|
+
it('handles paths not under HOME', () => {
|
|
269
|
+
const path = '/var/log/app.log';
|
|
270
|
+
const sanitized = sanitizePath(path);
|
|
271
|
+
// Should still work, won't match HOME but might match pattern
|
|
272
|
+
assert.strictEqual(typeof sanitized, 'string');
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
describe('anonymizes user paths', () => {
|
|
276
|
+
it('anonymizes /Users/username paths', () => {
|
|
277
|
+
const originalHome = process.env.HOME;
|
|
278
|
+
process.env.HOME = '/some/other/path';
|
|
279
|
+
try {
|
|
280
|
+
const path = '/Users/johnsmith/.claude/config';
|
|
281
|
+
const sanitized = sanitizePath(path);
|
|
282
|
+
assert.ok(!sanitized.includes('johnsmith'));
|
|
283
|
+
assert.ok(sanitized.includes('~/.claude/config'));
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
process.env.HOME = originalHome;
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
it('anonymizes /home/username paths', () => {
|
|
290
|
+
const originalHome = process.env.HOME;
|
|
291
|
+
process.env.HOME = '/some/other/path';
|
|
292
|
+
try {
|
|
293
|
+
const path = '/home/developer/.config/app';
|
|
294
|
+
const sanitized = sanitizePath(path);
|
|
295
|
+
assert.ok(!sanitized.includes('developer'));
|
|
296
|
+
assert.ok(sanitized.includes('~/.config/app'));
|
|
297
|
+
}
|
|
298
|
+
finally {
|
|
299
|
+
process.env.HOME = originalHome;
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
describe('truncates long paths', () => {
|
|
304
|
+
it('shows last two parts for deep paths', () => {
|
|
305
|
+
const originalHome = process.env.HOME;
|
|
306
|
+
process.env.HOME = '/some/other/path';
|
|
307
|
+
try {
|
|
308
|
+
const path = '/some/long/path/to/deeply/nested/file.txt';
|
|
309
|
+
const sanitized = sanitizePath(path);
|
|
310
|
+
// Should truncate to show context without full path
|
|
311
|
+
assert.ok(sanitized.includes('nested/file.txt') || sanitized.length < path.length);
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
process.env.HOME = originalHome;
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
describe('edge cases', () => {
|
|
320
|
+
it('handles empty string', () => {
|
|
321
|
+
assert.strictEqual(sanitizeErrorMessage(''), '');
|
|
322
|
+
});
|
|
323
|
+
it('handles very long error messages', () => {
|
|
324
|
+
const longMessage = 'Error: ' + '/Users/john/path/'.repeat(100);
|
|
325
|
+
const sanitized = sanitizeErrorMessage(longMessage);
|
|
326
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
327
|
+
assert.ok(sanitized.length < longMessage.length);
|
|
328
|
+
});
|
|
329
|
+
it('does not cause ReDoS with pathological input (security regression)', () => {
|
|
330
|
+
// Regression test for ReDoS vulnerability fix
|
|
331
|
+
// Input length is limited before regex processing
|
|
332
|
+
const start = Date.now();
|
|
333
|
+
// Input that would cause backtracking without length limits
|
|
334
|
+
const maliciousInput = '/Users/' + 'a'.repeat(200000);
|
|
335
|
+
sanitizeErrorMessage(maliciousInput);
|
|
336
|
+
const elapsed = Date.now() - start;
|
|
337
|
+
// Should complete in under 200ms even with very long input
|
|
338
|
+
assert.ok(elapsed < 200, `ReDoS protection failed: took ${elapsed}ms`);
|
|
339
|
+
});
|
|
340
|
+
it('handles long paths without special chars efficiently', () => {
|
|
341
|
+
const start = Date.now();
|
|
342
|
+
// Long path without delimiters
|
|
343
|
+
const longPath = '/home/user/' + 'x'.repeat(5000) + '/file.txt';
|
|
344
|
+
const sanitized = sanitizeErrorMessage(`Error: ${longPath}`);
|
|
345
|
+
const elapsed = Date.now() - start;
|
|
346
|
+
assert.ok(elapsed < 100, `Path sanitization slow: ${elapsed}ms`);
|
|
347
|
+
assert.ok(sanitized.includes('[path]'));
|
|
348
|
+
});
|
|
349
|
+
it('truncates extremely long inputs to prevent DoS', () => {
|
|
350
|
+
const veryLongInput = '/Users/john/' + 'x'.repeat(150000);
|
|
351
|
+
const sanitized = sanitizeErrorMessage(veryLongInput);
|
|
352
|
+
// Should be truncated and include marker
|
|
353
|
+
assert.ok(sanitized.includes('[truncated]'));
|
|
354
|
+
assert.ok(sanitized.length < 110000); // Should be capped
|
|
355
|
+
});
|
|
356
|
+
it('preserves HTTP URLs', () => {
|
|
357
|
+
const message = 'Failed to fetch https://api.example.com/data';
|
|
358
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
359
|
+
assert.ok(sanitized.includes('https://api.example.com/data'));
|
|
360
|
+
});
|
|
361
|
+
it('handles mixed content', () => {
|
|
362
|
+
const message = 'Error reading /Users/john/data while calling https://api.test.com';
|
|
363
|
+
const sanitized = sanitizeErrorMessage(message);
|
|
364
|
+
assert.ok(!sanitized.includes('/Users/john'));
|
|
365
|
+
assert.ok(sanitized.includes('https://api.test.com'));
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
//# sourceMappingURL=error-sanitizer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-sanitizer.test.js","sourceRoot":"","sources":["../../src/lib/error-sanitizer.test.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/file-utils.d.ts
CHANGED
|
@@ -21,6 +21,12 @@ export declare function getDateString(date?: Date): string;
|
|
|
21
21
|
/**
|
|
22
22
|
* Validate that a path is within allowed base directories
|
|
23
23
|
* Prevents path traversal attacks by resolving symlinks and checking containment
|
|
24
|
+
*
|
|
25
|
+
* Security measures:
|
|
26
|
+
* - Uses realpathSync() to resolve symlinks (prevents symlink attacks)
|
|
27
|
+
* - Requires non-empty allowedBasePaths
|
|
28
|
+
* - Uses platform-specific path separator
|
|
29
|
+
* - Logs security failures for audit trail
|
|
24
30
|
*/
|
|
25
31
|
export declare function isPathWithinAllowed(targetPath: string, allowedBasePaths: string[]): boolean;
|
|
26
32
|
/**
|
|
@@ -32,6 +38,8 @@ export declare function isPathWithinAllowed(targetPath: string, allowedBasePaths
|
|
|
32
38
|
export declare function listFiles(dir: string, pattern: RegExp, allowedBasePaths?: string[]): string[];
|
|
33
39
|
/**
|
|
34
40
|
* Parse date from filename like traces-2026-01-28.jsonl
|
|
41
|
+
* Validates date components to prevent path traversal via malicious date strings.
|
|
42
|
+
* Returns null for invalid dates (month > 12, day > 31, unreasonable years).
|
|
35
43
|
*/
|
|
36
44
|
export declare function parseDateFromFilename(filename: string): string | null;
|
|
37
45
|
/**
|
|
@@ -168,4 +176,130 @@ export declare class BatchWriter<T = unknown> {
|
|
|
168
176
|
*/
|
|
169
177
|
get bufferedCount(): number;
|
|
170
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Aggregation types supported by StreamingAggregator
|
|
181
|
+
*/
|
|
182
|
+
export type AggregationType = 'sum' | 'avg' | 'min' | 'max' | 'count' | 'p50' | 'p95' | 'p99';
|
|
183
|
+
/**
|
|
184
|
+
* Streaming aggregator that computes aggregations incrementally without holding all values.
|
|
185
|
+
* Uses reservoir sampling for percentile approximations.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```ts
|
|
189
|
+
* const aggregator = new StreamingAggregator();
|
|
190
|
+
* for (const value of largeDataset) {
|
|
191
|
+
* aggregator.add(value);
|
|
192
|
+
* }
|
|
193
|
+
* const avg = aggregator.getResult('avg');
|
|
194
|
+
* const p95 = aggregator.getResult('p95');
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
export declare class StreamingAggregator {
|
|
198
|
+
private count;
|
|
199
|
+
private sum;
|
|
200
|
+
private min;
|
|
201
|
+
private max;
|
|
202
|
+
private static readonly RESERVOIR_SIZE;
|
|
203
|
+
private reservoir;
|
|
204
|
+
private seenCount;
|
|
205
|
+
/**
|
|
206
|
+
* Add a value to the aggregator
|
|
207
|
+
*/
|
|
208
|
+
add(value: number): void;
|
|
209
|
+
/**
|
|
210
|
+
* Add multiple values at once
|
|
211
|
+
*/
|
|
212
|
+
addAll(values: number[]): void;
|
|
213
|
+
/**
|
|
214
|
+
* Get the result for a specific aggregation type
|
|
215
|
+
*/
|
|
216
|
+
getResult(type: AggregationType): number | undefined;
|
|
217
|
+
/**
|
|
218
|
+
* Get all computed statistics
|
|
219
|
+
*/
|
|
220
|
+
getStats(): {
|
|
221
|
+
count: number;
|
|
222
|
+
sum: number;
|
|
223
|
+
avg: number | undefined;
|
|
224
|
+
min: number | undefined;
|
|
225
|
+
max: number | undefined;
|
|
226
|
+
p50: number | undefined;
|
|
227
|
+
p95: number | undefined;
|
|
228
|
+
p99: number | undefined;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Reset the aggregator to initial state
|
|
232
|
+
*/
|
|
233
|
+
reset(): void;
|
|
234
|
+
/**
|
|
235
|
+
* Get the current count of values added
|
|
236
|
+
*/
|
|
237
|
+
getCount(): number;
|
|
238
|
+
/**
|
|
239
|
+
* Calculate percentile using R-7 linear interpolation on the reservoir sample
|
|
240
|
+
*/
|
|
241
|
+
private getPercentile;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Result from enforceMemoryLimit when truncation occurs
|
|
245
|
+
*/
|
|
246
|
+
export interface MemoryLimitResult<T> {
|
|
247
|
+
/** The (possibly truncated) results */
|
|
248
|
+
results: T[];
|
|
249
|
+
/** Whether results were truncated */
|
|
250
|
+
truncated: boolean;
|
|
251
|
+
/** Original count before truncation */
|
|
252
|
+
originalCount: number;
|
|
253
|
+
/** Reason for truncation if truncated */
|
|
254
|
+
truncationReason?: 'count' | 'size';
|
|
255
|
+
}
|
|
256
|
+
export declare const CONSERVATIVE_FALLBACK_SIZE = 1000000;
|
|
257
|
+
/**
|
|
258
|
+
* Check if a value contains circular references using a WeakSet
|
|
259
|
+
* @param obj - The object to check
|
|
260
|
+
* @param seen - WeakSet to track seen objects
|
|
261
|
+
* @returns true if circular reference detected
|
|
262
|
+
*/
|
|
263
|
+
export declare function hasCircularReference(obj: unknown, seen?: WeakSet<object>): boolean;
|
|
264
|
+
/**
|
|
265
|
+
* Estimate approximate byte size of an object (rough approximation)
|
|
266
|
+
* Uses a sample-based approach for large arrays to avoid performance issues
|
|
267
|
+
*
|
|
268
|
+
* Security: Returns a conservative estimate (1MB) when serialization fails
|
|
269
|
+
* to prevent memory limit bypass via circular references or other edge cases.
|
|
270
|
+
*/
|
|
271
|
+
export declare function estimateByteSize<T>(results: T[], sampleSize?: number): number;
|
|
272
|
+
/**
|
|
273
|
+
* Enforce memory limit on results array.
|
|
274
|
+
* Truncates results if they exceed count limit OR estimated byte size limit.
|
|
275
|
+
* Uses sampling for large arrays to avoid performance overhead.
|
|
276
|
+
*
|
|
277
|
+
* @param results - Array of results to limit
|
|
278
|
+
* @param limit - Maximum number of results (defaults to MAX_RESULTS_IN_MEMORY)
|
|
279
|
+
* @returns Object with results, truncated flag, and original count
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```ts
|
|
283
|
+
* const { results, truncated } = enforceMemoryLimit(largeArray);
|
|
284
|
+
* if (truncated) {
|
|
285
|
+
* console.warn('Results were truncated');
|
|
286
|
+
* }
|
|
287
|
+
* ```
|
|
288
|
+
*/
|
|
289
|
+
export declare function enforceMemoryLimit<T>(results: T[], limit?: number): MemoryLimitResult<T>;
|
|
290
|
+
/**
|
|
291
|
+
* Check if streaming aggregation should be used based on result count
|
|
292
|
+
*
|
|
293
|
+
* @param count - Number of results
|
|
294
|
+
* @param threshold - Threshold to trigger streaming (defaults to STREAMING_THRESHOLD)
|
|
295
|
+
* @returns true if streaming aggregation should be used
|
|
296
|
+
*/
|
|
297
|
+
export declare function shouldUseStreamingAggregation(count: number, threshold?: number): boolean;
|
|
298
|
+
/**
|
|
299
|
+
* Get current memory limit constants (useful for testing)
|
|
300
|
+
*/
|
|
301
|
+
export declare function getMemoryLimits(): {
|
|
302
|
+
maxResults: number;
|
|
303
|
+
streamingThreshold: number;
|
|
304
|
+
};
|
|
171
305
|
//# sourceMappingURL=file-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/lib/file-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/lib/file-utils.ts"],"names":[],"mappings":"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"}
|