Harden auth, payments, and frontend against review findings.
Close exploitable gaps in booking/payment flows, enforce token versioning and account checks, gate sensitive payment data, and add middleware plus input validation across admin routes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -162,6 +162,13 @@ legalPagesRouter.get('/', async (c) => {
|
||||
legalPagesRouter.get('/:slug', async (c) => {
|
||||
const { slug } = c.req.param();
|
||||
const locale = c.req.query('locale') || 'en';
|
||||
|
||||
// Reject anything that isn't a simple slug. The filesystem fallback below builds a
|
||||
// path from this value, so an unconstrained slug (e.g. "../../etc/passwd") would
|
||||
// allow path traversal / arbitrary file reads.
|
||||
if (!/^[a-z0-9-]+$/.test(slug)) {
|
||||
return c.json({ error: 'Legal page not found' }, 404);
|
||||
}
|
||||
|
||||
// First try to get from database
|
||||
const page = await dbGet<any>(
|
||||
@@ -275,6 +282,17 @@ legalPagesRouter.put('/admin/:slug', requireAuth(['admin']), async (c) => {
|
||||
if (!enContent && !esContent) {
|
||||
return c.json({ error: 'At least one language content is required' }, 400);
|
||||
}
|
||||
|
||||
// Bound the sizes of admin-supplied content to avoid unbounded payloads.
|
||||
const MAX_CONTENT_LEN = 200000; // ~200 KB of markdown per language
|
||||
const MAX_TITLE_LEN = 255;
|
||||
const tooLong = (v: any, max: number) => typeof v === 'string' && v.length > max;
|
||||
if (tooLong(enContent, MAX_CONTENT_LEN) || tooLong(esContent, MAX_CONTENT_LEN)) {
|
||||
return c.json({ error: `Content must be at most ${MAX_CONTENT_LEN} characters` }, 400);
|
||||
}
|
||||
if (tooLong(title, MAX_TITLE_LEN) || tooLong(titleEs, MAX_TITLE_LEN)) {
|
||||
return c.json({ error: `Title must be at most ${MAX_TITLE_LEN} characters` }, 400);
|
||||
}
|
||||
|
||||
const existing = await dbGet(
|
||||
(db as any)
|
||||
|
||||
Reference in New Issue
Block a user