fix: harden API, DB, and web layer from audit findings
- Cap list API limit at 200 to prevent unbounded queries - Sanitize markdown output with DOMPurify to prevent XSS - Add v4 migration with indexes on deleted_at and modified_at - Fix v2 migration swallowed ALTER TABLE errors - Tighten ~/.nib directory permissions to 0o700
This commit is contained in:
@@ -92,6 +92,9 @@ func listEntities(store *db.Store) http.HandlerFunc {
|
||||
writeError(w, http.StatusBadRequest, "invalid_input", "limit must be a positive integer")
|
||||
return
|
||||
}
|
||||
if limit > 200 {
|
||||
limit = 200
|
||||
}
|
||||
p.Limit = limit
|
||||
}
|
||||
if offsetStr := r.URL.Query().Get("offset"); offsetStr != "" {
|
||||
|
||||
+21
-4
@@ -51,7 +51,7 @@ func (s *Store) Close() error {
|
||||
return s.db.Close()
|
||||
}
|
||||
|
||||
const currentSchema = 3
|
||||
const currentSchema = 4
|
||||
|
||||
var migrations = []func(db *sql.DB) error{
|
||||
// v1: initial schema
|
||||
@@ -92,8 +92,12 @@ var migrations = []func(db *sql.DB) error{
|
||||
|
||||
// v2: add title and description columns
|
||||
func(db *sql.DB) error {
|
||||
db.Exec(`ALTER TABLE entities ADD COLUMN title TEXT`)
|
||||
db.Exec(`ALTER TABLE entities ADD COLUMN description TEXT`)
|
||||
if _, err := db.Exec(`ALTER TABLE entities ADD COLUMN title TEXT`); err != nil {
|
||||
return fmt.Errorf("add title column: %w", err)
|
||||
}
|
||||
if _, err := db.Exec(`ALTER TABLE entities ADD COLUMN description TEXT`); err != nil {
|
||||
return fmt.Errorf("add description column: %w", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -166,6 +170,19 @@ var migrations = []func(db *sql.DB) error{
|
||||
|
||||
return tx.Commit()
|
||||
},
|
||||
|
||||
// v4: add indexes for common query filters
|
||||
func(db *sql.DB) error {
|
||||
for _, idx := range []string{
|
||||
`CREATE INDEX IF NOT EXISTS idx_entities_deleted ON entities(deleted_at)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_entities_modified ON entities(modified_at DESC) WHERE deleted_at IS NULL`,
|
||||
} {
|
||||
if _, err := db.Exec(idx); err != nil {
|
||||
return fmt.Errorf("create index: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func (s *Store) migrate() error {
|
||||
@@ -200,7 +217,7 @@ func DefaultPath() (string, error) {
|
||||
return "", err
|
||||
}
|
||||
dir := filepath.Join(home, ".nib")
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
if err := os.MkdirAll(dir, 0o700); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(dir, "nib.db"), nil
|
||||
|
||||
Reference in New Issue
Block a user