{"record":{"id":"1bd89492d1853569","repo":"projectdiscovery/katana","slug":"expression-eval-panic-v","errorCode":null,"errorMessage":"expression eval panic: %v","messagePattern":"expression eval panic: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/utils/formfill.go","lineNumber":80,"sourceCode":"\t}\n\tengine := getFormDSLEngine()\n\tif engine == nil {\n\t\treturn value\n\t}\n\tresult, err := safeEvalExpr(engine, value)\n\tif err != nil {\n\t\treturn value\n\t}\n\treturn fmt.Sprintf(\"%v\", result)\n}\n\n// safeEvalExpr wraps engine.EvalExpr with panic recovery since the\n// underlying govaluate library can panic on inputs that aren't\n// valid expressions (e.g. plain strings treated as undefined variables).\nfunc safeEvalExpr(engine *dsl.Engine, expr string) (result interface{}, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"expression eval panic: %v\", r)\n\t\t}\n\t}()\n\treturn engine.EvalExpr(expr, map[string]interface{}{})\n}\n\n// Resolve evaluates all fields through the DSL engine, resolving any\n// helper function calls like rand_email() or rand_password(8, true).\n// Plain string values pass through unchanged.\nfunc (f *FormFillData) Resolve() {\n\tf.Email = resolveField(f.Email)\n\tf.Color = resolveField(f.Color)\n\tf.Password = resolveField(f.Password)\n\tf.PhoneNumber = resolveField(f.PhoneNumber)\n\tf.Placeholder = resolveField(f.Placeholder)\n}\n\n// FormInput is an input for a form field\ntype FormInput struct {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/projectdiscovery/katana/blob/e3e742739c3746f085943ce918fb4e2b8daf6fe6/pkg/utils/formfill.go#L62-L98","documentation":"safeEvalExpr wraps dsl engine.EvalExpr with a recover() because the govaluate evaluation engine can panic on inputs that aren't valid expressions — most commonly plain strings treated as references to undefined variables. Instead of crashing, the panic is converted into this error and returned to the form-filling resolver.","triggerScenarios":"Calling Resolve on form fields whose value expression is a literal string containing characters govaluate treats as expression syntax (quotes, operators, parentheses), causing engine.EvalExpr to panic internally and safeEvalExpr to recover and return \"expression eval panic: %v\".","commonSituations":"Auto-filling forms where the field value comes from arbitrary page data or user config; a value like \"O'Brien (work)\" or \"a && b\" interpreted as an expression instead of literal text; missing DSL escaping when values are meant to be plain strings.","solutions":["Quote/escape the value before evaluation, or bypass the DSL for values that are plain literals (pass them straight through).","Check the %v panic message to identify the offending expression and fix the field's value in your form-fill config.","Upgrade the govaluate dependency if a newer version handles the failing input without panicking.","Pre-validate values with a regex for expression metacharacters and mark them as literals."],"exampleFix":"// before\nresult, err := safeEvalExpr(engine, fieldValue) // panics on \"O'Brien (work)\"\n// after\nvar result interface{}\nvar err error\nif isPlainLiteral(fieldValue) {\n    result = fieldValue\n} else {\n    result, err = safeEvalExpr(engine, fieldValue)\n}","handlingStrategy":"try-catch","validationCode":"// treat values containing expression metacharacters as literals\nvar exprMeta = regexp.MustCompile(`[()&|!<>=\"']`)\nfunc needsLiteral(v string) bool { return exprMeta.MatchString(v) }","typeGuard":"func isSafeExpression(s string) bool {\n    // a safe expression references only known variables and operators\n    return exprMeta.MatchString(s) == false || isQuotedString(s)\n}","tryCatchPattern":"result, err := safeEvalExpr(engine, expr)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"expression eval panic\") {\n        log.Printf(\"non-expression value %q, using as literal\", expr)\n        result = expr\n        err = nil\n    }\n}","preventionTips":["Route plain-literal field values around the DSL engine entirely.","Keep the govaluate dependency updated for panic fixes on edge-case inputs.","Unit-test Resolve with realistic page strings containing quotes, apostrophes, and operators."],"tags":["dsl","formfill","panic-recovery"],"backgroundTag":"expression-eval-panic","analyzedSha":"e3e742739c3746f085943ce918fb4e2b8daf6fe6","analyzedAt":"2026-09-03T14:55:13.248Z","contentChangedAt":"2026-09-03T14:55:13.248Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}