-
Notifications
You must be signed in to change notification settings - Fork 0
ARGUS A26
will2469 edited this page Aug 29, 2026
·
1 revision
| Meta Field | Specification |
|---|---|
| Rule Code | ARGUS-A26 |
| Identifier | LIKE_WILDCARD_INJECTION |
| Severity | HIGH |
| Category | SQL Injection Prevention, Pattern Hygiene & DoS Prevention |
| Analysis Layer | Layer 4 - Interprocedural Taint & Pattern Analysis |
| CWE Mapping | CWE-89: SQL Injection (Pattern Language Variant), CWE-400: Uncontrolled Resource Consumption |
| OWASP ASVS | OWASP ASVS v4.0.3/v5.0 §V5.3.1 (Input Validation & Output Encoding) |
| PostgreSQL Target | Pattern Matching Engine §9.7.1, Prefix Index B-tree Invalidation & Sequential Scan DoS Prevention |
| Default Status | enabled |
User-derived input strings bound to SQL LIKE or ILIKE pattern matching clauses must be explicitly sanitized to escape SQL wildcard characters (\, %, and _) prior to pattern assembly (e.g. hecate.FormatLikeContains(userInput)).
┌─────────────────────────────────────────────────────────────────────────────┐
│ ARCHITECTURAL INVARIANT │
│ │
│ Binding unsanitized user inputs to `LIKE`/`ILIKE` parameter placeholders │
│ is strictly prohibited. │
│ │
│ Standard parameterized queries (`$1`) protect against SQL syntax injection │
│ but DO NOT protect against Pattern Language Hijacking (§9.7.1). │
│ │
│ Mandatory escaping order: (1) `\` -> `\\`, (2) `%` -> `\%`, (3) `_` -> `\_`│
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ THE LIKE WILDCARD INJECTION EXPLOIT │
│ │
│ Search Endpoint: │
│ db.Query(ctx, "SELECT id, name FROM citizens WHERE name ILIKE $1", p) │
│ │
│ Case A: Raw Unsanitized User Input (VULNERABLE): │
│ Attacker submits: "%" │
│ ├─► Assembled Pattern: "%" + "%" + "%" = "%%%" │
│ ├─► Engine matches EVERY RECORD in table (100,000 PII records leaked!) │
│ ├─► B-tree prefix index INVALIDATED -> Full Table Scan & CPU 100% DoS │
│ └─► PII EXPOSURE & DENIAL OF SERVICE (CWE-89, CWE-400) │
│ │
│ Case B: Sanitized via hecate.SanitizeLikePattern(input) (COMPLIANT): │
│ Attacker submits: "%" │
│ ├─► SanitizeLikePattern transforms "%" into "\%" │
│ ├─► Assembled Pattern: "%\%%" ESCAPE '\' │
│ ├─► Engine strictly searches for names literally containing "%"! │
│ └─► Result: 0 matched rows. Zero CPU spike, zero data leakage! │
└─────────────────────────────────────────────────────────────────────────────┘
While parameter binding ($1) prevents command injection like ' OR 1=1 --, PostgreSQL's pattern matching engine evaluates % (match any sequence) and _ (match any character) semantically within the bound string value. A single % input defeats intentional query filtering and exposes unauthorized records across the dataset.
When tables use text_pattern_ops indexes for efficient prefix searches, leading wildcards force PostgreSQL to abandon index lookups and execute full sequential scans across millions of records.
flowchart TD
A["SQL Query Parameterized CallSite"] --> B{"Contains LIKE / ILIKE Clause in SQL AST?"}
B -- "No" --> C["PASS (Compliant)"]
B -- "Yes" --> D{"Is Bound Argument Constant or Sanitized?"}
D -- "Constant Literal or Sanitized via hecate" --> E["PASS (Compliant)"]
D -- "Raw Variable / Unsanitized Concat" --> F["FAIL: ARGUS-A26 Wildcard Injection Risk (CWE-89)"]
-
SQL AST Parser (
pg_query_go/v6): IdentifiesLIKE,ILIKE,~~,~~*expressions inSELECT,UPDATE,DELETE, andJOINstatements and extracts the 1-based parameter placeholder indices ($1, $2, ...). -
Taint Tracer: Verifies if the corresponding argument in the Go call expression originates from:
- Compile-time constant string literals (
*ast.BasicLit). - Official sanitizers:
hecate.SanitizeLikePattern,hecate.FormatLikeContains,hecate.FormatLikePrefix,hecate.FormatLikeSuffix,SanitizeLike. -
strings.ReplaceAllchains.
- Compile-time constant string literals (
-
Exemptions: Suppressed via
// argus:ignore ARGUS-A26 <reason>.
// VIOLATION: Raw parameter concatenated directly with wildcards
func SearchUsers(ctx context.Context, db DB, keyword string) ([]User, error) {
pattern := "%" + keyword + "%"
const query = "SELECT id, name FROM users WHERE name ILIKE $1"
return db.Query(ctx, query, pattern)
}// VIOLATION: Raw query parameter bound to SQL concat without sanitization
func SearchAuditLogs(ctx context.Context, db DB, q string) ([]Log, error) {
const query = "SELECT id FROM logs WHERE message ILIKE '%' || $1 || '%'"
return db.Query(ctx, query, q)
}// COMPLIANT: Sanitized using helper function
func SearchUsers(ctx context.Context, db DB, keyword string) ([]User, error) {
pattern := EscapeLikePattern(keyword)
const query = "SELECT id, name FROM users WHERE name ILIKE $1 ESCAPE '\\'"
return db.Query(ctx, query, pattern)
}// COMPLIANT: Explicit sanitization before query binding
func SearchAuditLogs(ctx context.Context, db DB, q string) ([]Log, error) {
safeQ := EscapeLikePattern(q)
const query = "SELECT id FROM logs WHERE message ILIKE '%' || $1 || '%' ESCAPE '\\'"
return db.Query(ctx, query, safeQ)
}-
Use Sanitized Wildcard Escaper:
// Escape user input before concatenating into LIKE query pattern func EscapeLikePattern(s string) string { s = strings.ReplaceAll(s, `\`, `\\`) s = strings.ReplaceAll(s, `%`, `\%`) s = strings.ReplaceAll(s, `_`, `\_`) return "%" + s + "%" }
-
Explicit Escape Clause:
Always include
ESCAPE '\\'in SQL statements when using wildcards to establish unambiguous delimiter semantics across PostgreSQL versions.
rules:
ARGUS-A26:
enabled: true// argus:ignore ARGUS-A26 internal administrative regex-style pattern search
rows, err := db.Query(ctx, adminQuery, rawWildcardPattern)