Skip to content

Commit 4f010d6

Browse files
committed
fix: address CodeRabbitAI review comments for database output
- Fix SQL injection in postgres.go using pq.QuoteIdentifier for table/index names - Fix SQL injection in mysql.go using custom quoteIdentifier function - Fix race condition in writer.go by checking closed state before channel send - Add missing idx_url index in mysql.go for parity with PostgreSQL schema - Include RawHeaders in omitRaw check for consistency
1 parent e64dfcb commit 4f010d6

3 files changed

Lines changed: 37 additions & 15 deletions

File tree

internal/db/mysql.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ import (
55
"database/sql"
66
"encoding/json"
77
"fmt"
8+
"strings"
89

910
_ "github.com/go-sql-driver/mysql"
1011
"github.com/projectdiscovery/httpx/runner"
1112
)
1213

14+
func quoteIdentifier(name string) string {
15+
return "`" + strings.ReplaceAll(name, "`", "``") + "`"
16+
}
17+
1318
func init() {
1419
Register(MySQL, newMySQLDatabase)
1520
}
@@ -45,6 +50,7 @@ func (m *mysqlDatabase) Close() error {
4550
}
4651

4752
func (m *mysqlDatabase) EnsureSchema(ctx context.Context) error {
53+
tableName := quoteIdentifier(m.cfg.TableName)
4854
schema := fmt.Sprintf(`
4955
CREATE TABLE IF NOT EXISTS %s (
5056
id BIGINT AUTO_INCREMENT PRIMARY KEY,
@@ -118,7 +124,7 @@ func (m *mysqlDatabase) EnsureSchema(ctx context.Context) error {
118124
119125
-- Metrics
120126
words INT,
121-
` + "`lines`" + ` INT,
127+
`+"`lines`"+` INT,
122128
123129
-- Headers and extracts
124130
header JSON,
@@ -146,10 +152,11 @@ func (m *mysqlDatabase) EnsureSchema(ctx context.Context) error {
146152
trace JSON,
147153
148154
INDEX idx_timestamp (timestamp),
155+
INDEX idx_url (url(255)),
149156
INDEX idx_host (host),
150157
INDEX idx_status_code (status_code)
151158
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
152-
`, m.cfg.TableName)
159+
`, tableName)
153160

154161
_, err := m.db.ExecContext(ctx, schema)
155162
if err != nil {
@@ -172,6 +179,8 @@ func (m *mysqlDatabase) InsertBatch(ctx context.Context, results []runner.Result
172179
_ = tx.Rollback()
173180
}()
174181

182+
// Use quoteIdentifier to safely quote table name to prevent SQL injection
183+
tableName := quoteIdentifier(m.cfg.TableName)
175184
query := fmt.Sprintf(`
176185
INSERT INTO %s (
177186
timestamp, url, input, host, port, scheme, path, method, final_url,
@@ -197,7 +206,7 @@ func (m *mysqlDatabase) InsertBatch(ctx context.Context, results []runner.Result
197206
?, ?,
198207
?, ?, ?, ?, ?,
199208
?, ?, ?
200-
)`, m.cfg.TableName)
209+
)`, tableName)
201210

202211
stmt, err := tx.PrepareContext(ctx, query)
203212
if err != nil {

internal/db/postgres.go

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ func (p *postgresDatabase) Close() error {
4545
}
4646

4747
func (p *postgresDatabase) EnsureSchema(ctx context.Context) error {
48+
tableName := pq.QuoteIdentifier(p.cfg.TableName)
49+
idxTimestamp := pq.QuoteIdentifier("idx_" + p.cfg.TableName + "_timestamp")
50+
idxURL := pq.QuoteIdentifier("idx_" + p.cfg.TableName + "_url")
51+
idxHost := pq.QuoteIdentifier("idx_" + p.cfg.TableName + "_host")
52+
idxStatusCode := pq.QuoteIdentifier("idx_" + p.cfg.TableName + "_status_code")
53+
idxTech := pq.QuoteIdentifier("idx_" + p.cfg.TableName + "_tech")
54+
4855
schema := fmt.Sprintf(`
4956
CREATE TABLE IF NOT EXISTS %s (
5057
id BIGSERIAL PRIMARY KEY,
@@ -146,18 +153,18 @@ func (p *postgresDatabase) EnsureSchema(ctx context.Context) error {
146153
trace JSONB
147154
);
148155
149-
CREATE INDEX IF NOT EXISTS idx_%s_timestamp ON %s(timestamp DESC);
150-
CREATE INDEX IF NOT EXISTS idx_%s_url ON %s(url);
151-
CREATE INDEX IF NOT EXISTS idx_%s_host ON %s(host);
152-
CREATE INDEX IF NOT EXISTS idx_%s_status_code ON %s(status_code);
153-
CREATE INDEX IF NOT EXISTS idx_%s_tech ON %s USING GIN(tech);
156+
CREATE INDEX IF NOT EXISTS %s ON %s(timestamp DESC);
157+
CREATE INDEX IF NOT EXISTS %s ON %s(url);
158+
CREATE INDEX IF NOT EXISTS %s ON %s(host);
159+
CREATE INDEX IF NOT EXISTS %s ON %s(status_code);
160+
CREATE INDEX IF NOT EXISTS %s ON %s USING GIN(tech);
154161
`,
155-
p.cfg.TableName,
156-
p.cfg.TableName, p.cfg.TableName,
157-
p.cfg.TableName, p.cfg.TableName,
158-
p.cfg.TableName, p.cfg.TableName,
159-
p.cfg.TableName, p.cfg.TableName,
160-
p.cfg.TableName, p.cfg.TableName,
162+
tableName,
163+
idxTimestamp, tableName,
164+
idxURL, tableName,
165+
idxHost, tableName,
166+
idxStatusCode, tableName,
167+
idxTech, tableName,
161168
)
162169

163170
_, err := p.db.ExecContext(ctx, schema)
@@ -181,6 +188,7 @@ func (p *postgresDatabase) InsertBatch(ctx context.Context, results []runner.Res
181188
_ = tx.Rollback()
182189
}()
183190

191+
tableName := pq.QuoteIdentifier(p.cfg.TableName)
184192
query := fmt.Sprintf(`
185193
INSERT INTO %s (
186194
timestamp, url, input, host, port, scheme, path, method, final_url,
@@ -206,7 +214,7 @@ func (p *postgresDatabase) InsertBatch(ctx context.Context, results []runner.Res
206214
$53, $54,
207215
$55, $56, $57, $58, $59,
208216
$60, $61, $62
209-
)`, p.cfg.TableName)
217+
)`, tableName)
210218

211219
stmt, err := tx.PrepareContext(ctx, query)
212220
if err != nil {

internal/db/writer.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ func NewWriter(ctx context.Context, cfg *Config) (*Writer, error) {
6060

6161
func (w *Writer) GetWriterCallback() runner.OnResultCallback {
6262
return func(r runner.Result) {
63+
if w.closed.Load() {
64+
return
65+
}
66+
6367
if r.Err != nil {
6468
return
6569
}
@@ -68,6 +72,7 @@ func (w *Writer) GetWriterCallback() runner.OnResultCallback {
6872
r.Raw = ""
6973
r.Request = ""
7074
r.ResponseBody = ""
75+
r.RawHeaders = ""
7176
}
7277

7378
select {

0 commit comments

Comments
 (0)