shadow1ng/fscan · error

local_pe_not_specified

Error message

local_pe_not_specified

What it means

The WinRegistryPlugin.Scan method requires a local Windows PE file path via session.Config.WinPEFile to analyze registry persistence for that binary. When WinPEFile is the empty string, the plugin aborts before doing any work and returns this localized error. It is a pre-flight configuration check, not a runtime failure.

Source

Thrown at plugins/local/winregistry.go:31

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

type WinRegistryPlugin struct {
	plugins.BasePlugin
}

func NewWinRegistryPlugin() *WinRegistryPlugin {
	return &WinRegistryPlugin{
		BasePlugin: plugins.NewBasePlugin("winregistry"),
	}
}

func (p *WinRegistryPlugin) 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)
	baseName := strings.TrimSuffix(filepath.Base(absPath), filepath.Ext(absPath))

	entries := []struct {
		key  string
		name string
		desc string
	}{
		{`HKCU\Software\Microsoft\Windows\CurrentVersion\Run`, fmt.Sprintf("WindowsUpdate_%s", baseName), i18n.GetText("winregistry_current_user_run")},
		{`HKLM\Software\Microsoft\Windows\CurrentVersion\Run`, fmt.Sprintf("SystemUpdate_%s", baseName), i18n.GetText("winregistry_local_machine_run")},
		{`HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce`, fmt.Sprintf("SetupComplete_%s", baseName), i18n.GetText("winregistry_current_user_runonce")},
	}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Set session.Config.WinPEFile to the absolute or relative path of the local PE (.exe/.dll) before invoking Scan.
  2. If invoking via CLI, pass the PE file flag so the config loader populates Config.WinPEFile.
  3. Validate the config before running the scan: reject sessions with empty WinPEFile early with a clear user-facing message.

Example fix

// before
session.Config.WinPEFile = ""
plugin.Scan(ctx, host, session) // -> local_pe_not_specified
// after
session.Config.WinPEFile = "C:\\samples\\implant.dll"
plugin.Scan(ctx, host, session)
Defensive patterns

Strategy: validation

Validate before calling

if cfg == nil || cfg.WinPEFile == "" {
    return fmt.Errorf("winregistry plugin requires a PE file path (set Config.WinPEFile)")
}

Type guard

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

Prevention

When it happens

Trigger: Calling Scan (directly or via the plugin runner) with a common.ScanSession whose Config.WinPEFile was never set (empty string). Typically happens when the user did not pass the PE-file option on the CLI/API so Config.WinPEFile defaults to "".

Common situations: Running the winregistry local plugin without the corresponding flag (e.g. forgetting the -f/--pe-file style argument); constructing ScanSession programmatically and leaving WinPEFile at its zero value; a config file that omits the win-pe-file key.

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/53832325841e5dd5. Report an issue: GitHub.