shadow1ng/fscan · error
local_pe_not_found
Error message
local_pe_not_found
What it means
WinStartupPlugin.Scan stats the configured PE path to confirm the local file exists before scanning Startup folders and Run keys for references to it. When os.Stat fails, it returns this localized 'local PE not found' error with the path embedded. No startup locations are inspected afterwards.
Source
Thrown at plugins/local/winstartup.go:34
)
type WinStartupPlugin struct {
plugins.BasePlugin
}
func NewWinStartupPlugin() *WinStartupPlugin {
return &WinStartupPlugin{
BasePlugin: plugins.NewBasePlugin("winstartup"),
}
}
func (p *WinStartupPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *plugins.Result {
pePath := session.Config.WinPEFile
if pePath == "" {
return &plugins.Result{Success: false, Error: fmt.Errorf("%s", i18n.GetText("local_pe_not_specified"))}
}
if _, err := os.Stat(pePath); err != nil {
return &plugins.Result{Success: false, Error: fmt.Errorf("%s", i18n.Tr("local_pe_not_found", pePath))}
}
absPath, _ := filepath.Abs(pePath)
fileName := filepath.Base(absPath)
locations := []struct {
name string
dir string
}{
{i18n.GetText("winstartup_user_folder"), filepath.Join(os.Getenv("APPDATA"), "Microsoft", "Windows", "Start Menu", "Programs", "Startup")},
{i18n.GetText("winstartup_common_folder"), filepath.Join(os.Getenv("ProgramData"), "Microsoft", "Windows", "Start Menu", "Programs", "Startup")},
}
var output strings.Builder
var successCount int
for _, loc := range locations {
target := filepath.Join(loc.dir, fileName)View on GitHub (pinned to 95cc12e753)
Solutions
- Check the file exists (Test-Path / os.Stat) and fix the configured path.
- Prefer absolute paths so behavior is CWD-independent.
- Restore the sample or update Config.WinPEFile to a valid copy.
- Verify permissions on the containing directory.
Example fix
// before
session.Config.WinPEFile = "sample.exe" // wrong CWD
// after
pe, _ := filepath.Abs("sample.exe")
if _, err := os.Stat(pe); err == nil {
session.Config.WinPEFile = pe
} Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(cfg.WinPEFile); err != nil {
return fmt.Errorf("startup sample %q unavailable: %w", cfg.WinPEFile, err)
} Try / catch
res := plugin.Scan(ctx, host, session)
if !res.Success {
log.Errorf("winstartup scan failed: %v", res.Error) // inspect for not-found
} Prevention
- Use absolute sample paths; recompute Abs at load time.
- Confirm the file exists after any config edit or tool move.
- Guard against AV quarantine by checking presence right before the scan.
When it happens
Trigger: Config.WinPEFile is set but unresolvable: the file does not exist, a relative path resolves against the wrong CWD, the sample was removed/quarantined, or the path is inaccessible.
Common situations: Typo in the sample path; moving the tool or running it from another directory breaks a relative path; AV deleted the sample; the drive/share hosting the sample is unavailable.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/275c609787fddb80.
Report an issue: GitHub.