Skip to content

VNX-GO-029: Hardcoded weak or default password

Detects a well-known weak or default password (admin, password, 123456, changeme, postgres...) written into Go source as a credential: a password variable or field, a setter or SetBasicAuth, connection-string userinfo, or an env/flag/viper default.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-GO-029
Severity High
SARIF level error
Kind sast
Languages Go
CWE CWE-798
CAPEC CAPEC-256
ATT&CK T1078.003
CWSS vector CWSS:1.0/TI:H/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H
Tags hardcoded-password weak-password credentials
Source internal/sast/rules/vnx-go-029.rego

Overview

This rule flags Go source code where variables with names like password, passwd, pass, or pwd are assigned well-known weak or default string values such as "admin", "password", "123456", "secret", or similar. Hardcoded credentials, whether used as defaults in configuration, embedded in initialization code, or left over from development, are a direct path to unauthorized access and are trivially found by static analysis, binary inspection, or simple string searches. This maps to CWE-798: Use of Hardcoded Credentials.

Default and hardcoded passwords are among the most frequently exploited weaknesses in deployed software. IoT devices, network appliances, and web applications with factory-default credentials have been the root cause of major botnets and infrastructure attacks. Even when intended only for development, such credentials frequently survive into production environments through misconfigured deployments or operator error.

Why This Matters

Attackers routinely scan for services using default credentials as one of the first steps in reconnaissance. Tools like Shodan, Masscan, and Metasploit modules automate this at internet scale. A single default password left in a deployed service can grant full administrative access without any exploitation of other vulnerabilities. MITRE ATT&CK technique T1078.003 (Valid Accounts: Local Accounts) covers the use of default or hardcoded credentials to gain initial access.

Beyond active exploitation, hardcoded credentials embedded in source code become a persistent liability: they are often committed to public repositories, included in packaged binaries, and copied between projects. Rotating them typically requires a code change and redeployment, meaning they persist in production for far longer than dynamically managed secrets.

What Gets Flagged

A common default password used as a credential.

// FLAGGED: password-named constant, map key and struct field
const defaultPassword = "admin123"
var creds = map[string]string{"username": "admin", "password": "admin"}
cfg := DB{User: "sa", Password: "Passw0rd"}

// FLAGGED: user:password in a connection string
sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/shop")

// FLAGGED: a weak default for a password flag
dbPass := flag.String("db-password", "password", "database password")

Not flagged: field-name constants (PasswordField = "password"), empty defaults, environment lookups and ${VAR} placeholders, deny-lists of common passwords, strong literals (other rules cover hard-coded secrets), test files.

Remediation

  1. Load credentials from environment variables at runtime, never at compile time:

    // SAFE: read from environment
    import "os"
    
    func getDBPassword() string {
        pw := os.Getenv("DB_PASSWORD")
        if pw == "" {
            panic("DB_PASSWORD environment variable is not set")
        }
        return pw
    }
  2. Use a secrets manager such as HashiCorp Vault, AWS Secrets Manager, or GCP Secret Manager for production deployments:

    // SAFE: retrieve from secrets manager at startup
    func loadSecrets(ctx context.Context, client *secretmanager.Client) (string, error) {
        name := "projects/my-project/secrets/db-password/versions/latest"
        result, err := client.AccessSecretVersion(ctx,
            &secretmanagerpb.AccessSecretVersionRequest{Name: name})
        if err != nil {
            return "", err
        }
        return string(result.Payload.Data), nil
    }
  3. For tests and local development, use randomly generated credentials created at setup time, never check in real or weak passwords:

    // SAFE: generate a random password for test setup
    import (
        "crypto/rand"
        "encoding/base64"
    )
    
    func randomPassword(n int) string {
        b := make([]byte, n)
        rand.Read(b)
        return base64.URLEncoding.EncodeToString(b)[:n]
    }
  4. Audit your repository history. If a weak credential was ever committed, rotate it immediately and consider the affected system fully compromised. Use tools like git-secrets or truffleHog to prevent future commits containing credentials.

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-go-029
// nosec vnx-go-029

Or record an ignore rule: vulnetix ignore add --rule vnx-go-029 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-go-029.rego, cli/internal/sast/docs/vnx-go-029.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.