{"record":{"id":"2ec1dafea522dbfe","repo":"projectdiscovery/nuclei","slug":"unresolved-dsl-placeholders-must-be-inside-string","errorCode":null,"errorMessage":"unresolved DSL placeholders must be inside string literals","messagePattern":"unresolved DSL placeholders must be inside string literals","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/operators/matchers/dsl_string_markers.go","lineNumber":45,"sourceCode":"}\n\ntype stringLiteralSpan struct {\n\tstart int\n\tend   int\n\tquote byte\n}\n\nfunc resolveDSLStringMarkers(expression string, data map[string]interface{}) (string, error) {\n\t// Resolve only marker spans already present in the compiled DSL source.\n\t// Values are escaped for the surrounding string literal before recompilation.\n\tstringSpans := findStringLiteralSpans(expression)\n\tmarkers, err := findDSLStringMarkers(expression, data, stringSpans)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif len(markers) == 0 {\n\t\treturn \"\", fmt.Errorf(\"unresolved DSL placeholders must be inside string literals\")\n\t}\n\n\tsort.Slice(markers, func(i, j int) bool {\n\t\treturn markers[i].start > markers[j].start\n\t})\n\n\tresolved := expression\n\tfor _, marker := range markers {\n\t\tresult, err := render.Render(render.Input{\n\t\t\tText:   \"{{\" + marker.expr + \"}}\",\n\t\t\tValues: data,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\n\t\treplacement := expressions.EscapeStringValue(result.Text, marker.quote)\n\t\tresolved = resolved[:marker.start] + replacement + resolved[marker.end:]","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/operators/matchers/dsl_string_markers.go#L27-L63","documentation":"Runtime resolution error from resolveDSLStringMarkers (pkg/operators/matchers/dsl_string_markers.go:45). When a DSL matcher expression still contains unresolved {{...}} markers after compile-time variable substitution, nuclei attempts to substitute them only inside string literals of the expression. If findDSLStringMarkers returns zero markers — the expression has unresolved markers but none resided in string literals — this error aborts the matcher with that message.","triggerScenarios":"A DSL matcher like `dsl: [\"{{payload}} == '1'\"]` where `{{payload}}` sits outside quotes, and `payload` is not a known govaluate variable/base value at evaluation time, so the raw marker survives to this stage; the marker scan then finds no in-literal candidates and len(markers)==0 triggers the error.","commonSituations":"Fuzzing/payload templates where generator variables are referenced unquoted inside DSL expressions; marker typos ({{Paylaod}}) that never bind; referencing dynamic extractor names before they are defined; expressions mixing govaluate identifiers with template markers incorrectly.","solutions":["Quote the placeholder so it is a string literal: `\"'{{payload}}' == '1'\"` style, letting the resolver substitute inside quotes","Fix the variable name so the marker binds at compile time and disappears entirely","Precompute the value into a named variable (internal:true extractor + {{var}}) instead of inlining a raw marker in the DSL expression","Re-run with -v to see the exact expression after partial substitution and confirm quoting"],"exampleFix":"# before\ndsl:\n  - '{{myvar}} == \"admin\"'\n# after\ndsl:\n  - \"'{{myvar}}' == 'admin'\"","handlingStrategy":"validation","validationCode":"// lint: any {{...}} in a dsl matcher must sit between quotes\nvar bareMarker = regexp.MustCompile(`(^|[^\"'])\\{\\{[^{}]+\\}\\}($|[^\"'])`)\nif bareMarker.MatchString(dslExpr) {\n\treturn fmt.Errorf(\"dsl %q contains an unquoted placeholder\", dslExpr)\n}","typeGuard":"func dslMarkersQuoted(expr string) bool { return !bareMarkerRE.MatchString(expr) }","tryCatchPattern":"// errors surface at match time; log and drop to no-match, then fix template:\nif err := m.Match(data); err != nil && strings.Contains(err.Error(), \"unresolved DSL placeholders\") {\n\tgologger.Warn().Msgf(\"template bug in %s: quote {{...}} inside dsl\", tplID)\n}","preventionTips":["Always quote placeholders inside DSL strings: \"'{{var}}'\"","Prefer bound variables over surviving markers in expressions","Test fuzz/payload templates against a local echo server before shipping"],"tags":["matcher","dsl","placeholders","template","runtime"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}