-
Notifications
You must be signed in to change notification settings - Fork 0
ARGUS A25
will2469 edited this page Aug 29, 2026
·
1 revision
| Meta Field | Specification |
|---|---|
| Rule Code | ARGUS-A25 |
| Identifier | EXPENSIVE_CPU_IN_TRANSACTION |
| Severity | HIGH |
| Category | Transaction Hygiene, Concurrency Scalability & Resource Starvation Prevention |
| Analysis Layer | Layer 3 - Contextual & Interprocedural Call Graph Analysis |
| CWE Mapping | CWE-400: Uncontrolled Resource Consumption, CWE-662: Improper Synchronization |
| OWASP ASVS | OWASP ASVS v4.0.3/v5.0 §V7.1.1, §V11.1.4 (Resource Governance & Lock Contention Avoidance) |
| PostgreSQL Target | Transaction Lock Duration Inflation & Connection Pool Starvation Prevention |
| Default Status | enabled |
CPU-intensive computations-such as cryptographic password hashing (bcrypt, argon2, scrypt), asymmetric key generation (RSA, ECDSA, Ed25519), or document/media subprocess execution (exec.Command)-are strictly prohibited inside active database transactions (pgx.Tx, BeginFunc, ExecuteTx).
┌─────────────────────────────────────────────────────────────────────────────┐
│ ARCHITECTURAL INVARIANT │
│ │
│ Heavy CPU computations MUST execute in Go memory BEFORE opening a database │
│ transaction, or asynchronously AFTER `COMMIT`. │
│ │
│ Transactions must be ultra-lean (< 5 milliseconds duration) to prevent │
│ database connection pool starvation and lock convoys. │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ EXPENSIVE CPU IN TRANSACTION DISASTER │
│ │
│ [ BEGIN Transaction ] │
│ │ │
│ ├─► INSERT INTO users (pending_status) ──► Acquired Row Lock (1ms) │
│ │ │
│ ├─► bcrypt.GenerateFromPassword(cost: 12) ◄── 300ms HEAVY CPU BURDEN! │
│ │ (DB connection idle on wire; Row Lock held for 300ms!) │
│ │ │
│ ├─► INSERT INTO auth_credentials (hashed) (1ms) │
│ │ │
│ [ COMMIT Transaction ] │
│ │
│ Impact: 100 concurrent requests = 100 connections held for 300ms │
│ = POOL EXHAUSTION & SYSTEM-WIDE REQUEST TIMEOUTS (CWE-400) │
└─────────────────────────────────────────────────────────────────────────────┘
When an application performs heavy hashing or key generation inside a transaction:
- The database backend sits idle on the TCP socket waiting for application bytes.
- It continues holding exclusive row-level and table-level locks for hundreds of milliseconds.
- Any concurrent transaction touching the same tables is forced into a lock wait convoy.
- With a pool size of 50 connections, 50 simultaneous user registrations executing
bcrypt(300ms) will exhaust the entire connection pool instantly. - Unrelated, high-speed queries (e.g. login checks, public portal reads) fail with connection acquisition timeouts, making the service appear down even when server CPU usage is low.
flowchart TD
A["AST Function Declaration"] --> B{"Is Call Site Inside Active Transaction Scope?"}
B -- "No (Outside Transaction)" --> C["PASS (Compliant)"]
B -- "Yes (BeginFunc / pool.Begin ... tx.Commit)" --> D{"Is Operation Heavy CPU / Crypto?"}
D -- "No (Light Math/Strings)" --> E["PASS"]
D -- "Yes (bcrypt, argon2, RSA keygen, exec.Command)" --> F["FAIL: ARGUS-A25 Expensive CPU in Transaction (CWE-400)"]
-
Transaction Scope Walker: Detects both closure-based transactions (
BeginFunc,ExecuteTx,ExecuteLockedTx,WithTx) and explicit lexical blocks (pool.Begin...tx.Commit). -
Expensive Call Matcher: Identifies calls to:
-
golang.org/x/crypto/bcrypt(GenerateFromPassword,CompareHashAndPassword) -
golang.org/x/crypto/argon2(IDKey,Key) -
golang.org/x/crypto/scrypt(Key) -
crypto/rsa,crypto/ecdsa,crypto/ed25519(GenerateKey) -
os/exec(Command,CommandContext)
-
- Intra-Package Helper Traversal: Recursively inspects helper functions called from within the transaction scope.
-
Exemptions: Statements pre-annotated with
// argus:ignore ARGUS-A25 <reason>.
// VIOLATION: Hashing password inside BeginFunc holds connection for 300ms
err := pool.BeginFunc(ctx, func(tx pgx.Tx) error {
hashed, err := bcrypt.GenerateFromPassword([]byte(password), 12)
if err != nil {
return err
}
_, err = tx.Exec(ctx, "INSERT INTO users (hash) VALUES ($1)", hashed)
return err
})// VIOLATION: RSA key generation inside explicit transaction
tx, err := pool.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
key, err := rsa.GenerateKey(rand.Reader, 4096) // 1-2 seconds CPU delay!
if err != nil {
return err
}
_, err = tx.Exec(ctx, "INSERT INTO keys (pub) VALUES ($1)", key.PublicKey)
return tx.Commit(ctx)// COMPLIANT: Compute hash in memory before opening transaction
hashed, err := bcrypt.GenerateFromPassword([]byte(password), 12)
if err != nil {
return err
}
// Transaction duration is ultra-lean (< 2ms)
err = pool.BeginFunc(ctx, func(tx pgx.Tx) error {
_, err := tx.Exec(ctx, "INSERT INTO users (hash) VALUES ($1)", hashed)
return err
})// COMPLIANT: Keypair generated prior to database interaction
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return err
}
return saveKey(ctx, pool, key)- Pre-compute Hashes: Run password hashing and key derivation in Go memory before acquiring a pooled database connection.
- Post-Commit Asynchronous Tasks: Offload document compiling (Typst), media encoding, or image resizing to background workers after the transaction commits.
-
Tune Cost Parameters: In unit tests or development environments, use minimal work factors (
bcrypt.MinCost) to maintain fast test execution.
rules:
ARGUS-A25:
enabled: true// argus:ignore ARGUS-A25 mock test harness isolated benchmark execution
hashed, err := bcrypt.GenerateFromPassword([]byte(password), 4)