crowdsecurity/crowdsec · error

unable to copy appsec-rule from

Error message

unable to copy appsec-rule from '%s' to '%s': %w

What it means

installAppsecRuleCustomFrom copies the located custom appsec-rule file into <RuntimePath>/appsec-rules/ and wraps Copy failures. The custom rule was found (os.Stat passed) but reading the source or writing the destination failed.

Solutions

  1. Verify the custom rule file is readable (permissions) and is a regular file, not a directory
  2. Re-check write permissions on <RuntimePath>/appsec-rules/ after the mkdir step
  3. Check disk space and re-run

Example fix

# before
-rw------- 1 root root 512 my-rule.yaml   # unreadable by test user
# after
chmod 644 my-rule.yaml && re-run
Defensive patterns

Strategy: validation

Validate before calling

src := filepath.Join(customPath, appsecrule)
fi, err := os.Stat(src)
if err != nil || fi.IsDir() || fi.Mode().Perm()&0o400 == 0 {
	return fmt.Errorf("custom appsec-rule %s missing, unreadable or a directory", src)
}

Prevention

When it happens

Trigger: installAppsecRuleCustom → installAppsecRuleCustomFrom when the Copy from customPath/appsecrule to the runtime destination fails: source unreadable, destination unwritable, source is a directory, or disk full.

Common situations: Custom rule file exists but with restrictive permissions; destination directory removed between MkdirAll and Copy by a concurrent process; the 'custom' entry is actually a directory; out-of-space CI runner.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/cf6f5e90a7d8a619. Report an issue: GitHub.

Appendix: source

Thrown at pkg/hubtest/appsecrule.go:66

func (t *HubTestItem) installAppsecRuleCustomFrom(appsecrule string, customPath string) (bool, error) {
	// we check if its a custom appsec-rule
	customAppsecRulePath := filepath.Join(customPath, appsecrule)
	if _, err := os.Stat(customAppsecRulePath); os.IsNotExist(err) {
		return false, nil
	}

	customAppsecRulePathSplit := strings.Split(customAppsecRulePath, "/")
	customAppsecRuleName := customAppsecRulePathSplit[len(customAppsecRulePathSplit)-1]

	itemTypeDirDest := fmt.Sprintf("%s/appsec-rules/", t.RuntimePath)
	if err := os.MkdirAll(itemTypeDirDest, os.ModePerm); err != nil {
		return false, fmt.Errorf("unable to create folder '%s': %w", itemTypeDirDest, err)
	}

	customAppsecRuleDest := fmt.Sprintf("%s/appsec-rules/%s", t.RuntimePath, customAppsecRuleName)
	if err := Copy(customAppsecRulePath, customAppsecRuleDest); err != nil {
		return false, fmt.Errorf("unable to copy appsec-rule from '%s' to '%s': %w", customAppsecRulePath, customAppsecRuleDest, err)
	}

	return true, nil
}

func (t *HubTestItem) installAppsecRuleCustom(appsecrule string) error {
	for _, customPath := range t.CustomItemsLocation {
		found, err := t.installAppsecRuleCustomFrom(appsecrule, customPath)
		if err != nil {
			return err
		}

		if found {
			return nil
		}
	}

	return fmt.Errorf("couldn't find custom appsec-rule '%s' in the following location: %+v", appsecrule, t.CustomItemsLocation)

View on GitHub (pinned to 909b515798)