Replay Attack in Echo Go with Cockroachdb
Replay Attack in Echo Go with Cockroachdb — how this specific combination creates or exposes the vulnerability
A replay attack in the combination of Echo Go and Cockroachdb occurs when an attacker intercepts a valid request or transaction identifier and re-sends it to the API to achieve unauthorized effects, such as duplicate payments or state mutation. Because Echo Go is a web framework often used to build APIs that coordinate with Cockroachdb, a strongly-consistent distributed SQL database, the interaction between HTTP handling in Echo and Cockroachdb transactions can expose replay risks when idempotency controls are absent.
Consider an Echo Go handler that executes a Cockroachdb transaction to transfer funds or insert a record without verifying whether the request has been processed before. If the client uses an HTTP method that is not inherently idempotent or the server does not enforce idempotency keys, an attacker can capture a request containing a unique transaction ID, timestamp, or a signed token, then replay that request later. Cockroachdb’s serializable isolation and distributed nature do not prevent logical duplicate writes if the application layer does not deduplicate; the database will faithfully execute each transaction, leading to double-charges, repeated state changes, or inconsistent ledger entries.
The vulnerability is shaped by three dimensions in this stack:
- Echo Go request lifecycle: Without an idempotency key or nonce in the request, two identical POST or PUT requests are indistinguishable to the handler. Echo middleware can be used to inspect headers, but if idempotency is not enforced before the Cockroachdb transaction begins, the server may process the same business action multiple times.
- Cockroachdb transaction semantics: Cockroachdb guarantees ACID properties across distributed nodes, but it does not automatically prevent application-level duplicates. If a transaction writes a row with a unique business identifier (e.g., payment_id) only after checking for its existence, a race condition or missing uniqueness constraint can allow a replay to insert a second, conflicting record.
- Transport and storage of identifiers: If request identifiers, timestamps, or cryptographic nonces are stored in Cockroachdb without proper constraints (unique indexes), an attacker can replay requests within the validity window. Without encryption in transit and careful handling of sensitive metadata, intercepted identifiers can be reused to craft malicious but valid-looking requests.
For example, an attacker who observes a successful order creation request with a payment ID can replay the same HTTP call to create additional orders, and Cockroachdb will commit each as a new transaction unless the application enforces uniqueness at the schema level.
Cockroachdb-Specific Remediation in Echo Go — concrete code fixes
To mitigate replay attacks in Echo Go with Cockroachdb, implement idempotency at the application layer, enforce uniqueness constraints in the database, and ensure safe handling of identifiers. Below are concrete code examples that demonstrate these protections.
1. Enforce uniqueness with Cockroachdb schema constraints
Define a unique index on business identifiers (such as idempotency_key or payment_id) in Cockroachdb so that duplicate commits are rejected at the database level.
-- Cockroachdb SQL schema
CREATE TABLE payments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
idempotency_key STRING UNIQUE NOT NULL,
user_id UUID NOT NULL,
amount DECIMAL(12,2) NOT NULL,
status STRING NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
2. Idempotency check within an Echo Go handler using a Cockroachdb transaction
Before executing business logic, check for an existing idempotency key within a serializable transaction. If the key exists, return the previous result instead of reprocessing.
// Echo Go handler example
package handlers
import (
"context"
"net/http"
"github.com/labstack/echo/v4"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/google/uuid"
)
type PaymentRequest struct {
IDempotencyKey string `json:"idempotency_key"`
UserID string `json:"user_id"`
Amount float64 `json:"amount"`
}
func CreatePayment(db *pgxpool.Pool) echo.HandlerFunc {
return func(c echo.Context) error {
req := new(PaymentRequest)
if err := c.Bind(req); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "invalid payload")
}
if req.IDempotencyKey == "" {
return echo.NewHTTPError(http.StatusBadRequest, "idempotency_key is required")
}
ctx := c.Request().Context()
err := db.BeginTx(ctx, pgxpool.TxOptions{}).Tx(ctx).(func(tx pgx.Tx) error {
var existing string
row := tx.QueryRow(ctx, "SELECT idempotency_key FROM payments WHERE idempotency_key = $1", req.IDempotencyKey)
if err := row.Scan(&existing); err != nil {\n if err == pgx.ErrNoRows {
// No previous record, proceed with insert
_, err = tx.Exec(ctx, "INSERT INTO payments (idempotency_key, user_id, amount, status) VALUES ($1, $2, $3, 'completed')",
req.IDempotencyKey, req.UserID, req.Amount)
return err
}
return err
}
// Key already exists; do not reprocess
return nil
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "failed to process payment")
}
return c.JSON(http.StatusOK, map[string]string{"status": "ok"})
}
}
3. Use request-level nonces and timestamps
Include a client-supplied nonce and timestamp in the payload, store them in Cockroachdb, and reject requests with a nonce or timestamp that has been seen recently. This prevents replays beyond a defined time window.
-- Additional uniqueness guard
CREATE TABLE request_nonces (
nonce STRING NOT NULL,
seen_at TIMESTAMPTZ DEFAULT now(),
PRIMARY KEY (nonce)
);
In your Echo middleware or handler, verify the nonce against this table within the same transaction to ensure it has not been processed.
4. Transport security and identifier handling
Ensure all communication between Echo Go and Cockroachdb uses TLS, and avoid logging or persisting sensitive identifiers in plaintext. Use prepared statements or parameterized queries to prevent injection when checking or inserting idempotency keys.
By combining schema-level uniqueness, server-side idempotency checks, and strict nonce management, replay attacks against this stack are effectively neutralized while preserving Cockroachdb’s consistency guarantees.