RegexSafetyManager

org.llm4s.security.RegexSafetyManager

Safety wrapper for user-supplied regex compilation and matching.

ReDoS is mitigated by two complementary defences:

  1. A cheap pre-screen (safeCompile) rejects null/empty/oversized patterns and a set of well-known catastrophic-backtracking shapes before they are ever compiled.
  2. A hard execution bound (safeFind/safeMatches) caps the number of character accesses the backtracking engine may perform for a single match. Catastrophic backtracking explores an exponential number of paths, each of which reads characters, so a step ceiling deterministically bounds worst-case runtime - even for dangerous patterns the pre-screen misses - without relying on thread interruption or wall-clock timeouts.

The step bound is the real security boundary: any pattern that reaches the matching helpers is safe regardless of how it was constructed. The shape blocklist is only a fast early-reject and must not be relied on for safety.

NOTE: kept intentionally in sync with org.llm4s.runner.WorkspaceRegexSafetyManager, which duplicates this logic because the workspace runner module cannot depend on core. Changes to the heuristics or bounds here should be mirrored there.

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type

Members list

Type members

Classlikes

final class RegexComplexityException(message: String) extends RuntimeException

Raised when a match exceeds its step budget (likely catastrophic backtracking).

Raised when a match exceeds its step budget (likely catastrophic backtracking).

Attributes

Supertypes
class RuntimeException
class Exception
class Throwable
trait Serializable
class Object
trait Matchable
class Any
Show all

Value members

Concrete methods

def compileLiteral(pattern: String, flags: Int): Pattern
def compileLiteralCaseInsensitive(pattern: String): Pattern
def replaceAllLiteral(input: String, literalPattern: String, replacement: String, caseInsensitive: Boolean): String
def replaceFirstLiteral(input: String, literalPattern: String, replacement: String, caseInsensitive: Boolean): String
def safeCompile(pattern: String, flags: Int): Either[String, Pattern]
def safeFind(pattern: Pattern, input: String, maxSteps: Long): Either[String, Boolean]
def safeMatches(pattern: Pattern, input: String, maxSteps: Long): Either[String, Boolean]