shadow1ng/fscan · error
%s
Error message
%s
What it means
The FTP plugin's Scan returns a ScanResult whose Error field carries the i18n message for 'no credentials available' when GenerateCredentials("ftp", config) yields an empty list. Scan aborts before any connection is attempted because there is nothing to test. This is a configuration/input problem, not a network failure.
Source
Thrown at plugins/services/ftp.go:47
config := session.Config
state := session.State
if config.DisableBrute {
return p.identifyService(info, session)
}
target := info.Target()
// 优先检测匿名访问
if result := p.testAnonymousAccess(ctx, info, session); result != nil && result.Success {
return result
}
credentials := GenerateCredentials("ftp", config)
if len(credentials) == 0 {
return &ScanResult{
Success: false,
Service: "ftp",
Error: fmt.Errorf("%s", i18n.GetText("service_no_credentials")),
}
}
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
testConfig := DefaultConcurrentTestConfigWithTarget(config, info)
result := TestCredentialsConcurrently(ctx, credentials, authFn, "ftp", testConfig)
if result.Success {
// 成功后重新连接获取文件列表
fileList := p.getFileListAfterAuth(info, result.Username, result.Password, config, state)
var output strings.Builder
fmt.Fprintf(&output, "FTP %s %s:%s", target, result.Username, result.Password)
if len(fileList) > 0 {
for _, file := range fileList {
fmt.Fprintf(&output, "\n [->] %s", file)
}View on GitHub (pinned to 95cc12e753)
Solutions
- Provide at least one username and password in the FTP scan config
- Enable built-in default credential lists if you intended dictionary brute force
- Validate the config before invoking Scan and fail fast with a clear message
- Check GenerateCredentials("ftp", config) unit behavior for your config shape
Example fix
// before
credentials := GenerateCredentials("ftp", config) // may be empty
// after
credentials := GenerateCredentials("ftp", config)
if len(credentials) == 0 {
return nil, fmt.Errorf("ftp scan requires at least one username/password pair in config")
} Defensive patterns
Strategy: validation
Validate before calling
cfg := loadFTPConfig(config)
if len(cfg.Usernames) == 0 || len(cfg.Passwords) == 0 {
return fmt.Errorf("ftp config must contain at least one username and password")
} Type guard
func hasCredentials(c map[string][]string) bool {
return len(c["usernames"]) > 0 && len(c["passwords"]) > 0
} Try / catch
res := plugin.Scan(info, config, state)
if res != nil && res.Error != nil && strings.Contains(res.Error.Error(), i18n.GetText("service_no_credentials")) {
log.Println("ftp: add usernames/passwords to the scan config and rerun")
return
} Prevention
- Validate credential lists are non-empty before invoking Scan
- Enable built-in default lists when custom lists are omitted
- Check config key spelling so GenerateCredentials finds the lists
- Fail fast with a config lint step before starting scans
When it happens
Trigger: Scan (public) on the FTP plugin: credentials := GenerateCredentials("ftp", config) returns len 0 — e.g. empty or missing user/pass lists in the config with no defaults enabled.
Common situations: Config supplied with no username or password wordlists; typo'd config keys so the credential generator finds nothing; user intentionally restricted to custom credentials but passed an empty list.
Related errors
- %s
- i18n.GetText("service_no_credentials")
- service_no_credentials
- service_no_credentials
- service_no_credentials
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/80feab9855209a17.
Report an issue: GitHub.