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

  1. Confirm the file exists at the configured path and fix the path in Config.WinPEFile.
  2. Switch to an absolute path independent of CWD.
  3. Check filesystem/AV interference and restore or whitelist the file.
  4. 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

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.