Skip to main content

Security Measures

This page captures the application-level controls that reduce common attack paths in RideSync, with a concrete review of SQL injection exposure in the current codebase.

SQL Injection Review

An April 5, 2026 review of the repository did not find any confirmed SQL injection vulnerabilities in the live application query paths.

Scope Reviewed

  • services/platform-service/internal/infrastructure/repository/postgres_users.go
  • services/platform-service/internal/infrastructure/repository/postgres_ledger.go
  • services/platform-service/internal/infrastructure/platgrpc/auth.go
  • services/platform-service/internal/infrastructure/platgrpc/finance.go
  • services/platform-service/internal/service/auth_service.go
  • services/api-gateway/finance_api.go
  • services/api-gateway/admin_api.go

Why The Current Queries Are Safe

  • Runtime PostgreSQL access is concentrated in the Platform Service repositories and uses pgx positional parameters such as $1, $2, and $3 for user-controlled values.
  • User-provided values including email addresses, user IDs, reset tokens, and pagination limits are passed as bound parameters rather than interpolated into SQL strings.
  • Finance date-range filters are validated as RFC3339 timestamps in the gRPC layer before reaching the repository, so free-form SQL fragments cannot flow into the query builder.
  • The small amount of dynamic SQL construction in the ledger analytics queries only appends placeholder indexes like $1 and $2; it does not append raw request text, column names, table names, or sort expressions.

Reviewed Examples

Safe parameterized patterns currently used in the repository include:

r.Pool.QueryRow(ctx, `SELECT COUNT(*) FROM users WHERE email = $1`, email)

r.Pool.Exec(ctx, `
INSERT INTO users (id, email, password_hash, role) VALUES ($1, $2, $3, $4)`,
id, email, hash, role)

The date-range analytics queries are also safe in their current form because only placeholder numbers are concatenated:

q := `SELECT COALESCE(SUM(amount_cents),0) FROM transactions WHERE 1=1`
if from != nil {
args = append(args, *from)
q += ` AND created_at >= $` + strconv.Itoa(len(args))
}

This pattern is safe here because the resulting SQL text changes only in parameter position, while the actual values still travel through args....

Remaining Security Constraints

The current posture is good, but the safety depends on preserving a few implementation rules:

  • Do not concatenate request values directly into SQL statements, even for seemingly harmless filters.
  • If the project later adds dynamic ORDER BY, column selection, table selection, or free-form search operators, those identifiers must be chosen from a fixed allowlist rather than copied from user input.
  • Keep date parsing and numeric parsing in the HTTP or gRPC boundary so repositories continue to receive typed values instead of untrusted raw strings.
  • Treat migration execution as trusted operator-only behavior. shared/sqlmigrate/sqlmigrate.go executes raw SQL files by design, so migration paths and files must not be user-controlled.
  • Password reset tokens are hashed before lookup and update operations in the Platform Service.
  • Audit log insertion validates that detail_json is valid JSON before persisting it as jsonb.
  • The API Gateway already documents CORS behavior and should continue tightening production origin allowlists rather than relying on wildcard origins.

Reviewer Conclusion

At the time of review, the checked-in Postgres query paths are parameterized and are not SQL-injection prone. The main future risk is not the existing repository code, but any later introduction of string-built identifiers or raw search clauses without an allowlist.