projectdiscovery/nuclei · error

include directive preprocessing is disabled

Error message

include directive preprocessing is disabled

What it means

The YAML preprocessor (pkg/utils/yaml/preprocess.go:52) expands `!include:path` directives only when pkg/utils/yaml.StrictSyntax is false. The nuclei binary sets yaml.StrictSyntax = !options.NoStrictSyntax (internal/runner/runner.go:189), so strict mode is ON by default and any template containing an include directive is rejected before expansion — even when the include path is valid. The -nss/-no-strict-syntax flag (cmd/nuclei/main.go:298) is the intended opt-out.

Source

Thrown at pkg/utils/yaml/preprocess.go:53

var TemplateBaseDirProvider func() string

// PreProcess all include directives. templatePath is the path of the template
// currently being processed and is used to resolve relative include paths and
// to validate them.
func PreProcess(data []byte, templatePath string) ([]byte, error) {
	return preProcess(data, templatePath, make(map[string]struct{}), 0)
}

func preProcess(data []byte, templatePath string, includeStack map[string]struct{}, depth int) ([]byte, error) {
	// find all matches like !include:path\n
	// FindAllSubmatchIndex is used (instead of FindAllSubmatch) so each match
	// carries its own offset; relying on bytes.Index would always resolve to the
	// first occurrence and incorrectly pad repeated include directives.
	importMatches := reImportsPattern.FindAllSubmatchIndex(data, -1)
	hasImportDirectives := len(importMatches) > 0

	if hasImportDirectives && StrictSyntax {
		return data, errors.New("include directive preprocessing is disabled")
	}

	if !hasImportDirectives {
		return data, nil
	}

	// Expand each directive in place using its own offset. A strings.Replacer
	// cannot be used here because it collapses identical directive lines onto a
	// single replacement, which would reuse the first occurrence's indentation
	// for every later occurrence.
	var out bytes.Buffer
	lastEnd := 0

	for _, match := range importMatches {
		matchStart, matchEnd := match[0], match[1]

		var includeFileName string
		if len(match) > 3 && match[2] >= 0 {

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Run nuclei with `-nss` / `-no-strict-syntax` so include directives preprocess
  2. Inline the included file's content into the template to stay strict-compliant
  3. SDK users: leave yaml.StrictSyntax false (or set parser.NoStrictSyntax) for templates using includes
  4. Audit templates for includes: `grep -rn '!include:' templates/`

Example fix

# before
nuclei -t tmpl-with-include.yaml

# after
nuclei -nss -t tmpl-with-include.yaml
Defensive patterns

Strategy: validation

Validate before calling

import "regexp"

var includeRe = regexp.MustCompile(`(?m)^\s*!include:`)

if includeRe.Match(data) {
    // either opt out of strict mode or reject the template explicitly
    yaml.StrictSyntax = false // equivalent of -nss
}

Prevention

When it happens

Trigger: Loading a template containing `!include:file` lines with default CLI settings (strict on); CI pipelines running nuclei without -nss; re-enabling strict after previously running lax.

Common situations: Community or internal templates that rely on include preprocessing; version upgrades where templates began shipping includes; SDK users who set yaml.StrictSyntax=true explicitly.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/73defc14ff160965. Report an issue: GitHub.