shadow1ng/fscan · error

local_pe_not_specified

Error message

local_pe_not_specified

What it means

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.

Source

Thrown at plugins/local/winstartup.go:31

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

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

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Assign the PE path to session.Config.WinPEFile before Scan.
  2. Wire the CLI/config option that populates WinPEFile and confirm it parses.
  3. Fail fast with a validation pass that rejects empty WinPEFile for local plugins.

Example fix

// before
session.Config.WinPEFile = ""
p.Scan(ctx, host, session) // local_pe_not_specified
// after
session.Config.WinPEFile = "C:\\cases\\case42\\sample.exe"
p.Scan(ctx, host, session)
Defensive patterns

Strategy: validation

Validate before calling

if session.Config == nil || session.Config.WinPEFile == "" {
    return errors.New("winstartup plugin: WinPEFile must be provided")
}

Type guard

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

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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/456713c745235093. Report an issue: GitHub.