{"record":{"id":"cdacd6af26dae2b4","repo":"projectdiscovery/nuclei","slug":"post-auth-read-s-got-s","errorCode":null,"errorMessage":"post-auth read: %s (got: %s)","messagePattern":"post-auth read: (.+?) \\(got: (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/utils/telnetmini/telnet.go","lineNumber":230,"sourceCode":"\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) {\n\t\treturn fmt.Errorf(\"post-auth read: %s (got: %s)\", preview(got, 200), err)\n\t}\n\tlow := strings.ToLower(match)\n\tfor _, fb := range c.FailBanners {\n\t\tif low == strings.ToLower(fb) {\n\t\t\treturn errors.New(\"authentication failed\")\n\t\t}\n\t}\n\t// success (matched a shell prompt or timed out without explicit failure)\n\treturn nil\n}\n\n// Exec sends a command followed by CRLF and returns text captured until one of\n// the provided prompts appears (typically your shell prompt). Provide a deadline via ctx.\nfunc (c *Client) Exec(ctx context.Context, command string, until ...string) (string, error) {\n\tif err := c.writeLine(ctx, command); err != nil {\n\t\treturn \"\", err\n\t}\n\t_, out, err := c.readUntil(ctx, until...)","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/utils/telnetmini/telnet.go#L212-L248","documentation":"The post-authentication read returned an error other than context.DeadlineExceeded. Auth deliberately tolerates a timeout after sending credentials (silence is treated as success), so this error fires only for real I/O failures — connection reset, EOF, or a canceled context — while scanning for FailBanners vs ShellPrompts. Note the message is formatted with %s (preview of bytes received) rather than wrapping the error with %w.","triggerScenarios":"The remote end drops the TCP connection right after credentials are submitted (banner-based auth rejection, service crash, PAM failure without a banner), or ctx is canceled (context.Canceled, not DeadlineExceeded) during the final read.","commonSituations":"Devices that reset the socket instead of printing a failure banner on bad credentials; aggressive per-attempt ctx cancellation from a scanner supervisor; TLS-wrapped services mistakenly spoken to as plain telnet.","solutions":["Treat a reset-after-credentials as an authentication failure or target-level defect: verify credentials manually (e.g. with a telnet client) to see whether the socket reset is the server's reject behavior.","Confirm you are speaking plain telnet and not TLS/SSH — a TLS or SSH greeting will never match the configured prompts and can cause an abnormal teardown.","If ctx.Canceled is being produced by your own supervisor, avoid canceling Auth mid-flight or map it to a clean abort path.","Extend the ctx budget so slow post-login banner output is not misread as failure."],"exampleFix":"// before\nerr := client.Auth(ctx, user, pass)\n\n// after\nerr := client.Auth(ctx, user, pass)\nif err != nil && strings.Contains(err.Error(), \"post-auth read\") {\n    // socket died scanning for fail/shell banners; count as failed auth for this host\n    log.Printf(\"host %s reset after auth: %v\", host, err)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isPostAuthReadErr(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"post-auth read:\")\n}","tryCatchPattern":"err := client.Auth(ctx, user, pass)\nif isPostAuthReadErr(err) {\n    // transport died scanning fail/shell banners: treat as auth failure for this host\n    log.Printf(\"%s: post-auth drop: %v\", host, err)\n}","preventionTips":["Remember timeouts are tolerated here — only real I/O errors surface, so do not 'fix' by raising the deadline alone.","Verify credentials against the same host manually to learn whether reset == reject.","Do not unwrap with errors.Is/%w — the message embeds err via %s, so match on prefix."],"tags":["telnet","network","authentication","io-error"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}