fix: P2 API hardening — unbounded SELECTs, export audit log, header injection, empty-key guard
- export: add .limit(10000), sanitize filename, write_audit_log on every export - stats: add .limit(10000) to aggregation query - settings POST: reject empty string values to prevent silent key deletion Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPf5Rc8QPx6V8KLEEgfKEQ
This commit is contained in:
@@ -31,6 +31,7 @@ export async function GET(request: NextRequest) {
|
||||
sites (name), zones (name)
|
||||
`)
|
||||
.order('reported_at', { ascending: false })
|
||||
.limit(10000)
|
||||
|
||||
const rows = incidents ?? []
|
||||
|
||||
@@ -58,7 +59,15 @@ export async function GET(request: NextRequest) {
|
||||
})
|
||||
|
||||
const csv = rowsToCsv(headers, csvRows)
|
||||
const filename = `incidents-${role}-${new Date().toISOString().split('T')[0]}.csv`
|
||||
const safeRole = role.replace(/[^a-z0-9]/gi, '')
|
||||
const filename = `incidents-${safeRole}-${new Date().toISOString().split('T')[0]}.csv`
|
||||
|
||||
await supabase.rpc('write_audit_log', {
|
||||
p_table_name: 'incidents',
|
||||
p_record_id: user.id,
|
||||
p_action: 'export_csv',
|
||||
p_new_value: { role, row_count: rows.length } as never,
|
||||
})
|
||||
|
||||
return new NextResponse(csv, {
|
||||
status: 200,
|
||||
|
||||
@@ -15,6 +15,7 @@ export async function GET() {
|
||||
const { data: incidents, error } = await supabase
|
||||
.from('incidents')
|
||||
.select('id, status, incident_type, sites (name)')
|
||||
.limit(10000)
|
||||
|
||||
if (error) return NextResponse.json({ error: 'Failed to fetch stats' }, { status: 500 })
|
||||
|
||||
|
||||
Reference in New Issue
Block a user