{"record":{"id":"456713c745235093","repo":"shadow1ng/fscan","slug":"local-pe-not-specified-456713","errorCode":null,"errorMessage":"local_pe_not_specified","messagePattern":"local_pe_not_specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/local/winstartup.go","lineNumber":31,"sourceCode":"\t\"github.com/shadow1ng/fscan/common\"\n\t\"github.com/shadow1ng/fscan/common/i18n\"\n\t\"github.com/shadow1ng/fscan/plugins\"\n)\n\ntype WinStartupPlugin struct {\n\tplugins.BasePlugin\n}\n\nfunc NewWinStartupPlugin() *WinStartupPlugin {\n\treturn &WinStartupPlugin{\n\t\tBasePlugin: plugins.NewBasePlugin(\"winstartup\"),\n\t}\n}\n\nfunc (p *WinStartupPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *plugins.Result {\n\tpePath := session.Config.WinPEFile\n\tif pePath == \"\" {\n\t\treturn &plugins.Result{Success: false, Error: fmt.Errorf(\"%s\", i18n.GetText(\"local_pe_not_specified\"))}\n\t}\n\tif _, err := os.Stat(pePath); err != nil {\n\t\treturn &plugins.Result{Success: false, Error: fmt.Errorf(\"%s\", i18n.Tr(\"local_pe_not_found\", pePath))}\n\t}\n\n\tabsPath, _ := filepath.Abs(pePath)\n\tfileName := filepath.Base(absPath)\n\n\tlocations := []struct {\n\t\tname string\n\t\tdir  string\n\t}{\n\t\t{i18n.GetText(\"winstartup_user_folder\"), filepath.Join(os.Getenv(\"APPDATA\"), \"Microsoft\", \"Windows\", \"Start Menu\", \"Programs\", \"Startup\")},\n\t\t{i18n.GetText(\"winstartup_common_folder\"), filepath.Join(os.Getenv(\"ProgramData\"), \"Microsoft\", \"Windows\", \"Start Menu\", \"Programs\", \"Startup\")},\n\t}\n\n\tvar output strings.Builder\n\tvar successCount int","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/local/winstartup.go#L13-L49","documentation":"WinStartupPlugin.Scan expects a local PE file path in session.Config.WinPEFile to match against Startup-folder entries and Run-key values. An empty WinPEFile causes the plugin to return this localized error immediately, before any filesystem or registry inspection. The PE file is the required subject of the persistence check.","triggerScenarios":"Scan invoked with a ScanSession whose Config.WinPEFile is \"\" — the PE-file option was never provided through the CLI, config file, or programmatic Config construction.","commonSituations":"Omitting the PE-file flag when running the startup-persistence plugin; loading a stale/partial config that lacks the win-pe-file key; building Config in tests without setting the field.","solutions":["Assign the PE path to session.Config.WinPEFile before Scan.","Wire the CLI/config option that populates WinPEFile and confirm it parses.","Fail fast with a validation pass that rejects empty WinPEFile for local plugins."],"exampleFix":"// before\nsession.Config.WinPEFile = \"\"\np.Scan(ctx, host, session) // local_pe_not_specified\n// after\nsession.Config.WinPEFile = \"C:\\\\cases\\\\case42\\\\sample.exe\"\np.Scan(ctx, host, session)","handlingStrategy":"validation","validationCode":"if session.Config == nil || session.Config.WinPEFile == \"\" {\n    return errors.New(\"winstartup plugin: WinPEFile must be provided\")\n}","typeGuard":"func peProvided(c *common.Config) bool { return c != nil && c.WinPEFile != \"\" }","tryCatchPattern":null,"preventionTips":["Feed all local plugins from a single validated Config builder.","Reject empty required fields at CLI/config parse time.","Cover the empty-WinPEFile path in unit tests."],"tags":["configuration","windows","startup","pe-file"],"backgroundTag":"missing-required-config-field","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"}