shadow1ng/fscan · error

local_pe_not_specified

Error message

local_pe_not_specified

What it means

WinSchTaskPlugin.Scan needs a local PE file path in session.Config.WinPEFile to match scheduled-task actions against. If WinPEFile is empty, the plugin returns this localized error before checking the file or enumerating tasks. Like the other local plugins, it is a mandatory-input guard.

Source

Thrown at plugins/local/winschtask.go:31

	"github.com/shadow1ng/fscan/common"
	"github.com/shadow1ng/fscan/common/i18n"
	"github.com/shadow1ng/fscan/plugins"
)

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"},

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Populate session.Config.WinPEFile with the target PE path before calling Scan.
  2. Ensure the CLI flag or config key that feeds Config.WinPEFile is actually being parsed.
  3. Add an early validation step that fails fast with a clear message when WinPEFile is empty.

Example fix

// before
session := &common.ScanSession{Config: &common.Config{}} // WinPEFile empty
p.Scan(ctx, host, session)
// after
session := &common.ScanSession{Config: &common.Config{WinPEFile: "C:\\tmp\\agent.exe"}}
p.Scan(ctx, host, session)
Defensive patterns

Strategy: validation

Validate before calling

if session.Config == nil || session.Config.WinPEFile == "" {
    return errors.New("winschtask plugin: Config.WinPEFile is required")
}

Type guard

func peConfigured(c *common.Config) bool { return c != nil && c.WinPEFile != "" }

Prevention

When it happens

Trigger: Invoking Scan with a ScanSession whose Config.WinPEFile was left unset/empty, e.g. the user did not supply the PE file option when selecting the winschtask plugin.

Common situations: Forgetting the PE-file CLI flag while running the scheduled-task persistence check; building the config programmatically without setting the field; a refactor renamed the config key so the loader no longer populates WinPEFile.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/247831d22b9ee7af. Report an issue: GitHub.