shadow1ng/fscan · error
local_pe_not_specified
Error message
local_pe_not_specified
What it means
WinBITSPlugin.Scan requires a local PE file path from session.Config.WinPEFile because the BITS-based persistence technique uploads/executes a local executable. When the config field is empty, Scan immediately returns a failed Result with the localized message for key "local_pe_not_specified". It is a configuration-validation failure, not a runtime fault.
Source
Thrown at plugins/local/winbits.go:29
"strings"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
"github.com/shadow1ng/fscan/plugins"
)
type WinBITSPlugin struct {
plugins.BasePlugin
}
func NewWinBITSPlugin() *WinBITSPlugin {
return &WinBITSPlugin{BasePlugin: plugins.NewBasePlugin("winbits")}
}
func (p *WinBITSPlugin) 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))
jobName := fmt.Sprintf("WindowsUpdate_%s", baseName)
var output strings.Builder
// 创建任务并提取 GUID
out, err := exec.Command("bitsadmin", "/create", "/download", jobName).CombinedOutput()
if err != nil {
output.WriteString(i18n.Tr("winbits_create_task_failed", strings.TrimSpace(string(out))) + "\n")
return &plugins.Result{Success: false, Output: output.String()}
}
View on GitHub (pinned to 95cc12e753)
Solutions
- Set the WinPEFile value in the scan config (the CLI flag/config key that populates session.Config.WinPEFile) before enabling winbits.
- Verify the config file/profile actually contains that key and that it's under the correct section.
- If running programmatically, populate session.Config.WinPEFile with an absolute path to a valid PE before calling Scan.
- Check the tool's current usage docs in case the option name changed in your version.
Example fix
// before session.Config.WinPEFile == "" // -> local_pe_not_specified // after (programmatic) session.Config.WinPEFile = "C:\\tools\\payload.exe" // CLI equivalent: // <tool> --winpe-file C:\tools\payload.exe --plugin winbits
Defensive patterns
Strategy: validation
Validate before calling
// Validate config before invoking the plugin
if session.Config.WinPEFile == "" {
return errors.New("winbits requires --winpe-file / session.Config.WinPEFile to be set")
} Try / catch
result := plugin.Scan(ctx, host, session)
if result != nil && !result.Success && result.Error.Error() == i18n.GetText("local_pe_not_specified") {
// print usage hint: supply the local PE path option
} Prevention
- Always pass the PE path flag when enabling winbits/winifeo/winlogon plugins.
- Validate required config fields at startup with a preflight check.
- After tool upgrades, re-diff your config keys against the current flag names.
When it happens
Trigger: Scan is invoked while session.Config.WinPEFile == "" — i.e., the winbits plugin was enabled without setting the local PE file option.
Common situations: User enabled the winbits module but forgot the corresponding flag/config key (e.g., --winpe-file), config file loaded from the wrong profile, or the field name changed between tool versions so the old key is silently ignored.
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/5d4fc96022073d76.
Report an issue: GitHub.