shadow1ng/fscan · error
local_pe_not_specified
Error message
local_pe_not_specified
What it means
WinWMIPlugin.Scan requires a local PE file path in session.Config.WinPEFile to compare against WMI persistence artifacts (e.g. event consumer payloads). If the field is empty, the plugin returns this localized error before doing any WMI queries. It is the same required-input guard used by the other local Windows plugins.
Source
Thrown at plugins/local/winwmi.go:31
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
"github.com/shadow1ng/fscan/plugins"
)
type WinWMIPlugin struct {
plugins.BasePlugin
}
func NewWinWMIPlugin() *WinWMIPlugin {
return &WinWMIPlugin{
BasePlugin: plugins.NewBasePlugin("winwmi"),
}
}
func (p *WinWMIPlugin) 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))
filterName := fmt.Sprintf("SysMon_%s", baseName)
consumerName := fmt.Sprintf("SysExec_%s", baseName)
ps := fmt.Sprintf(`$ok = 0
try {
$f = ([wmiclass]"\\.\root\subscription:__EventFilter").CreateInstance()
$f.Name = "%s"; $f.EventNameSpace = "root\cimv2"; $f.QueryLanguage = "WQL"
$f.Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
$f.Put() | Out-Null; $ok++; Write-Output "[OK] EventFilter"
} catch { Write-Output "[FAIL] EventFilter: $_" }View on GitHub (pinned to 95cc12e753)
Solutions
- Set session.Config.WinPEFile to the target PE path before invoking Scan.
- Confirm the CLI/config layer actually populates Config.WinPEFile for the winwmi plugin.
- Add a pre-run config validation that reports which required field is missing per plugin.
Example fix
// before session.Config.WinPEFile = "" p.Scan(ctx, host, session) // local_pe_not_specified // after session.Config.WinPEFile = "C:\\samples\\wmipersist.dll" p.Scan(ctx, host, session)
Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(cfg.WinPEFile) == "" {
return errors.New("winwmi plugin requires Config.WinPEFile")
} Type guard
func winPEConfigured(c *common.Config) bool { return c != nil && strings.TrimSpace(c.WinPEFile) != "" } Prevention
- Set Config.WinPEFile whenever any win* local plugin is enabled.
- Validate plugin prerequisites centrally before Scan dispatch.
- Document the PE-file requirement alongside each plugin selection flag.
When it happens
Trigger: Calling Scan with Config.WinPEFile left empty — the PE-file option was not supplied via CLI, config file, or programmatic Config construction when the winwmi plugin runs.
Common situations: Forgetting the PE-file flag while running the WMI persistence check; a config file missing the win-pe-file field; constructing ScanSession in code/tests without initializing WinPEFile; a rename in the config struct that silently drops the value.
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
- local_pe_not_specified
- local_pe_not_specified
- local_pe_not_specified
- local_pe_not_specified
- local_pe_not_specified
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/e70ce037c4b482ab.
Report an issue: GitHub.