shadow1ng/fscan · error

Target file not specified

Error message

Target file not specified

What it means

Scan of the crontask plugin requires config.PersistenceTargetFile — the path of the script to persist via cron. When it is empty, the plugin returns a failed Result with this error, because it cannot proceed without knowing which file to install into a cron job.

Source

Thrown at plugins/local/crontask.go:56

func (p *CronTaskPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *plugins.Result {
	config := session.Config
	var output strings.Builder

	if runtime.GOOS != "linux" {
		return &plugins.Result{
			Success: false,
			Output:  i18n.GetText("crontask_linux_only"),
			Error:   fmt.Errorf("%s", i18n.Tr("unsupported_platform", runtime.GOOS)),
		}
	}

	// 从config获取配置
	p.targetFile = config.PersistenceTargetFile
	if p.targetFile == "" {
		return &plugins.Result{
			Success: false,
			Output:  i18n.GetText("persistence_file_required"),
			Error:   fmt.Errorf("%s", i18n.GetText("target_file_not_specified")),
		}
	}

	// 检查目标文件是否存在
	if _, err := os.Stat(p.targetFile); os.IsNotExist(err) {
		return &plugins.Result{
			Success: false,
			Output:  i18n.Tr("target_file_not_exist", p.targetFile),
			Error:   err,
		}
	}

	// 检查crontab是否可用
	if _, err := exec.LookPath("crontab"); err != nil {
		return &plugins.Result{
			Success: false,
			Output:  i18n.GetText("crontab_unavailable"),
			Error:   err,

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Set Config.PersistenceTargetFile to the absolute path of the script to persist before calling Scan.
  2. Fix key-name mismatches in your config file/struct tags so the field deserializes.
  3. Check the field in the caller and skip or error out early with a clearer message.
  4. Require the corresponding CLI flag at startup if the value ultimately comes from argv.

Example fix

// before
cfg := plugins.Config{Name: "crontask"}
// after
cfg := plugins.Config{Name: "crontask", PersistenceTargetFile: "/opt/agent/agent.sh"}
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(cfg.PersistenceTargetFile) == "" {
    return errors.New("PersistenceTargetFile is required for crontask plugin")
}
if _, err := os.Stat(cfg.PersistenceTargetFile); err != nil {
    return fmt.Errorf("target file missing: %w", err)
}

Type guard

func crontaskConfigReady(cfg plugins.Config) bool {
    return strings.TrimSpace(cfg.PersistenceTargetFile) != ""
}

Try / catch

res := plugin.Scan(ctx, cfg)
if !res.Success && res.Error != nil && strings.Contains(res.Error.Error(), "Target file not specified") {
    return fmt.Errorf("crontask misconfigured: %w", res.Error)
}

Prevention

When it happens

Trigger: Calling Scan with a Config in which PersistenceTargetFile is "" (zero value / omitted in config file / CLI flag not passed).

Common situations: Config struct built programmatically with the field forgotten; YAML/JSON key typo (e.g. persist_target vs PersistenceTargetFile) so it never deserializes; running the plugin without the required CLI flag.

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/4d38c79e102f26aa. Report an issue: GitHub.