{"record":{"id":"49c37df6c1bb38b2","repo":"projectdiscovery/nuclei","slug":"waiting-for-login-username-prompt-w","errorCode":null,"errorMessage":"waiting for login/username prompt: %w","messagePattern":"waiting for login/username prompt: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/utils/telnetmini/telnet.go","lineNumber":211,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ti += 2 // Skip command and option\n\t\t\t}\n\t\t}\n\t}\n\n\treturn supportsEncryption, options\n}\n\n// Auth performs a minimal Telnet username/password interaction.\n// It waits for a username/login prompt, sends username, waits for a password prompt,\n// sends password, and then looks for fail banners or shell prompts.\n// A timeout should be enforced via ctx.\nfunc (c *Client) Auth(ctx context.Context, username, password string) error {\n\t// Wait for username/login prompt\n\tif _, _, err := c.readUntil(ctx, c.UserPrompts...); err != nil {\n\t\treturn fmt.Errorf(\"waiting for login/username prompt: %w\", err)\n\t}\n\tif err := c.writeLine(ctx, username); err != nil {\n\t\treturn fmt.Errorf(\"sending username: %w\", err)\n\t}\n\n\t// Wait for password prompt\n\tif _, _, err := c.readUntil(ctx, c.PasswordPrompts...); err != nil {\n\t\treturn fmt.Errorf(\"waiting for password prompt: %w\", err)\n\t}\n\tif err := c.writeLine(ctx, password); err != nil {\n\t\treturn fmt.Errorf(\"sending password: %w\", err)\n\t}\n\n\t// Post-auth: look quickly for explicit failure, else accept shell prompt / silence.\n\tmatch, got, err := c.readUntil(ctx,\n\t\tappend(append([]string{}, c.FailBanners...), c.ShellPrompts...)...,\n\t)\n\tif err != nil && !errors.Is(err, context.DeadlineExceeded) {","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/utils/telnetmini/telnet.go#L193-L229","documentation":"Client.Auth (telnet.go:208) drives a minimal login dialog: it first waits for any of the configured UserPrompts via readUntil. Timeout (context deadline → net.Error timeout → context.DeadlineExceeded) or a read error returns 'waiting for login/username prompt: %w'. Note readUntil enforces the ctx deadline and compares lowercased needles, but only the prompts in c.UserPrompts are recognized.","triggerScenarios":"The service never prints a prompt matching c.UserPrompts within the ctx deadline: a non-login service on the port (raw TCP banner, embedded device shell that needs a keypress), prompts with different wording (e.g. 'Login:', 'Account:', 'Username->' when defaults only cover common variants), slow/PAUSE-before-prompt servers, or the server closing the connection (read error instead of timeout).","commonSituations":"Telnet brute-force/info templates run against mixed fleets where many port-23 services are not classic Unix login prompts; ctx deadline set too tight (sub-second) for WAN latency; default prompt lists not covering the target's exact banner string.","solutions":["Increase the ctx deadline passed to Auth — WAN targets commonly need 10-30s to reach the prompt","Widen c.UserPrompts to match the actual banner (capture it with `telnet target` or a raw read first, then add the exact string, case-insensitively)","Confirm the port actually speaks interactive telnet login before calling Auth; skip non-login services","Distinguish outcomes in the wrapped error: DeadlineExceeded = no prompt in time; EOF/reset = server dropped — different remediations"],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 3*time.Second)\nerr := client.Auth(ctx, user, pass)\n\n// after\nclient.UserPrompts = append(client.UserPrompts, \"account:\", \"username->\")\nctx, cancel := context.WithTimeout(ctx, 20*time.Second)\nerr := client.Auth(ctx, user, pass)","handlingStrategy":"retry","validationCode":"// Capture the banner once and extend prompts to match before authing:\nclient.UserPrompts = append(client.UserPrompts, \"login:\", \"username:\", \"account:\", \"user->\")\nctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)","typeGuard":"func hasPrompt(banner string, prompts []string) bool {\n    low := strings.ToLower(banner)\n    for _, p := range prompts {\n        if strings.Contains(low, p) { return true }\n    }\n    return false\n}","tryCatchPattern":"err := client.Auth(ctx, user, pass)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) || strings.Contains(err.Error(), \"waiting for login/username prompt\") {\n        // retry once with a longer deadline and wider prompt set, else classify as non-login service\n        return retryAuthWithLongerDeadline()\n    }\n    return err\n}","preventionTips":["Set generous ctx deadlines (10-30s) for WAN telnet targets","Read the banner first and configure UserPrompts to its exact wording (match is case-insensitive)","Verify the port is an interactive login service before attempting auth","Treat prompt-timeout as 'service not login telnet' — a classification, not a crash"],"tags":["telnet","auth","timeout","prompt-matching","network-protocol"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}