{"record":{"id":"01a8cbba58a7fc6d","repo":"shadow1ng/fscan","slug":"service-no-credentials-01a8cb","errorCode":null,"errorMessage":"service_no_credentials","messagePattern":"service_no_credentials","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"plugins/services/mysql.go","lineNumber":54,"sourceCode":"func NewMySQLPlugin() *MySQLPlugin {\n\treturn &MySQLPlugin{\n\t\tBasePlugin: plugins.NewBasePlugin(\"mysql\"),\n\t}\n}\n\nfunc (p *MySQLPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {\n\tconfig := session.Config\n\tstate := session.State\n\tif config.DisableBrute {\n\t\treturn p.identifyService(ctx, info, session)\n\t}\n\n\tcredentials := GenerateCredentials(\"mysql\", config)\n\tif len(credentials) == 0 {\n\t\treturn &ScanResult{\n\t\t\tSuccess: false,\n\t\t\tService: \"mysql\",\n\t\t\tError:   fmt.Errorf(\"%s\", i18n.GetText(\"service_no_credentials\")),\n\t\t}\n\t}\n\n\ttarget := info.Target()\n\n\t// 使用公共框架进行并发凭据测试\n\tauthFn := p.createAuthFunc(info, config, state)\n\ttestConfig := DefaultConcurrentTestConfigWithTarget(config, info)\n\n\tresult := TestCredentialsConcurrently(ctx, credentials, authFn, \"mysql\", testConfig)\n\n\tif result.Success {\n\t\tsession.LogVuln(i18n.Tr(\"mysql_credential\", target, result.Username, result.Password))\n\t}\n\n\treturn result\n}\n","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/mysql.go#L36-L72","documentation":"The MySQL plugin's Scan first generates the credential list via GenerateCredentials(\"mysql\", config). If the combined config (custom credentials plus built-in defaults) yields an empty list, there is nothing to test, so Scan returns a failed ScanResult carrying the localized 'service_no_credentials' message.","triggerScenarios":"Calling Scan with a Config whose credential sources produce zero entries — e.g. a user-supplied credential file or config section for 'mysql' that is empty, and defaults disabled via brute-force settings.","commonSituations":"Users pass a custom usernames/passwords file that is empty or has the wrong path/format; config disables built-in wordlists while providing no replacements; typo in the config keys so GenerateCredentials reads nothing.","solutions":["Populate the credential config for mysql (usernames/passwords lists or a valid dictionary file).","Check the credential file path and encoding — an empty or unreadable file yields zero credentials.","Re-enable built-in default credential lists if you intended to rely on them.","Log the generated credential count at startup to catch empty lists before scanning."],"exampleFix":"// before\n# config: mysql users/passwords sections empty, defaults off\n// after\nmysql:\n  users: [\"root\", \"admin\"]\n  passwords: [\"123456\", \"password\"]","handlingStrategy":"validation","validationCode":"creds := GenerateCredentials(\"mysql\", config)\nif len(creds) == 0 {\n    return fmt.Errorf(\"no mysql credentials configured: populate users/passwords or enable defaults\")\n}","typeGuard":null,"tryCatchPattern":"result := plugin.Scan(ctx, info, session)\nif result.Error != nil && strings.Contains(result.Error.Error(), \"service_no_credentials\") {\n    // surface a config warning to the user instead of a scan failure\n}","preventionTips":["Always provide at least one username/password pair for mysql scans.","Validate credential file paths and non-empty content at config load.","Log the credential count before starting a scan.","Don't disable built-in defaults without supplying replacements."],"tags":["mysql","credentials","config","scan"],"backgroundTag":"missing-credentials","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}