javascript-solid-server 0.0.71 → 0.0.73

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.
@@ -220,7 +220,15 @@
220
220
  "WebFetch(domain:webfinger.net)",
221
221
  "Bash(npm update:*)",
222
222
  "Bash(timeout 8 node:*)",
223
- "Bash(gh pr view:*)"
223
+ "Bash(gh pr view:*)",
224
+ "Bash(gh pr diff:*)",
225
+ "Bash(gh pr review:*)",
226
+ "Bash(gh api:*)",
227
+ "Bash(gh pr comment:*)",
228
+ "Bash(git pull:*)",
229
+ "Bash(gh pr:*)",
230
+ "Bash(node --test:*)",
231
+ "Bash(TOKEN_SECRET=test node --test:*)"
224
232
  ]
225
233
  }
226
234
  }
@@ -0,0 +1,382 @@
1
+ # JSS Security Audit Report
2
+
3
+ **Date:** 2026-01-05
4
+ **Auditor:** Automated QE Fleet Analysis
5
+ **Version Audited:** 0.0.71
6
+ **Previous Audit:** 2026-01-03 (v0.0.48)
7
+
8
+ ---
9
+
10
+ ## Executive Summary
11
+
12
+ A comprehensive multi-agent security audit of JavaScriptSolidServer (v0.0.71) was conducted using 5 specialized review agents examining authentication, path traversal, DoS resistance, WAC authorization, and dependency security.
13
+
14
+ **Overall Security Posture:** **GOOD** - Major vulnerabilities from previous audit (v0.0.48-0.0.51) have been fixed. Several medium and low severity issues remain.
15
+
16
+ | Severity | Count | Status |
17
+ |----------|-------|--------|
18
+ | Critical | 0 | - |
19
+ | High | 1 | NEW |
20
+ | Medium | 7 | Open |
21
+ | Low | 8 | Open |
22
+
23
+ **npm audit:** 0 vulnerabilities found
24
+
25
+ ---
26
+
27
+ ## Previous Audit Issues - Remediation Status
28
+
29
+ | Issue | Previous Severity | Status | Fixed In |
30
+ |-------|-------------------|--------|----------|
31
+ | ACL bypass (unauthenticated .acl access) | Critical | FIXED | v0.0.49 |
32
+ | JWT signature not verified | Critical | FIXED | v0.0.49 |
33
+ | SSRF in OIDC discovery | Critical | FIXED | v0.0.50 |
34
+ | SSRF in client document fetch | Critical | FIXED | v0.0.50 |
35
+ | Path traversal via `..` bypass | Critical | FIXED | v0.0.52 |
36
+ | Unauthenticated pod creation | High | FIXED | v0.0.51 |
37
+ | Default token secret | High | FIXED | v0.0.51 |
38
+ | No rate limiting | Medium | FIXED | v0.0.51 |
39
+ | WebSocket subscription spam | High | FIXED | v0.0.52 |
40
+ | JSON.parse DoS | High | PARTIALLY FIXED | v0.0.52 |
41
+
42
+ ---
43
+
44
+ ## New/Open Vulnerabilities
45
+
46
+ ### HIGH SEVERITY
47
+
48
+ #### 1. Path Traversal in Git Handler
49
+
50
+ **Location:** `src/handlers/git.js:82-97`
51
+
52
+ **Description:** The git handler does NOT use the secure `urlToPath()` function. Instead, it extracts the repository path and passes it directly to `path.resolve()` without sanitization.
53
+
54
+ ```javascript
55
+ const urlPath = decodeURIComponent(request.url.split('?')[0]);
56
+ const repoRelative = extractRepoPath(urlPath);
57
+ const repoAbs = resolve(dataRoot, repoRelative); // No traversal check!
58
+ ```
59
+
60
+ **Attack Vector:**
61
+ ```
62
+ GET /../../etc/passwd/info/refs?service=git-upload-pack
63
+ ```
64
+
65
+ **Impact:** Potential directory traversal outside DATA_ROOT when git endpoints are enabled.
66
+
67
+ **Mitigating Factors:**
68
+ - `findGitDir()` validates git-specific files exist, limiting exploitation
69
+ - Git support is optional
70
+
71
+ **CVSS Score:** 7.5 (High)
72
+
73
+ **Recommendation:** Use `urlToPath()` or equivalent sanitization before `path.resolve()`.
74
+
75
+ ---
76
+
77
+ ### MEDIUM SEVERITY
78
+
79
+ #### 2. DPoP Replay Attack Vulnerability
80
+
81
+ **Location:** `src/auth/solid-oidc.js:178-181`
82
+
83
+ ```javascript
84
+ // jti: Unique identifier (we should track these to prevent replay, but skip for now)
85
+ if (!payload.jti) {
86
+ return { thumbprint: null, error: 'DPoP proof missing jti' };
87
+ }
88
+ ```
89
+
90
+ **Description:** DPoP proof `jti` (JWT ID) is required but NOT tracked. The same DPoP proof can be replayed within its 5-minute validity window (`DPOP_MAX_AGE`).
91
+
92
+ **Impact:** Token replay attacks within short window.
93
+
94
+ **CVSS Score:** 5.3 (Medium)
95
+
96
+ **Recommendation:** Implement time-bounded jti cache (5-min TTL).
97
+
98
+ ---
99
+
100
+ #### 3. Agent Group Authorization Not Implemented
101
+
102
+ **Location:** `src/wac/checker.js:182`
103
+
104
+ ```javascript
105
+ // TODO: Check agent groups (requires fetching and parsing group documents)
106
+ ```
107
+
108
+ **Description:** ACL rules using `acl:agentGroup` are parsed (`src/wac/parser.js:152-153`) but never checked during authorization. Group-based access control silently fails.
109
+
110
+ **Impact:** Resources protected by agent groups may be incorrectly denied or allowed.
111
+
112
+ **CVSS Score:** 6.1 (Medium)
113
+
114
+ **Recommendation:** Implement group document fetching and membership checking.
115
+
116
+ ---
117
+
118
+ #### 4. JSON.parse Without Size Limits (Partial)
119
+
120
+ **Locations:**
121
+ - `src/wac/parser.js:40` - ACL content parsing
122
+ - `src/auth/did-nostr.js:129,141` - DID document parsing
123
+ - `src/nostr/relay.js:242` - WebSocket message parsing
124
+ - `src/auth/token.js:105` - Token payload parsing
125
+ - `src/ap/routes/inbox.js:126` - ActivityPub inbox
126
+
127
+ **Description:** `safeJsonParse()` exists (`src/utils/url.js:242-246`) but is not used consistently.
128
+
129
+ **Impact:** DoS via large JSON payloads in unprotected parsers.
130
+
131
+ **CVSS Score:** 5.3 (Medium)
132
+
133
+ **Recommendation:** Use `safeJsonParse()` consistently across all JSON parsing.
134
+
135
+ ---
136
+
137
+ #### 5. Missing Global Security Headers
138
+
139
+ **Description:** Security headers are only applied for mashlib responses, not globally:
140
+
141
+ **Present (mashlib only):**
142
+ - `X-Frame-Options: DENY`
143
+ - `Content-Security-Policy: frame-ancestors 'none'`
144
+
145
+ **Missing globally:**
146
+ - `X-Content-Type-Options: nosniff`
147
+ - `Strict-Transport-Security` (for HTTPS deployments)
148
+ - `Referrer-Policy`
149
+
150
+ **CVSS Score:** 4.3 (Medium)
151
+
152
+ **Recommendation:** Add security headers via Fastify plugin for all responses.
153
+
154
+ ---
155
+
156
+ #### 6. DNS Resolution Failure Allows SSRF
157
+
158
+ **Location:** `src/utils/ssrf.js:125-130`
159
+
160
+ ```javascript
161
+ } catch (err) {
162
+ // DNS resolution failed - could be a legitimate issue or attacker trying to bypass
163
+ // For security, we'll allow it through but log a warning
164
+ console.warn(`DNS resolution failed for ${hostname}: ${err.message}`);
165
+ }
166
+ ```
167
+
168
+ **Description:** When DNS resolution fails, the request is allowed to proceed. An attacker could exploit DNS timing or failure to bypass SSRF protection.
169
+
170
+ **Impact:** Potential SSRF bypass via DNS manipulation.
171
+
172
+ **CVSS Score:** 4.9 (Medium)
173
+
174
+ **Recommendation:** Block requests on DNS resolution failure.
175
+
176
+ ---
177
+
178
+ #### 7. RDF Parsing Without Triple Limits
179
+
180
+ **Locations:** `src/rdf/turtle.js:34`, `src/patch/sparql-update.js:106`
181
+
182
+ **Description:** N3.js parser is used without limits on triple count or recursion depth. Combined with 10MB body limit, a crafted Turtle file could cause CPU exhaustion.
183
+
184
+ **CVSS Score:** 5.3 (Medium)
185
+
186
+ **Recommendation:** Add triple count limit (e.g., 100,000 max).
187
+
188
+ ---
189
+
190
+ #### 8. Verbose Error Messages to Clients
191
+
192
+ **Locations:**
193
+ - `src/handlers/resource.js:501-505` - Turtle parsing errors
194
+ - `src/auth/solid-oidc.js:198` - DPoP proof errors
195
+
196
+ **Description:** Internal error messages from parsing libraries are exposed to clients.
197
+
198
+ **Impact:** Information disclosure about implementation details.
199
+
200
+ **CVSS Score:** 4.3 (Medium)
201
+
202
+ ---
203
+
204
+ ### LOW SEVERITY
205
+
206
+ #### 9. PodName Single-Pass Sanitization
207
+
208
+ **Location:** `src/utils/url.js:69`
209
+
210
+ ```javascript
211
+ let safePodName = podName.replace(/\.\./g, '');
212
+ ```
213
+
214
+ Uses single-pass `..` removal unlike the iterative approach for urlPath. Mitigated by subsequent boundary check.
215
+
216
+ ---
217
+
218
+ #### 10. No Global WebSocket Connection Limit
219
+
220
+ **Location:** `src/notifications/websocket.js`
221
+
222
+ Per-connection subscription limit (100) exists, but no global limit across all connections.
223
+
224
+ ---
225
+
226
+ #### 11. Minimum Username Length
227
+
228
+ **Location:** `src/idp/interactions.js:370-371`
229
+
230
+ Minimum username length is 3 characters, allowing very short usernames.
231
+
232
+ ---
233
+
234
+ #### 12. No Password Strength Validation
235
+
236
+ **Location:** `src/idp/interactions.js`
237
+
238
+ No minimum password length or complexity requirements enforced.
239
+
240
+ ---
241
+
242
+ #### 13. TOKEN_SECRET Entropy Not Validated
243
+
244
+ **Location:** `src/auth/token.js:16-33`
245
+
246
+ Production requires TOKEN_SECRET but doesn't validate minimum entropy/length.
247
+
248
+ ---
249
+
250
+ #### 14. bcrypt Rounds
251
+
252
+ **Location:** `src/idp/accounts.js:41`
253
+
254
+ Uses 10 rounds (acceptable but 12 recommended for future-proofing).
255
+
256
+ ---
257
+
258
+ #### 15. CORS Reflected Origin Pattern
259
+
260
+ **Location:** `src/ldp/headers.js:93-102`
261
+
262
+ Reflects any origin with credentials. Intentional for Solid interoperability but should be documented.
263
+
264
+ ---
265
+
266
+ #### 16. Console.error Information Logging
267
+
268
+ **Locations:** `src/handlers/resource.js:129,203,290`
269
+
270
+ Error messages logged to console may reveal internal details if logs are exposed.
271
+
272
+ ---
273
+
274
+ ## Positive Security Findings
275
+
276
+ | Control | Location | Assessment |
277
+ |---------|----------|------------|
278
+ | Path traversal protection | `src/utils/url.js:24-46` | Multi-pass `..` removal + path.resolve boundary check |
279
+ | JWT signature verification | `src/auth/token.js:125-160` | Proper jose.jwtVerify() against JWKS |
280
+ | HMAC timing-safe comparison | `src/auth/token.js:94-101` | crypto.timingSafeEqual() used |
281
+ | Production token secret enforcement | `src/auth/token.js:21-26` | process.exit(1) if not set |
282
+ | ACL Control permission for .acl files | `src/auth/middleware.js:378-389` | Stricter than spec (more secure) |
283
+ | Default deny on missing ACL | `src/wac/checker.js:30-33` | Restrictive default |
284
+ | Rate limiting | `src/server.js`, `src/idp/index.js` | Comprehensive coverage |
285
+ | SSRF protection | `src/utils/ssrf.js` | Private IP blocking, DNS rebinding protection |
286
+ | WebSocket limits | `src/notifications/websocket.js` | 100 subs/connection, 2048 char URL limit |
287
+ | Dotfile blocking | `src/server.js:235-251` | Allowlist approach |
288
+ | Body size limits | `src/server.js:84` | 10MB global, 1MB for IdP |
289
+ | bcrypt password hashing | `src/idp/accounts.js` | Proper implementation |
290
+ | DPoP proof validation | `src/auth/solid-oidc.js` | Method, URI, timestamp, ath, cnf.jkt checks |
291
+ | Nostr NIP-98 validation | `src/auth/nostr.js` | Event kind, timestamp, URL, method, signature |
292
+ | Slug validation | `src/handlers/container.js:56-69` | Strict alphanumeric + length limit |
293
+
294
+ ---
295
+
296
+ ## Dependency Security
297
+
298
+ **npm audit:** 0 vulnerabilities
299
+
300
+ | Package | Version | Latest | Notes |
301
+ |---------|---------|--------|-------|
302
+ | jose | 6.1.3 | 6.1.3 | Current - JWT/JWKS handling |
303
+ | bcrypt | 6.0.0 | 6.0.0 | Current - Password hashing |
304
+ | oidc-provider | 9.6.0 | 9.6.0 | Current - OIDC IdP |
305
+ | fastify | 4.29.1 | 5.6.2 | Major version behind (v5 available) |
306
+ | better-sqlite3 | 12.5.0 | 12.5.0 | Current |
307
+ | nostr-tools | 2.19.4 | 2.19.4 | Current |
308
+
309
+ **Outdated (non-security):**
310
+ - @fastify/middie: 8.3.3 -> 9.1.0
311
+ - @fastify/rate-limit: 9.1.0 -> 10.3.0
312
+ - @fastify/websocket: 8.3.1 -> 11.2.0
313
+ - fastify: 4.29.1 -> 5.6.2
314
+
315
+ ---
316
+
317
+ ## Recommendations
318
+
319
+ ### Priority 1 (High)
320
+
321
+ 1. **Fix git handler path traversal** - Use `urlToPath()` in `src/handlers/git.js`
322
+
323
+ ### Priority 2 (Medium)
324
+
325
+ 2. **Implement DPoP jti tracking** - Add time-bounded cache for replay prevention
326
+ 3. **Implement agent group checking** - Complete TODO in `src/wac/checker.js`
327
+ 4. **Use safeJsonParse consistently** - Replace raw `JSON.parse()` calls
328
+ 5. **Add global security headers** - X-Content-Type-Options, HSTS
329
+ 6. **Block on DNS failure** - Change SSRF to deny on DNS resolution failure
330
+
331
+ ### Priority 3 (Low)
332
+
333
+ 7. Add RDF triple count limits
334
+ 8. Add password strength requirements
335
+ 9. Validate TOKEN_SECRET entropy
336
+ 10. Add global WebSocket connection limit
337
+ 11. Consider Fastify v5 upgrade path
338
+
339
+ ---
340
+
341
+ ## Changes Since Last Audit (v0.0.51 -> v0.0.71)
342
+
343
+ 20 releases since last audit, including:
344
+
345
+ - **v0.0.52** - Security hardening (path traversal fix)
346
+ - **v0.0.53** - Stricter pod creation rate limit
347
+ - **v0.0.54** - SSRF false positive fix
348
+ - **v0.0.55** - Secure cookie flag for HTTPS
349
+ - **v0.0.56-0.0.58** - Invite-only registration, quotas, did:nostr
350
+ - **v0.0.59-0.0.61** - Nostr relay, ActivityPub federation
351
+ - **v0.0.62-0.0.66** - ActivityPub fixes, Android support
352
+ - **v0.0.67-0.0.71** - UI improvements, error pages, mashlib integration
353
+
354
+ ---
355
+
356
+ ## Legacy Audit Files
357
+
358
+ | File | Status | Action |
359
+ |------|--------|--------|
360
+ | SECURITY-AUDIT-2026-01-03.md | Outdated (v0.0.48) | Retained for history |
361
+ | SECURITY-AUDIT-2026-01-15.md | Invalid (future date) | **REMOVED** |
362
+
363
+ ---
364
+
365
+ ## Conclusion
366
+
367
+ JavaScriptSolidServer v0.0.71 demonstrates strong security fundamentals with all critical vulnerabilities from previous audits remediated. The primary concern is the **HIGH severity path traversal in the git handler** which should be addressed promptly.
368
+
369
+ The codebase shows security-conscious design patterns including:
370
+ - Defense-in-depth path traversal protection
371
+ - Proper cryptographic verification
372
+ - Comprehensive rate limiting
373
+ - SSRF protection with DNS rebinding mitigation
374
+ - Secure defaults (deny on missing ACL)
375
+
376
+ **Overall Assessment:** Suitable for production use after addressing the git handler path traversal issue.
377
+
378
+ ---
379
+
380
+ _Report generated: 2026-01-05_
381
+ _Audit methodology: Multi-agent QE fleet (5 specialized reviewers)_
382
+ _Next audit recommended: 2026-04-05_