fix: remediate audited defects (resolves #29, #30, #31, #32)
Build and Push Docker Image / build (push) Successful in 51s
Licence Check / Licence compatibility and copyright header verification (push) Failing after 1m48s
CI / Security audit (push) Successful in 2m27s
CI / Swagger Validation & Coverage (push) Successful in 2m27s
CI / Tests & coverage (push) Successful in 2m39s

- Fix permanent qBittorrent fallback degradation by resetting fallback flags during group-by polling (resolves #29)
- Fix Ombi webhook key mismatch in status endpoint and test mocks (resolves #30)
- Prevent timingSafeEqual TypeErrors on multi-byte CSRF token length mismatches (resolves #31)
- Eliminate duplicate write stream on server.log by delegating to index.js console override (resolves #32)
This commit is contained in:
2026-05-22 16:01:20 +01:00
parent 4aa3590017
commit 548aca6bee
7 changed files with 26 additions and 18 deletions
+2 -2
View File
@@ -72,9 +72,9 @@ const OMBI_WEBHOOK_CONFIG = {
};
const OMBI_WEBHOOK_METRICS = {
eventCount: 10,
eventsReceived: 10,
pollsSkipped: 5,
lastEventTimestamp: 1716326400000
lastWebhookTimestamp: 1716326400000
};
// ---------------------------------------------------------------------------
+2
View File
@@ -219,11 +219,13 @@ describe('DownloadClientRegistry', () => {
});
it('should get downloads grouped by client type', async () => {
const qbClient = testRegistry.getClient('qb1');
const downloadsByType = await testRegistry.getDownloadsByClientType();
expect(downloadsByType.sabnzbd).toHaveLength(1);
expect(downloadsByType.qbittorrent).toHaveLength(1);
expect(downloadsByType.transmission).toBeUndefined();
expect(qbClient.resetFallbackFlag).toHaveBeenCalled();
});
it('should handle client errors gracefully', async () => {
+9
View File
@@ -81,5 +81,14 @@ describe('verifyCsrf middleware', () => {
expect(res.statusCode).toBe(403);
expect(res.body.error).toBe('CSRF token invalid');
});
it('blocks when tokens have same character length but different byte lengths (multi-byte)', () => {
const next = vi.fn();
const res = makeRes();
verifyCsrf(makeReq('POST', 'cafe\u0301', 'cafes'), res, next);
expect(res.statusCode).toBe(403);
expect(res.body.error).toBe('CSRF token invalid');
expect(next).not.toHaveBeenCalled();
});
});
});