javascript-solid-server 0.0.71 → 0.0.72

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.
@@ -1,514 +0,0 @@
1
- # JSS Deep Security Audit Report
2
-
3
- **Date:** 2026-01-15
4
- **Auditor:** Comprehensive Security Review
5
- **Version Audited:** 0.0.51
6
- **Previous Audit:** 2026-01-03 (v0.0.48)
7
-
8
- ---
9
-
10
- ## Executive Summary
11
-
12
- A comprehensive security audit of JavaScriptSolidServer (v0.0.51) revealed **1 critical**, **3 high**, **5 medium**, and **4 low** severity vulnerabilities. While previous critical issues (ACL bypass, JWT signature verification, SSRF) have been fixed, new vulnerabilities were discovered in path traversal protection, input validation, and denial-of-service resistance.
13
-
14
- **Overall Security Posture:** 🟡 **Moderate Risk** - Critical path traversal vulnerability requires immediate attention.
15
-
16
- ---
17
-
18
- ## Critical Vulnerabilities
19
-
20
- ### 1. Path Traversal Vulnerability in `urlToPath` (CRITICAL) ⚠️
21
-
22
- **Location:** `src/utils/url.js:23-32`
23
-
24
- **Description:** The path traversal protection in `urlToPath()` and `urlToPathWithPod()` is insufficient and can be bypassed using multiple techniques.
25
-
26
- **Vulnerable Code:**
27
-
28
- ```javascript
29
- export function urlToPath(urlPath) {
30
- let normalized = urlPath.startsWith('/') ? urlPath.slice(1) : urlPath
31
- normalized = decodeURIComponent(normalized)
32
-
33
- // Security: prevent path traversal
34
- normalized = normalized.replace(/\.\./g, '') // ❌ INSUFFICIENT
35
-
36
- return path.join(getDataRoot(), normalized)
37
- }
38
- ```
39
-
40
- **Attack Vectors:**
41
-
42
- 1. **Double-dot bypass:** `....//` → after replacement becomes `../`
43
- 2. **URL encoding bypass:** `%2e%2e%2f` → decodes to `../` after replacement
44
- 3. **Mixed encoding:** `%2e.` → decodes to `..` after replacement
45
- 4. **Path separator injection:** `path.join()` doesn't prevent traversal if normalized still contains `/` or `\`
46
-
47
- **Proof of Concept:**
48
-
49
- ```bash
50
- # Bypass 1: Double-dot
51
- GET /alice/....//etc/passwd
52
-
53
- # Bypass 2: URL encoding
54
- GET /alice/%2e%2e%2f%2e%2e%2fetc%2fpasswd
55
-
56
- # Bypass 3: Mixed
57
- GET /alice/%2e./%2e./etc/passwd
58
-
59
- # Bypass 4: Windows path separator
60
- GET /alice/..\..\etc\passwd
61
- ```
62
-
63
- **Impact:**
64
-
65
- - Read arbitrary files outside DATA_ROOT
66
- - Write arbitrary files (if write permission exists)
67
- - Access other pods' data in multi-user mode
68
- - Potential remote code execution if sensitive config files are overwritten
69
-
70
- **CVSS Score:** 9.1 (Critical)
71
-
72
- **Fix Required:**
73
-
74
- ```javascript
75
- export function urlToPath(urlPath) {
76
- let normalized = urlPath.startsWith('/') ? urlPath.slice(1) : urlPath
77
- normalized = decodeURIComponent(normalized)
78
-
79
- // Remove all path traversal attempts (multiple passes)
80
- normalized = normalized.replace(/\.\./g, '')
81
- normalized = normalized.replace(/\.\./g, '') // Second pass for ....//
82
-
83
- // Resolve to absolute path and check it's within DATA_ROOT
84
- const resolved = path.resolve(getDataRoot(), normalized)
85
- const dataRoot = path.resolve(getDataRoot())
86
-
87
- if (!resolved.startsWith(dataRoot + path.sep) && resolved !== dataRoot) {
88
- throw new Error('Path traversal detected')
89
- }
90
-
91
- return resolved
92
- }
93
- ```
94
-
95
- ---
96
-
97
- ## High Severity Vulnerabilities
98
-
99
- ### 2. JSON.parse DoS via Malicious Input (HIGH)
100
-
101
- **Location:** Multiple files (17 instances found)
102
-
103
- **Description:** `JSON.parse()` is called on user-controlled input without size limits or try-catch in several locations, allowing denial-of-service attacks via:
104
-
105
- - Deeply nested JSON structures
106
- - Large JSON payloads
107
- - Malformed JSON causing parser hangs
108
-
109
- **Vulnerable Locations:**
110
-
111
- - `src/handlers/resource.js:89, 271, 294, 653, 670` - HTML data island extraction
112
- - `src/auth/nostr.js:87` - Nostr event decoding
113
- - `src/idp/interactions.js:62, 75, 321` - Form body parsing
114
- - `src/rdf/conneg.js:140` - Content negotiation
115
- - `src/wac/parser.js:40` - ACL parsing
116
-
117
- **Impact:**
118
-
119
- - Server resource exhaustion (CPU, memory)
120
- - Request timeouts
121
- - Potential service unavailability
122
-
123
- **CVSS Score:** 7.5 (High)
124
-
125
- **Fix Required:** Add size limits and proper error handling:
126
-
127
- ```javascript
128
- // Example fix for resource.js
129
- try {
130
- const maxSize = 10 * 1024 * 1024 // 10MB limit
131
- if (jsonLdMatch[1].length > maxSize) {
132
- throw new Error('JSON-LD data island too large')
133
- }
134
- const jsonLd = JSON.parse(jsonLdMatch[1])
135
- } catch (e) {
136
- if (e instanceof SyntaxError) {
137
- return reply.code(400).send({ error: 'Invalid JSON-LD' })
138
- }
139
- throw e
140
- }
141
- ```
142
-
143
- ---
144
-
145
- ### 3. SPARQL Update Injection Risk (HIGH)
146
-
147
- **Location:** `src/patch/sparql-update.js:22-85`
148
-
149
- **Description:** The SPARQL Update parser uses regex-based parsing with fallback to simple pattern matching. This can be exploited to:
150
-
151
- - Inject malicious SPARQL constructs
152
- - Bypass intended DELETE/INSERT operations
153
- - Cause parser errors leading to information disclosure
154
-
155
- **Vulnerable Code:**
156
-
157
- ```javascript
158
- // Regex-based parsing without proper validation
159
- const insertDataMatch = query.match(/INSERT\s+DATA\s*\{([^}]+)\}/is)
160
- const deleteDataMatch = query.match(/DELETE\s+DATA\s*\{([^}]+)\}/is)
161
- ```
162
-
163
- **Attack Vector:**
164
-
165
- ```sparql
166
- INSERT DATA {
167
- <#malicious> <predicate> "value" .
168
- } INSERT DATA {
169
- <#legitimate> <predicate> "value" .
170
- }
171
- ```
172
-
173
- **Impact:**
174
-
175
- - Unauthorized data modification
176
- - Data corruption
177
- - ACL bypass through unexpected triple insertions
178
-
179
- **CVSS Score:** 8.1 (High)
180
-
181
- **Fix Required:** Use proper SPARQL parser library or implement strict validation.
182
-
183
- ---
184
-
185
- ### 4. WebSocket DoS via Subscription Spam (HIGH)
186
-
187
- **Location:** `src/notifications/websocket.js:34-53`
188
-
189
- **Description:** WebSocket connections can subscribe to unlimited URLs without rate limiting, allowing:
190
-
191
- - Memory exhaustion via subscription spam
192
- - CPU exhaustion via broadcast storms
193
- - Resource exhaustion attacks
194
-
195
- **Vulnerable Code:**
196
-
197
- ```javascript
198
- socket.on('message', message => {
199
- const msg = message.toString().trim()
200
- if (msg.startsWith('sub ')) {
201
- const url = msg.slice(4).trim()
202
- if (url) {
203
- subscribe(socket, url) // ❌ No limits
204
- socket.send(`ack ${url}`)
205
- }
206
- }
207
- })
208
- ```
209
-
210
- **Impact:**
211
-
212
- - Server memory exhaustion
213
- - CPU exhaustion during broadcasts
214
- - Service unavailability
215
-
216
- **CVSS Score:** 7.5 (High)
217
-
218
- **Fix Required:** Implement per-connection subscription limits:
219
-
220
- ```javascript
221
- const MAX_SUBSCRIPTIONS_PER_CONNECTION = 100
222
- const socketSubs = subscriptions.get(socket)
223
- if (socketSubs && socketSubs.size >= MAX_SUBSCRIPTIONS_PER_CONNECTION) {
224
- socket.send('error: Subscription limit exceeded')
225
- return
226
- }
227
- ```
228
-
229
- ---
230
-
231
- ## Medium Severity Vulnerabilities
232
-
233
- ### 5. Insufficient Rate Limiting Coverage (MEDIUM)
234
-
235
- **Location:** `src/server.js:131-143`
236
-
237
- **Description:** Rate limiting is configured but not applied to all sensitive endpoints:
238
-
239
- - PATCH operations (can be expensive)
240
- - DELETE operations (destructive)
241
- - WebSocket connections (no rate limit)
242
- - OIDC token endpoint (credential stuffing)
243
-
244
- **Impact:**
245
-
246
- - Brute force attacks on authentication
247
- - Resource exhaustion via rapid requests
248
- - DoS via expensive operations
249
-
250
- **CVSS Score:** 5.3 (Medium)
251
-
252
- **Fix Required:** Apply rate limiting to all write operations and authentication endpoints.
253
-
254
- ---
255
-
256
- ### 6. Information Disclosure via Error Messages (MEDIUM)
257
-
258
- **Location:** Multiple handlers
259
-
260
- **Description:** Error messages may reveal:
261
-
262
- - Internal file paths
263
- - Stack traces in development mode
264
- - Database structure hints
265
- - System architecture details
266
-
267
- **Examples:**
268
-
269
- - `src/handlers/resource.js:502` - Turtle parsing errors expose internal paths
270
- - `src/patch/sparql-update.js:696` - SPARQL errors reveal query structure
271
-
272
- **Impact:**
273
-
274
- - Information useful for further attacks
275
- - System fingerprinting
276
- - Path enumeration
277
-
278
- **CVSS Score:** 4.3 (Medium)
279
-
280
- **Fix Required:** Sanitize error messages in production:
281
-
282
- ```javascript
283
- if (process.env.NODE_ENV === 'production') {
284
- return reply.code(400).send({ error: 'Invalid request' })
285
- } else {
286
- return reply
287
- .code(400)
288
- .send({ error: 'Invalid request', details: err.message })
289
- }
290
- ```
291
-
292
- ---
293
-
294
- ### 7. Missing Input Validation on Slug Header (MEDIUM)
295
-
296
- **Location:** `src/handlers/container.js:55, 62`
297
-
298
- **Description:** The `Slug` header in POST requests is sanitized but not fully validated:
299
-
300
- - No length limit
301
- - No character set validation beyond path traversal
302
- - Can create files with problematic names
303
-
304
- **Vulnerable Code:**
305
-
306
- ```javascript
307
- const slug = request.headers.slug
308
- const filename = await storage.generateUniqueFilename(
309
- storagePath,
310
- slug,
311
- isCreatingContainer
312
- )
313
- ```
314
-
315
- **Impact:**
316
-
317
- - Filesystem issues with special characters
318
- - Potential path confusion attacks
319
- - Unicode normalization issues
320
-
321
- **CVSS Score:** 4.9 (Medium)
322
-
323
- **Fix Required:** Add strict validation:
324
-
325
- ```javascript
326
- if (slug && slug.length > 255) {
327
- return reply.code(400).send({ error: 'Slug too long' })
328
- }
329
- if (slug && !/^[a-zA-Z0-9._-]+$/.test(slug)) {
330
- return reply.code(400).send({ error: 'Invalid slug format' })
331
- }
332
- ```
333
-
334
- ---
335
-
336
- ### 8. RDF Parsing DoS via Billion Laughs Attack (MEDIUM)
337
-
338
- **Location:** `src/rdf/turtle.js:32-56`, `src/rdf/conneg.js`
339
-
340
- **Description:** Turtle/N3 parsing doesn't limit:
341
-
342
- - Quad count
343
- - Prefix expansion depth
344
- - Recursive entity references
345
-
346
- **Impact:**
347
-
348
- - Memory exhaustion via large RDF documents
349
- - CPU exhaustion via complex parsing
350
- - Service unavailability
351
-
352
- **CVSS Score:** 5.3 (Medium)
353
-
354
- **Fix Required:** Add parsing limits:
355
-
356
- ```javascript
357
- const MAX_QUADS = 100000
358
- const MAX_PREFIXES = 1000
359
- // Enforce limits during parsing
360
- ```
361
-
362
- ---
363
-
364
- ### 9. Missing CSRF Protection on State-Changing Operations (MEDIUM)
365
-
366
- **Location:** All PUT/PATCH/DELETE handlers
367
-
368
- **Description:** No CSRF tokens or SameSite cookie protection for state-changing operations. While Solid-OIDC DPoP tokens provide some protection, simple Bearer tokens are vulnerable.
369
-
370
- **Impact:**
371
-
372
- - Cross-site request forgery
373
- - Unauthorized data modification
374
- - Account takeover (if combined with XSS)
375
-
376
- **CVSS Score:** 6.1 (Medium)
377
-
378
- **Fix Required:** Implement CSRF protection for non-DPoP tokens or require SameSite cookies.
379
-
380
- ---
381
-
382
- ## Low Severity Vulnerabilities
383
-
384
- ### 10. Weak Path Traversal Protection in `generateUniqueFilename` (LOW)
385
-
386
- **Location:** `src/storage/filesystem.js:132-150`
387
-
388
- **Description:** Only removes `/` and `\` but doesn't validate the final path is within bounds.
389
-
390
- **Impact:** Limited - only affects POST slug generation, not direct path access.
391
-
392
- **CVSS Score:** 3.1 (Low)
393
-
394
- ---
395
-
396
- ### 11. Missing Content-Length Validation (LOW)
397
-
398
- **Location:** Request body handlers
399
-
400
- **Description:** `bodyLimit` is set to 10MB but no per-request validation of Content-Length header.
401
-
402
- **Impact:** Potential for request smuggling or resource exhaustion.
403
-
404
- **CVSS Score:** 3.5 (Low)
405
-
406
- ---
407
-
408
- ### 12. Insufficient Logging of Security Events (LOW)
409
-
410
- **Location:** Authentication and authorization handlers
411
-
412
- **Description:** Failed authentication attempts are logged but not rate-limited or blocked after repeated failures.
413
-
414
- **Impact:** Difficulty detecting brute force attacks.
415
-
416
- **CVSS Score:** 2.5 (Low)
417
-
418
- ---
419
-
420
- ### 13. CORS Headers Allow All Origins (LOW)
421
-
422
- **Location:** `src/ldp/headers.js`
423
-
424
- **Description:** CORS headers allow requests from any origin (`*`). While necessary for Solid interoperability, this increases XSS risk.
425
-
426
- **Impact:** Increased XSS attack surface.
427
-
428
- **CVSS Score:** 3.1 (Low)
429
-
430
- **Note:** This may be intentional for Solid protocol compliance.
431
-
432
- ---
433
-
434
- ## Positive Security Findings
435
-
436
- ✅ **Fixed Issues from Previous Audit:**
437
-
438
- - ACL bypass (v0.0.49) - Now requires Control permission
439
- - JWT signature verification (v0.0.49) - Properly verifies against JWKS
440
- - SSRF protection (v0.0.50) - URL validation implemented
441
- - Pod creation abuse (v0.0.51) - Rate limited
442
- - Default token secret (v0.0.51) - Fails in production if not set
443
- - Rate limiting (v0.0.51) - Basic rate limiting added
444
-
445
- ✅ **Good Security Practices:**
446
-
447
- - Constant-time comparison for HMAC verification
448
- - Proper bcrypt usage for password hashing
449
- - DPoP proof validation with timestamp checks
450
- - SSRF protection with DNS rebinding prevention
451
- - Path traversal attempt in `generateUniqueFilename`
452
- - WAC authorization properly implemented
453
- - No `eval()` or `Function()` usage found
454
-
455
- ---
456
-
457
- ## Recommendations
458
-
459
- ### Immediate Actions (Critical/High)
460
-
461
- 1. **Fix path traversal vulnerability** - Implement proper path resolution and validation
462
- 2. **Add JSON.parse size limits** - Prevent DoS via malicious JSON
463
- 3. **Harden SPARQL parser** - Use proper parser or strict validation
464
- 4. **Limit WebSocket subscriptions** - Prevent memory exhaustion
465
-
466
- ### Short-term Actions (Medium)
467
-
468
- 5. **Expand rate limiting** - Cover all write operations and auth endpoints
469
- 6. **Sanitize error messages** - Remove internal details in production
470
- 7. **Validate Slug header** - Add length and character restrictions
471
- 8. **Add RDF parsing limits** - Prevent Billion Laughs attacks
472
-
473
- ### Long-term Actions (Low)
474
-
475
- 9. **Implement CSRF protection** - For non-DPoP authentication
476
- 10. **Enhanced security logging** - Track and alert on suspicious patterns
477
- 11. **Security headers** - Add HSTS, CSP, X-Frame-Options where appropriate
478
- 12. **Regular security audits** - Schedule quarterly reviews
479
-
480
- ---
481
-
482
- ## Testing Recommendations
483
-
484
- 1. **Fuzz testing** - Path traversal, JSON parsing, SPARQL parsing
485
- 2. **Load testing** - WebSocket subscriptions, concurrent requests
486
- 3. **Penetration testing** - Full security assessment
487
- 4. **Dependency scanning** - Check for vulnerable npm packages
488
-
489
- ---
490
-
491
- ## Remediation Priority
492
-
493
- | Priority | Issue | Severity | Effort | Target Version |
494
- | -------- | ------------------ | -------- | ------ | -------------- |
495
- | P0 | Path traversal | Critical | Medium | v0.0.52 |
496
- | P1 | JSON.parse DoS | High | Low | v0.0.52 |
497
- | P1 | WebSocket DoS | High | Low | v0.0.52 |
498
- | P2 | SPARQL injection | High | High | v0.0.53 |
499
- | P2 | Rate limiting gaps | Medium | Medium | v0.0.53 |
500
- | P3 | Error disclosure | Medium | Low | v0.0.54 |
501
- | P3 | Input validation | Medium | Low | v0.0.54 |
502
-
503
- ---
504
-
505
- ## Conclusion
506
-
507
- While significant security improvements have been made since the previous audit, the path traversal vulnerability requires immediate attention. The codebase shows good security awareness with proper authentication, authorization, and SSRF protection. However, input validation and DoS resistance need strengthening.
508
-
509
- **Overall Assessment:** The server is suitable for production use after fixing the critical path traversal issue and implementing the high-priority recommendations.
510
-
511
- ---
512
-
513
- _Report generated: 2026-01-15_
514
- _Next audit recommended: 2026-04-15_