fix: security hardening and code quality

- SQL query mode uses read-only SQLite connection with PRAGMA query_only=ON
- Lua sandbox removes dofile/loadfile/load after OpenBase to block file access
- Plugin manager sorts by priority once at load time; GetPlugins is a plain copy
- Proxy appends [body truncated] marker when body hits size limit
- App startup exits with os.Exit(1) on DB open failure
- tickCmd uses tea.Tick instead of time.Sleep in a goroutine
- ErrMsg with non-nil error shows notification then quits
- DB stores path for use by read-only query connection
- WAL journal mode + NORMAL synchronous set in migrate()
- config.go uses errors.Is(err, os.ErrNotExist)
- main.go uses os.UserHomeDir() and removes racy port pre-check
- findings renderer is cached and rebuilt only on width change

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Hadi
2026-05-19 13:38:10 +02:00
parent 41c0e489cf
commit 172a77e13b
11 changed files with 88 additions and 37 deletions
+5 -1
View File
@@ -9,6 +9,7 @@ import (
type DB struct {
conn *sql.DB
path string
dedupMu sync.Mutex
}
@@ -17,7 +18,7 @@ func Open(path string) (*DB, error) {
if err != nil {
return nil, err
}
d := &DB{conn: conn}
d := &DB{conn: conn, path: path}
if err := d.migrate(); err != nil {
conn.Close()
return nil, err
@@ -26,6 +27,9 @@ func Open(path string) (*DB, error) {
}
func (d *DB) migrate() error {
if _, err := d.conn.Exec(`PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL; PRAGMA foreign_keys=OFF;`); err != nil {
return err
}
_, err := d.conn.Exec(`
CREATE TABLE IF NOT EXISTS entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
+11 -1
View File
@@ -110,9 +110,19 @@ func (d *DB) SearchEntries(term string) ([]Entry, error) {
// QueryEntries runs a WHERE expression supplied by the user against the entries
// table (e.g. "status_code = 404" or "host LIKE '%example.com%'").
// It opens a dedicated read-only connection so that any DML or DDL in the
// user-supplied expression is rejected by SQLite before it can execute.
func (d *DB) QueryEntries(where string) ([]Entry, error) {
roConn, err := sql.Open("sqlite", d.path)
if err != nil {
return nil, err
}
defer roConn.Close()
if _, err := roConn.Exec("PRAGMA query_only=ON"); err != nil {
return nil, err
}
q := "SELECT id, timestamp, method, host, path, status_code, request_raw, response_raw FROM entries WHERE " + strings.TrimSpace(where)
rows, err := d.conn.Query(q)
rows, err := roConn.Query(q)
if err != nil {
return nil, err
}