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:
@@ -9,6 +9,9 @@ import (
|
||||
|
||||
const canonicalToPDF = 72.0 / 300.0 // 0.24
|
||||
|
||||
// maxPointDataSize is the maximum allowed size of point data (4 MB).
|
||||
const maxPointDataSize = 4 * 1024 * 1024
|
||||
|
||||
// PageSizePt returns the page dimensions in PDF points (72 DPI).
|
||||
func PageSizePt(pageSize string) (float64, float64) {
|
||||
switch pageSize {
|
||||
@@ -20,15 +23,15 @@ func PageSizePt(pageSize string) (float64, float64) {
|
||||
}
|
||||
|
||||
type Stroke struct {
|
||||
PenSize float32
|
||||
Color int32
|
||||
Style string
|
||||
PointData []byte
|
||||
PenSize float32
|
||||
Color int32
|
||||
Style string
|
||||
PointData []byte
|
||||
StrokeOrder int
|
||||
}
|
||||
|
||||
// RenderSVG renders a page's strokes as an SVG document.
|
||||
func RenderSVG(pageSize string, strokes []Stroke) string {
|
||||
func RenderSVG(pageSize string, strokes []Stroke) (string, error) {
|
||||
w, h := PageSizePt(pageSize)
|
||||
var b strings.Builder
|
||||
|
||||
@@ -39,7 +42,10 @@ func RenderSVG(pageSize string, strokes []Stroke) string {
|
||||
b.WriteString("\n")
|
||||
|
||||
for _, s := range strokes {
|
||||
points := decodePoints(s.PointData)
|
||||
points, err := decodePoints(s.PointData)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(points) < 4 {
|
||||
continue
|
||||
}
|
||||
@@ -71,7 +77,7 @@ func RenderSVG(pageSize string, strokes []Stroke) string {
|
||||
}
|
||||
|
||||
b.WriteString("</svg>")
|
||||
return b.String()
|
||||
return b.String(), nil
|
||||
}
|
||||
|
||||
func renderArrowHeads(x1, y1, x2, y2 float64, style string, penW float64, color string) string {
|
||||
@@ -109,14 +115,28 @@ func renderArrowHeads(x1, y1, x2, y2 float64, style string, penW float64, color
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func decodePoints(data []byte) []float64 {
|
||||
// decodePoints decodes a byte slice of little-endian float32 values into float64.
|
||||
// Returns an error if the data length is not a multiple of 4, exceeds maxPointDataSize,
|
||||
// or contains NaN/Inf values.
|
||||
func decodePoints(data []byte) ([]float64, error) {
|
||||
if len(data)%4 != 0 {
|
||||
return nil, fmt.Errorf("point data length %d is not a multiple of 4", len(data))
|
||||
}
|
||||
if len(data) > maxPointDataSize {
|
||||
return nil, fmt.Errorf("point data size %d exceeds maximum %d", len(data), maxPointDataSize)
|
||||
}
|
||||
|
||||
count := len(data) / 4
|
||||
points := make([]float64, count)
|
||||
points := make([]float64, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
bits := binary.LittleEndian.Uint32(data[i*4 : (i+1)*4])
|
||||
points[i] = float64(math.Float32frombits(bits))
|
||||
v := float64(math.Float32frombits(bits))
|
||||
if math.IsNaN(v) || math.IsInf(v, 0) {
|
||||
return nil, fmt.Errorf("point data contains NaN or Inf at index %d", i)
|
||||
}
|
||||
points = append(points, v)
|
||||
}
|
||||
return points
|
||||
return points, nil
|
||||
}
|
||||
|
||||
func colorToCSS(argb int32) string {
|
||||
|
||||
Reference in New Issue
Block a user