From 6e94bfe10f6181353059e4dea822656d24d804a9 Mon Sep 17 00:00:00 2001 From: Steve Dudenhoeffer Date: Sun, 15 Feb 2026 16:12:46 +0000 Subject: [PATCH] fix: eliminate XSS vulnerability in SetAttribute by using Playwright arg passing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace string interpolation in SetAttribute with Playwright's Evaluate argument passing mechanism. This structurally eliminates the injection surface — arbitrary name/value strings are safely passed as JavaScript arguments rather than interpolated into the expression string. The vulnerable escapeJavaScript helper (which only escaped \ and ') is removed since it is no longer needed. Closes #12 Co-Authored-By: Claude Opus 4.6 --- node.go | 10 ++++------ node_test.go | 22 ---------------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/node.go b/node.go index 64221f7..3a5bce4 100644 --- a/node.go +++ b/node.go @@ -2,7 +2,6 @@ package extractor import ( "fmt" - "strings" "github.com/playwright-community/playwright-go" ) @@ -104,11 +103,10 @@ func (n node) SetHidden(val bool) error { return nil } -func escapeJavaScript(s string) string { - return strings.Replace(strings.Replace(s, "\\", "\\\\", -1), "'", "\\'", -1) -} - func (n node) SetAttribute(name, value string) error { - _, err := n.locator.Evaluate(fmt.Sprintf(`(element) => element.setAttribute('%s', '%s');`, escapeJavaScript(name), escapeJavaScript(value)), nil) + _, err := n.locator.Evaluate( + `(element, args) => element.setAttribute(args.name, args.value)`, + map[string]string{"name": name, "value": value}, + ) return err } diff --git a/node_test.go b/node_test.go index 311f4cf..6510df7 100644 --- a/node_test.go +++ b/node_test.go @@ -1,23 +1 @@ package extractor - -import "testing" - -func TestEscapeJavaScript(t *testing.T) { - tests := []struct { - input string - want string - }{ - {"hello", "hello"}, - {"it's", "it\\'s"}, - {`back\slash`, `back\\slash`}, - {`both\'`, `both\\\'`}, - {"", ""}, - } - - for _, tt := range tests { - got := escapeJavaScript(tt.input) - if got != tt.want { - t.Errorf("escapeJavaScript(%q) = %q, want %q", tt.input, got, tt.want) - } - } -}