Security hardening: fix critical, high, and medium issues from audit
CRITICAL: - A-001: SQL injection in snapshot — escape single quotes in backup path - A-002: Timing attack — always verify against dummy hash when user not found, preventing username enumeration - A-003: Notebook ownership — all authenticated endpoints now verify user_id before loading notebook data - A-004: Point data bounds — decodePoints returns error on misaligned data, >4MB payloads, and NaN/Inf values HIGH: - A-005: Error messages — generic errors in HTTP responses, no err.Error() - A-006: Share link authz — RevokeShareLink verifies notebook ownership - A-007: Scan errors — return 500 instead of silently continuing MEDIUM: - A-008: Web server TLS — optional TLS support (HTTPS when configured) - A-009: Input validation — page_size, stroke count, point_data alignment checked in SyncNotebook RPC - A-010: Graceful shutdown — 30s drain on SIGINT/SIGTERM, all servers shut down properly Added AUDIT.md with all 17 findings, status, and rationale for accepted risks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,8 +12,8 @@ type Page struct {
|
||||
}
|
||||
|
||||
// RenderPDF generates a minimal PDF document from pages.
|
||||
// Uses raw PDF operators — no external library needed.
|
||||
func RenderPDF(pageSize string, pages []Page) []byte {
|
||||
// Uses raw PDF operators -- no external library needed.
|
||||
func RenderPDF(pageSize string, pages []Page) ([]byte, error) {
|
||||
w, h := PageSizePt(pageSize)
|
||||
|
||||
var objects []string
|
||||
@@ -30,7 +30,7 @@ func RenderPDF(pageSize string, pages []Page) []byte {
|
||||
objects = append(objects, fmt.Sprintf("1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n"))
|
||||
pdf.WriteString(objects[0])
|
||||
|
||||
// Pages object (object 2) — we'll write this after we know the page objects
|
||||
// Pages object (object 2) -- we'll write this after we know the page objects
|
||||
pagesObjOffset := pdf.Len()
|
||||
pagesObjPlaceholder := strings.Repeat(" ", 200) + "\n"
|
||||
pdf.WriteString(pagesObjPlaceholder)
|
||||
@@ -47,7 +47,10 @@ func RenderPDF(pageSize string, pages []Page) []byte {
|
||||
// Content stream
|
||||
var stream strings.Builder
|
||||
for _, s := range page.Strokes {
|
||||
points := decodePoints(s.PointData)
|
||||
points, err := decodePoints(s.PointData)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(points) < 4 {
|
||||
continue
|
||||
}
|
||||
@@ -89,12 +92,12 @@ func RenderPDF(pageSize string, pages []Page) []byte {
|
||||
// Now write the Pages object at its placeholder position
|
||||
pagesObj := fmt.Sprintf("2 0 obj\n<< /Type /Pages /Kids [%s] /Count %d >>\nendobj\n",
|
||||
strings.Join(pageRefs, " "), len(pages))
|
||||
// Overwrite placeholder — we need to rebuild the PDF string
|
||||
// Overwrite placeholder -- we need to rebuild the PDF string
|
||||
pdfStr := pdf.String()
|
||||
pdfStr = pdfStr[:pagesObjOffset] + pagesObj + strings.Repeat(" ", len(pagesObjPlaceholder)-len(pagesObj)) + pdfStr[pagesObjOffset+len(pagesObjPlaceholder):]
|
||||
|
||||
// Rebuild with correct offsets for xref
|
||||
// For simplicity, just return the PDF bytes — most viewers handle minor xref issues
|
||||
// For simplicity, just return the PDF bytes -- most viewers handle minor xref issues
|
||||
var final strings.Builder
|
||||
final.WriteString(pdfStr)
|
||||
|
||||
@@ -102,7 +105,7 @@ func RenderPDF(pageSize string, pages []Page) []byte {
|
||||
xrefOffset := final.Len()
|
||||
fmt.Fprintf(&final, "xref\n0 %d\n", nextObj)
|
||||
fmt.Fprintf(&final, "0000000000 65535 f \n")
|
||||
// For a proper PDF we'd need exact offsets — skip for now
|
||||
// For a proper PDF we'd need exact offsets -- skip for now
|
||||
for i := 0; i < nextObj-1; i++ {
|
||||
fmt.Fprintf(&final, "%010d 00000 n \n", 0)
|
||||
}
|
||||
@@ -110,5 +113,5 @@ func RenderPDF(pageSize string, pages []Page) []byte {
|
||||
fmt.Fprintf(&final, "trailer\n<< /Size %d /Root 1 0 R >>\n", nextObj)
|
||||
fmt.Fprintf(&final, "startxref\n%d\n%%%%EOF\n", xrefOffset)
|
||||
|
||||
return []byte(final.String())
|
||||
return []byte(final.String()), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user