shadow1ng/fscan · error
local_pe_not_found
Error message
local_pe_not_found
What it means
WinSchTaskPlugin.Scan verifies that the configured local PE file exists by calling os.Stat on session.Config.WinPEFile. When Stat returns an error, the plugin aborts with this localized 'local PE not found' message containing the path. No scheduled-task comparison is performed.
Source
Thrown at plugins/local/winschtask.go:34
)
type WinSchTaskPlugin struct {
plugins.BasePlugin
}
func NewWinSchTaskPlugin() *WinSchTaskPlugin {
return &WinSchTaskPlugin{
BasePlugin: plugins.NewBasePlugin("winschtask"),
}
}
func (p *WinSchTaskPlugin) 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))}
}
ext := strings.ToLower(filepath.Ext(pePath))
if ext != ".exe" && ext != ".dll" {
return &plugins.Result{Success: false, Error: fmt.Errorf("%s", i18n.Tr("local_invalid_pe", pePath))}
}
absPath, _ := filepath.Abs(pePath)
baseName := strings.TrimSuffix(filepath.Base(absPath), filepath.Ext(absPath))
tasks := []struct {
name string
schedule string
modifier string
}{
{fmt.Sprintf("WindowsUpdateCheck_%s", baseName), "DAILY", "1"},
{fmt.Sprintf("SystemSecurityScan_%s", baseName), "ONLOGON", ""},
{fmt.Sprintf("MaintenanceTask_%s", baseName), "ONSTART", ""},
{fmt.Sprintf("BackgroundService_%s", baseName), "HOURLY", "2"},View on GitHub (pinned to 95cc12e753)
Solutions
- Confirm the file exists at the configured path and fix the path in Config.WinPEFile.
- Switch to an absolute path independent of CWD.
- Check filesystem/AV interference and restore or whitelist the file.
- Verify drive/UNC availability if the path is on a share.
Example fix
// before
session.Config.WinPEFile = "C:\\samples\\agent.exe" // file was quarantined
// after
if _, err := os.Stat(session.Config.WinPEFile); err != nil {
log.Fatalf("PE file missing: %v", err)
}
p.Scan(ctx, host, session) Defensive patterns
Strategy: validation
Validate before calling
if info, err := os.Stat(cfg.WinPEFile); err != nil || info.IsDir() {
return fmt.Errorf("invalid PE path %q", cfg.WinPEFile)
} Try / catch
res := plugin.Scan(ctx, host, session)
if !res.Success && strings.Contains(res.Error.Error(), "not found") {
log.Warnf("skipping schtask check: %v", res.Error)
} Prevention
- Verify the sample still exists at scan time (AV may remove it).
- Resolve relative paths to absolute at config-load time.
- Prefer copying the sample to a tool-controlled temp dir with known permissions.
When it happens
Trigger: Config.WinPEFile is set but the file cannot be stat'ed: non-existent path, wrong relative base directory, deleted sample, or a permission/filesystem error on the path.
Common situations: Path typo; running from a different working directory than the one where the PE file resides; antivirus quarantined or removed the sample between configuration and scan; UNC/network path 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/238de75037004159.
Report an issue: GitHub.