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
- Run nuclei with `-nss` / `-no-strict-syntax` so include directives preprocess
- Inline the included file's content into the template to stay strict-compliant
- SDK users: leave yaml.StrictSyntax false (or set parser.NoStrictSyntax) for templates using includes
- 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
- Standardize whether your team uses !include; if yes, always run nuclei with -nss
- grep new templates for '!include:' before adding them to strict-mode pipelines
- In SDK code, set yaml.StrictSyntax=false once at init if includes are expected
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
- Invalid protocol type: {valueToMap}
- invalid workflow with no templates or tags
- validation failed for these fields
- could not read profile file: %w
- could not parse profile YAML: %w
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/73defc14ff160965.
Report an issue: GitHub.