This is an automated email from the ASF dual-hosted git repository.
raboof pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko-connectors.git
The following commit(s) were added to refs/heads/main by this push:
new f93583e80 orientdb: validate class name (#1821)
f93583e80 is described below
commit f93583e80e42949b5a63f4206fb26187ecd81b41
Author: PJ Fanning <[email protected]>
AuthorDate: Wed Aug 5 11:02:55 2026 +0100
orientdb: validate class name (#1821)
---
.../orientdb/impl/OrientDbSourceStage.scala | 15 +++++
.../orientdb/impl/OrientDbSourceStageSpec.scala | 77 ++++++++++++++++++++++
2 files changed, 92 insertions(+)
diff --git
a/orientdb/src/main/scala/org/apache/pekko/stream/connectors/orientdb/impl/OrientDbSourceStage.scala
b/orientdb/src/main/scala/org/apache/pekko/stream/connectors/orientdb/impl/OrientDbSourceStage.scala
index db7b85eec..c3b54ef4a 100644
---
a/orientdb/src/main/scala/org/apache/pekko/stream/connectors/orientdb/impl/OrientDbSourceStage.scala
+++
b/orientdb/src/main/scala/org/apache/pekko/stream/connectors/orientdb/impl/OrientDbSourceStage.scala
@@ -30,6 +30,19 @@ import scala.jdk.OptionConverters._
/**
* INTERNAL API
*/
+@InternalApi
+private[orientdb] object OrientDbSourceStage {
+ // Valid OrientDB class names: letters, digits, underscores; must start with
letter or underscore
+ private val ValidClassName = "^[a-zA-Z_][a-zA-Z0-9_]*$".r
+
+ private[orientdb] def validateClassName(name: String): Unit = {
+ require(name != null && name.nonEmpty, "className must not be null or
empty")
+ require(
+ ValidClassName.matches(name),
+ s"className contains invalid characters: '$name'. Only letters, digits,
and underscores are allowed.")
+ }
+}
+
@InternalApi
private[orientdb] final class OrientDbSourceStage[T](className: String,
query: Option[String],
@@ -37,6 +50,8 @@ private[orientdb] final class
OrientDbSourceStage[T](className: String,
clazz: Option[Class[T]] = None)
extends GraphStage[SourceShape[OrientDbReadResult[T]]] {
+ OrientDbSourceStage.validateClassName(className)
+
val out: Outlet[OrientDbReadResult[T]] = Outlet("OrientDBSource.out")
override val shape = SourceShape(out)
override def initialAttributes: Attributes =
diff --git
a/orientdb/src/test/scala/org/apache/pekko/stream/connectors/orientdb/impl/OrientDbSourceStageSpec.scala
b/orientdb/src/test/scala/org/apache/pekko/stream/connectors/orientdb/impl/OrientDbSourceStageSpec.scala
new file mode 100644
index 000000000..0ef5c4993
--- /dev/null
+++
b/orientdb/src/test/scala/org/apache/pekko/stream/connectors/orientdb/impl/OrientDbSourceStageSpec.scala
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pekko.stream.connectors.orientdb.impl
+
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.wordspec.AnyWordSpec
+
+class OrientDbSourceStageSpec extends AnyWordSpec with Matchers {
+
+ "OrientDbSourceStage.validateClassName" should {
+
+ "accept valid class names" in {
+ OrientDbSourceStage.validateClassName("User")
+ OrientDbSourceStage.validateClassName("MyClass")
+ OrientDbSourceStage.validateClassName("_internal")
+ OrientDbSourceStage.validateClassName("Class123")
+ OrientDbSourceStage.validateClassName("my_class")
+ }
+
+ "reject null class name" in {
+ assertThrows[IllegalArgumentException] {
+ OrientDbSourceStage.validateClassName(null)
+ }
+ }
+
+ "reject empty class name" in {
+ assertThrows[IllegalArgumentException] {
+ OrientDbSourceStage.validateClassName("")
+ }
+ }
+
+ "reject class name with SQL injection attempt" in {
+ assertThrows[IllegalArgumentException] {
+ OrientDbSourceStage.validateClassName("User; DROP TABLE users; --")
+ }
+ }
+
+ "reject class name with quotes" in {
+ assertThrows[IllegalArgumentException] {
+ OrientDbSourceStage.validateClassName("User\" OR 1=1 --")
+ }
+ }
+
+ "reject class name starting with digit" in {
+ assertThrows[IllegalArgumentException] {
+ OrientDbSourceStage.validateClassName("123Class")
+ }
+ }
+
+ "reject class name with spaces" in {
+ assertThrows[IllegalArgumentException] {
+ OrientDbSourceStage.validateClassName("My Class")
+ }
+ }
+
+ "reject class name with special characters" in {
+ assertThrows[IllegalArgumentException] {
+ OrientDbSourceStage.validateClassName("Class@name")
+ }
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]