Fix five P0/P1 security & correctness findings from the full-eval
- Arbitrary file write (P0): validate import keys in /api/library/import via a now-exported safeFilename(); a ../../ key is skipped, not written out of the scope dir. - SSRF (P0): guard downloadPodcastAudio — reject non-HTTP(S) schemes, block IP-literal and DNS-resolved private/link-local/loopback/reserved/multicast and embedded-IPv4 IPv6 targets (closes DNS rebinding), cap + resolve redirects. - ESM require (P1): top-level import of randomBytes in license-purchase.js (the inner require threw on the anon purchase-settle path). - Concurrency lock (P1): skip the process-global free-tier slot in multi-mode so it no longer serializes every cloud tenant onto one job. - X-Forwarded-For bypass (P1): set Express trust proxy from RECAP_TRUSTED_PROXY_HOPS (default 1); getClientIp now reads req.ip instead of a client-spoofable XFF entry. Tests added for safeFilename, the SSRF guard, and getClientIp (119 pass). Registry blockers deferred (ROADMAP); leaked-key history purge queued.
This commit is contained in:
@@ -138,3 +138,24 @@ describe("loadMeta + saveMeta", () => {
|
||||
assert.deepEqual(loaded.uncategorized, []);
|
||||
});
|
||||
});
|
||||
|
||||
describe("safeFilename", () => {
|
||||
// Exported so callers writing user content to disk (e.g. library import)
|
||||
// can share the one guard instead of rolling their own.
|
||||
test("returns valid ids unchanged", () => {
|
||||
for (const id of ["abc123", "a_b-c", "VIDEOid123", "0"]) {
|
||||
assert.equal(history.safeFilename(id), id);
|
||||
}
|
||||
});
|
||||
|
||||
test("rejects traversal, separators, and other unsafe chars", () => {
|
||||
for (const bad of ["../../evil", "..", "a/b", "a\\b", "a.json", "foo bar", "", "a:b"]) {
|
||||
assert.throws(() => history.safeFilename(bad), /invalid_session_id/);
|
||||
}
|
||||
});
|
||||
|
||||
test("rejects non-strings", () => {
|
||||
assert.throws(() => history.safeFilename(123), /invalid_session_id/);
|
||||
assert.throws(() => history.safeFilename(null), /invalid_session_id/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user