fix: filter exact variable names from expression evaluation to avoid …#7396
fix: filter exact variable names from expression evaluation to avoid …#7396X3r0Day wants to merge 1 commit into
Conversation
Neo - PR Security ReviewNo security issues found Comment |
WalkthroughThe ChangesExpression Filter Pre-processing
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR fixes a regression in the template expression engine where hyphenated template variable names (e.g. request-id) were incorrectly treated as govaluate expressions and misparsed as subtraction, causing evaluation failures during request execution.
Changes:
- Filter out expressions that exactly match keys in the variable map before govaluate evaluation.
- Preserve normal placeholder substitution for simple variable references (handled via
replacer.Replace) while avoiding mis-evaluation of hyphenated names.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Filter out expressions that are exact variable names in base | ||
| // these are simple variable references handled by replacer.Replace and | ||
| // evaluating them as govaluate expressions can misparse hyphens as subtraction | ||
| filtered := make([]string, 0, len(expressions)) | ||
| for _, expr := range expressions { | ||
| if _, ok := base[expr]; !ok { | ||
| filtered = append(filtered, expr) | ||
| } | ||
| } | ||
| expressions = filtered |
| // Filter out expressions that are exact variable names in base | ||
| // these are simple variable references handled by replacer.Replace and | ||
| // evaluating them as govaluate expressions can misparse hyphens as subtraction |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/protocols/common/expressions/expressions.go`:
- Around line 48-57: Add a unit test in the expressions package that ensures
hyphenated variable names are treated as simple variable references (not parsed
as subtraction) by the replacer/Evaluate flow: create a base map containing keys
like "request-id" and "nextjs-html" and assert that Evaluate (or the public
evaluation wrapper that uses the logic in expressions.go which filters exact
variable names from govaluate parsing) returns "abc123" for "{{request-id}}",
"ID: abc123" for "ID: {{request-id}}", and "abc123/content" for
"{{request-id}}/{{nextjs-html}}"; this will prevent regressions to the filtering
logic that skips entries present in base and relies on replacer.Replace rather
than govaluate parsing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b23f7c59-1da8-4f1e-b392-8e13f7b16c80
📒 Files selected for processing (1)
pkg/protocols/common/expressions/expressions.go
| // Filter out expressions that are exact variable names in base | ||
| // these are simple variable references handled by replacer.Replace and | ||
| // evaluating them as govaluate expressions can misparse hyphens as subtraction | ||
| filtered := make([]string, 0, len(expressions)) | ||
| for _, expr := range expressions { | ||
| if _, ok := base[expr]; !ok { | ||
| filtered = append(filtered, expr) | ||
| } | ||
| } | ||
| expressions = filtered |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Add test coverage for hyphenated variable names to prevent regression.
While the fix correctly addresses issue #7395, the PR checklist indicates no tests were added. Since this fixes a regression introduced between v3.7.1 and v3.8.0, a test case specifically covering hyphenated variable names (e.g., request-id, nextjs-html) would prevent future regressions.
🧪 Suggested test case structure
Consider adding a test in the expression package that verifies:
// Test that hyphenated variable names are treated as simple variables,
// not parsed as subtraction expressions
func TestEvaluateHyphenatedVariableNames(t *testing.T) {
base := map[string]interface{}{
"request-id": "abc123",
"nextjs-html": "content",
}
// Test single hyphenated variable
result, err := Evaluate("{{request-id}}", base)
// expect: "abc123", no govaluate parse error
// Test hyphenated variable in text
result, err = Evaluate("ID: {{request-id}}", base)
// expect: "ID: abc123"
// Test multiple hyphenated variables
result, err = Evaluate("{{request-id}}/{{nextjs-html}}", base)
// expect: "abc123/content"
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/protocols/common/expressions/expressions.go` around lines 48 - 57, Add a
unit test in the expressions package that ensures hyphenated variable names are
treated as simple variable references (not parsed as subtraction) by the
replacer/Evaluate flow: create a base map containing keys like "request-id" and
"nextjs-html" and assert that Evaluate (or the public evaluation wrapper that
uses the logic in expressions.go which filters exact variable names from
govaluate parsing) returns "abc123" for "{{request-id}}", "ID: abc123" for "ID:
{{request-id}}", and "abc123/content" for "{{request-id}}/{{nextjs-html}}"; this
will prevent regressions to the filtering logic that skips entries present in
base and relies on replacer.Replace rather than govaluate parsing.
| filtered := make([]string, 0, len(expressions)) | ||
| for _, expr := range expressions { | ||
| if _, ok := base[expr]; !ok { | ||
| filtered = append(filtered, expr) | ||
| } | ||
| } | ||
| expressions = filtered |
There was a problem hiding this comment.
I see this as nothing more than a temporary workaround because it only addresses the callers of evaluate(). The problem is that any other direct caller of FindExpressions(..., base) is still going to run into issues where they see the exact placeholder keys being treated as expressions.
Also, this approach allocates.
|
Superseded by #7397. |
Closes #7395
Proposed changes
Filter out expressions that are exact keys in the variable map from govaluate evaluation. Hyphenated template variables like
request-idare misparsed as subtraction (request - id) causing"No parameter 'request' found."on every request - these are simple variable references handled byreplacer.Replaceand should not be re-evaluated.Proof
[VER] Sent HTTP requestinstead of[WRN] Could not execute requestChecklist
Summary by CodeRabbit