Skip to content

Commit 3661b11

Browse files
committed
ensure request ids contain alphanumerics,dashes,underscores
prevent potential for XSS by rejecting ids with special characters
1 parent 1014fb0 commit 3661b11

File tree

2 files changed

+73
-7
lines changed

2 files changed

+73
-7
lines changed

lib/json_rpc_handler.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class ErrorCode
1717
ParseError = -32700
1818
end
1919

20+
ALLOWED_ID_CHARACTERS = /\A[a-zA-Z0-9_-]+\z/.freeze
21+
2022
module_function
2123

2224
def handle(request, &method_finder)
@@ -67,7 +69,7 @@ def process_request(request, &method_finder)
6769

6870
error = case
6971
when !valid_version?(request[:jsonrpc]) then 'JSON-RPC version must be 2.0'
70-
when !valid_id?(request[:id]) then 'Request ID must be a string or an integer or null'
72+
when !valid_id?(request[:id]) then 'Request ID must contain only alphanumerics, dashes, or underscores, or be an integer or null'
7173
when !valid_method_name?(request[:method]) then 'Method name must be a string and not start with "rpc."'
7274
end
7375

@@ -115,8 +117,12 @@ def valid_version?(version)
115117
version == Version::V2_0
116118
end
117119

120+
118121
def valid_id?(id)
119-
id.is_a?(String) || id.is_a?(Integer) || id.nil?
122+
return true if id.nil? || id.is_a?(Integer)
123+
return false unless id.is_a?(String)
124+
125+
id.match?(ALLOWED_ID_CHARACTERS)
120126
end
121127

122128
def valid_method_name?(method)

test/json_rpc_handler_test.rb

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@
9090
# The Server MUST reply with the same value in the Response object if included. This member is used to correlate the
9191
# context between the two objects.
9292

93-
it "returns a response with the same request id when the id is a string" do
93+
it "returns a response with the same request id when the id is a valid string" do
9494
register("add") { |params| params[:a] + params[:b] }
95-
id = "rpc-call-42"
95+
id = "request-123_abc"
9696

9797
handle jsonrpc: "2.0", id:, method: "add", params: { a: 1, b: 2 }
9898

@@ -116,7 +116,67 @@
116116
assert_rpc_error expected_error: {
117117
code: -32600,
118118
message: "Invalid Request",
119-
data: "Request ID must be a string or an integer or null",
119+
data: "Request ID must contain only alphanumerics, dashes, or underscores, or be an integer or null",
120+
}
121+
end
122+
123+
it "accepts string id with alphanumerics, dashes, and underscores" do
124+
register("add") { |params| params[:a] + params[:b] }
125+
id = "request-123_ABC"
126+
127+
handle jsonrpc: "2.0", id:, method: "add", params: { a: 1, b: 2 }
128+
129+
assert_rpc_success expected_result: 3
130+
assert_equal id, @response[:id]
131+
end
132+
133+
it "accepts UUID format strings" do
134+
register("add") { |params| params[:a] + params[:b] }
135+
id = "550e8400-e29b-41d4-a716-446655440000"
136+
137+
handle jsonrpc: "2.0", id:, method: "add", params: { a: 1, b: 2 }
138+
139+
assert_rpc_success expected_result: 3
140+
assert_equal id, @response[:id]
141+
end
142+
143+
it "returns an error when request id contains HTML content (XSS prevention)" do
144+
handle jsonrpc: "2.0", id: "<script>alert('xss')</script>", method: "add", params: { a: 1, b: 2 }
145+
146+
assert_rpc_error expected_error: {
147+
code: -32600,
148+
message: "Invalid Request",
149+
data: "Request ID must contain only alphanumerics, dashes, or underscores, or be an integer or null",
150+
}
151+
end
152+
153+
it "returns an error when request id contains spaces" do
154+
handle jsonrpc: "2.0", id: "request 123", method: "add", params: { a: 1, b: 2 }
155+
156+
assert_rpc_error expected_error: {
157+
code: -32600,
158+
message: "Invalid Request",
159+
data: "Request ID must contain only alphanumerics, dashes, or underscores, or be an integer or null",
160+
}
161+
end
162+
163+
it "returns an error when request id contains special characters" do
164+
handle jsonrpc: "2.0", id: "request@123", method: "add", params: { a: 1, b: 2 }
165+
166+
assert_rpc_error expected_error: {
167+
code: -32600,
168+
message: "Invalid Request",
169+
data: "Request ID must contain only alphanumerics, dashes, or underscores, or be an integer or null",
170+
}
171+
end
172+
173+
it "returns an error when request id is an empty string" do
174+
handle jsonrpc: "2.0", id: "", method: "add", params: { a: 1, b: 2 }
175+
176+
assert_rpc_error expected_error: {
177+
code: -32600,
178+
message: "Invalid Request",
179+
data: "Request ID must contain only alphanumerics, dashes, or underscores, or be an integer or null",
120180
}
121181
end
122182

@@ -126,7 +186,7 @@
126186
assert_rpc_error expected_error: {
127187
code: -32600,
128188
message: "Invalid Request",
129-
data: "Request ID must be a string or an integer or null",
189+
data: "Request ID must contain only alphanumerics, dashes, or underscores, or be an integer or null",
130190
}
131191
end
132192

@@ -250,7 +310,7 @@
250310
assert_rpc_error expected_error: {
251311
code: -32600,
252312
message: "Invalid Request",
253-
data: "Request ID must be a string or an integer or null",
313+
data: "Request ID must contain only alphanumerics, dashes, or underscores, or be an integer or null",
254314
}
255315
assert_nil @response[:id]
256316
end

0 commit comments

Comments
 (0)