Skip to content

[BUG] validation executes DSL helpers while checking unresolved variables #7320

@dwisiswant0

Description

@dwisiswant0

Using evaluation as part of unresolved-variable detection means helper functions can run in validation paths, which is unsafe.

Recipes:

Template:
id: eval-while-validating

info:
  name: Evaluate expressions while validating
  author: dwisiswant0
  severity: info
  tags: test

http:
  - raw:
      - |
        GET /?func={{url_encode(func)}}&args={{url_encode(args)}} HTTP/1.1
        Host: {{Hostname}}

      - |
        POST /reuse HTTP/1.1
        Host: {{Hostname}}

        data={{body_1_internal}}

    extractors:
      - type: dsl
        name: body_1_internal
        internal: true
        dsl:
          - body_1
Server:
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
)

func splitArgs(value string) []string {
	var parts []string
	var current strings.Builder

	quote := rune(0)
	escaped := false
	flush := func() {
		part := strings.TrimSpace(current.String())
		if part != "" {
			parts = append(parts, part)
		}
		current.Reset()
	}

	for _, ch := range value {
		switch {
		case escaped:
			current.WriteRune(ch)
			escaped = false
		case ch == '\\':
			current.WriteRune(ch)
			escaped = true
		case quote != 0:
			current.WriteRune(ch)
			if ch == quote {
				quote = 0
			}
		case ch == '\'' || ch == '"':
			current.WriteRune(ch)
			quote = ch
		case ch == ',':
			flush()
		default:
			current.WriteRune(ch)
		}
	}

	flush()
	return parts
}

func formatArgs(values []string) string {
	parts := make([]string, 0, len(values))
	for _, value := range values {
		parts = append(parts, splitArgs(value)...)
	}
	return strings.Join(parts, ", ")
}

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		body, err := io.ReadAll(r.Body)
		if err != nil {
			log.Printf("method=%s path=%s query=%q body_read_error=%q", r.Method, r.URL.Path, r.URL.RawQuery, err.Error())
			http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
			return
		}
		r.Body.Close()
		log.Printf("method=%s path=%s query=%q body=%q", r.Method, r.URL.Path, r.URL.RawQuery, string(body))

		if r.Method != http.MethodGet {
			w.WriteHeader(http.StatusNoContent)
			return
		}

		query := r.URL.Query()
		funcName := strings.TrimSpace(query.Get("func"))
		args := formatArgs(query["args"])

		if args == "" {
			fmt.Fprintf(w, "{{%s()}}", funcName)
			return
		}

		fmt.Fprintf(w, "{{%s(%s)}}", funcName, args)
	})

	log.Fatal(http.ListenAndServe(":8088", nil))
}

Impact:

  • Unintended helper side effects during validation (UB).
  • Inconsistent behavior where a value stays literal in the final request but still executes internally.

Metadata

Metadata

Assignees

Labels

Type: BugInconsistencies or issues which will cause an issue or problem for users or implementors.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions