Backend/frontend hardening & consistency cleanups (#1113)

* refactor(auth): session token validation and password-change consistency

* refactor(journey): entry field allow-list and public share-link consistency

* refactor(mcp): align tool authorization with the REST permission checks

* chore: input validation and sanitisation touch-ups (uploads, pdf, maps, backup, csp)
This commit is contained in:
Maurice
2026-06-06 16:37:03 +02:00
committed by GitHub
parent 070ef01328
commit 093e069ccc
41 changed files with 653 additions and 74 deletions
@@ -596,6 +596,32 @@ describe('updateEntry', () => {
expect(result).toBeNull();
});
it('JOURNEY-SVC-034b: ignores injection column keys and mass-assignment attempts', () => {
const { user } = createUser(testDb);
const journey = createJourney(testDb, user.id);
const entry = createJourneyEntry(testDb, journey.id, user.id, {
title: 'Safe',
story: 'original',
entry_date: '2026-03-01',
});
// The keys come straight from the request body. A crafted key was previously
// interpolated as a raw SQL column name (`${key} = ?`), enabling subquery
// injection (full DB read) and mass-assignment of protected columns.
const malicious: Record<string, unknown> = {
title: 'Updated',
[`story = (SELECT password_hash FROM users WHERE id = ${user.id}), updated_at`]: 'x',
author_id: 999999,
};
const updated = updateEntry(entry.id, user.id, malicious as Parameters<typeof updateEntry>[2]);
expect(updated).not.toBeNull();
expect(updated!.title).toBe('Updated'); // legit field still applied
expect(updated!.story).toBe('original'); // injection key dropped — no hash leaked into story
expect(updated!.author_id).toBe(user.id); // mass-assignment blocked
});
});
describe('deleteEntry', () => {