114 lines
4.2 KiB
YAML
114 lines
4.2 KiB
YAML
rules:
|
|
# ── Go: HTTP handler context hygiene ────────────────────────────────────────
|
|
|
|
- id: veylant-context-background-in-handler
|
|
languages: [go]
|
|
severity: WARNING
|
|
message: >
|
|
HTTP handler uses context.Background() instead of r.Context().
|
|
This bypasses request cancellation, tracing, and tenant context propagation.
|
|
Use r.Context() to inherit the request lifetime.
|
|
patterns:
|
|
- pattern: |
|
|
func $HANDLER($W http.ResponseWriter, $R *http.Request) {
|
|
...
|
|
context.Background()
|
|
...
|
|
}
|
|
paths:
|
|
include:
|
|
- "internal/**/*.go"
|
|
- "cmd/**/*.go"
|
|
|
|
# ── Go: SQL injection risk ──────────────────────────────────────────────────
|
|
|
|
- id: veylant-sql-string-concatenation
|
|
languages: [go]
|
|
severity: ERROR
|
|
message: >
|
|
SQL query built using string concatenation or fmt.Sprintf.
|
|
This is a potential SQL injection vulnerability.
|
|
Use parameterised queries ($1, $2, ...) or named placeholders instead.
|
|
patterns:
|
|
- pattern: db.QueryContext($CTX, $QUERY + $VAR, ...)
|
|
- pattern: db.QueryRowContext($CTX, $QUERY + $VAR, ...)
|
|
- pattern: db.ExecContext($CTX, $QUERY + $VAR, ...)
|
|
- pattern: db.QueryContext($CTX, fmt.Sprintf(...), ...)
|
|
- pattern: db.QueryRowContext($CTX, fmt.Sprintf(...), ...)
|
|
- pattern: db.ExecContext($CTX, fmt.Sprintf(...), ...)
|
|
paths:
|
|
include:
|
|
- "internal/**/*.go"
|
|
|
|
# ── Go: Sensitive data in structured logs ───────────────────────────────────
|
|
|
|
- id: veylant-sensitive-field-in-log
|
|
languages: [go]
|
|
severity: WARNING
|
|
message: >
|
|
Potentially sensitive field name logged. Ensure this does not contain PII,
|
|
API keys, passwords, or tokens. Use redaction helpers for sensitive values.
|
|
patterns:
|
|
- pattern: zap.String("password", ...)
|
|
- pattern: zap.String("api_key", ...)
|
|
- pattern: zap.String("token", ...)
|
|
- pattern: zap.String("secret", ...)
|
|
- pattern: zap.String("Authorization", ...)
|
|
- pattern: zap.String("email", ...)
|
|
- pattern: zap.String("prompt", ...)
|
|
paths:
|
|
include:
|
|
- "internal/**/*.go"
|
|
- "cmd/**/*.go"
|
|
|
|
# ── Go: Hardcoded credentials ───────────────────────────────────────────────
|
|
|
|
- id: veylant-hardcoded-api-key
|
|
languages: [go]
|
|
severity: ERROR
|
|
message: >
|
|
Hardcoded string that looks like an API key or secret.
|
|
API keys must be loaded from environment variables or Vault — never hardcoded.
|
|
patterns:
|
|
- pattern: |
|
|
$KEY = "sk-..."
|
|
- pattern: |
|
|
APIKey: "sk-..."
|
|
paths:
|
|
include:
|
|
- "internal/**/*.go"
|
|
- "cmd/**/*.go"
|
|
|
|
# ── Go: Missing request size limit ─────────────────────────────────────────
|
|
|
|
- id: veylant-missing-max-bytes-reader
|
|
languages: [go]
|
|
severity: WARNING
|
|
message: >
|
|
HTTP request body decoded without http.MaxBytesReader().
|
|
A client can send an unbounded body, causing memory exhaustion.
|
|
Wrap r.Body with http.MaxBytesReader(w, r.Body, maxBytes) before decoding.
|
|
patterns:
|
|
- pattern: json.NewDecoder($R.Body).Decode(...)
|
|
paths:
|
|
include:
|
|
- "internal/**/*.go"
|
|
fix: |
|
|
r.Body = http.MaxBytesReader(w, r.Body, 1<<20) // 1 MiB
|
|
json.NewDecoder(r.Body).Decode(...)
|
|
|
|
# ── Python: Eval/exec of user input ─────────────────────────────────────────
|
|
|
|
- id: veylant-python-eval-user-input
|
|
languages: [python]
|
|
severity: ERROR
|
|
message: >
|
|
eval() or exec() called with a variable — potential code injection.
|
|
Never evaluate user-supplied data.
|
|
patterns:
|
|
- pattern: eval($X)
|
|
- pattern: exec($X)
|
|
paths:
|
|
include:
|
|
- "services/**/*.py"
|