RegExp.escape() Ya Funciona en Todos los Navegadores: Borra Tu Helper de Escape
La función que llevábamos años copiando de Stack Overflow por fin es estándar y Baseline. Cuándo usarla y por qué tu versión casera podía fallar silenciosamente.
La regex más copiada de la historia ya no hace falta
Si alguna vez has interpolado texto de un usuario dentro de una expresión regular —un buscador, un resaltado, un filtro— has escrito esto, o algo parecido:
const escaped = input.replace(/[.*+?^$()|[]\]/g, '\$&');
Llevábamos quince años copiándolo de la misma respuesta de Stack Overflow. Ya no hace falta: RegExp.escape(), parte de ES2025, es Baseline en todos los navegadores modernos y también está en Node reciente. Una función nativa, especificada, que hace exactamente eso.
const term = 'C++ (what?) [v2] $100';
const regex = new RegExp(RegExp.escape(term), 'gi');
regex.test('El precio es C++ (what?) [v2] $100'); // true
Por qué tu helper casero podía fallar
El problema del one-liner clásico no es que esté mal —es que había varias versiones circulando, y ninguna del todo correcta para todos los casos:
- Algunas no escapan
-, que dentro de una clase de caracteres[a-z]forma rangos. - Otras olvidan
^,$,|o los espacios significativos en algunos contextos. - Ninguna contemplaba el contexto: no es lo mismo escapar para dentro de una clase que para el patrón general.
La especificación de RegExp.escape() fija de una vez el conjunto exacto de caracteres a escapar: los SyntaxCharacters (^ $ . * + ? ( ) [ ] { } |) más los que son problemáticos en posiciones iniciales, como -, =, !, comas, almohadillas, porcentajes y demás símbolos que pueden dar significado especial al inicio de una alternativa o grupo.
El caso de uso que importa: regex injection
No es solo comodidad, es seguridad. Si construyes una regex a partir de input de usuario sin escapar, un atacante puede:
- Romper tu consulta inyectando alternativas: buscas
adminy te meten.* - Amplificar un ReDoS: patrones anidados tipo
(a+)+que convierten tu endpoint en un calentador de CPU - Filtrar datos en validaciones donde la regex decide qué es "permitido"
RegExp.escape() convierte cualquier input en literal —es el equivalente regex de parametrizar una query SQL.
// Buscador seguro: el texto se trata literal, nunca como patrón
function buscar(texto, termino) {
const regex = new RegExp(RegExp.escape(termino), 'gi');
return texto.match(regex) ?? [];
}
Detalles a conocer
- Escapa toda la cadena: no uses
RegExp.escape()sobre un patrón que ya contiene sintaxis que quieres conservar. Es para el fragmento literal, no para el patrón completo. - Sigue devolviendo un string: lo pasas a
new RegExp()con tus flags como siempre. - Si el input está vacío, devuelve
'(?:)'(un grupo vacío que no captura) — detalle fino pero pensado.
Puedes probar el comportamiento de tus patrones —escapados o no— en nuestro probador de regex. Y si todavía tienes el helper de Stack Overflow en un utils.js de 2018, ya sabes qué hacer este sprint.
Related articles
El Gusano Shai-Hulud Sigue Vivo en npm: Qué Credenciales Rotar y en Qué Orden
tensorlake@0.5.144 es la última variante del gusano que roba tokens de npm, GitHub y tu .env antes de republicarse con tu identidad. Checklist práctico si instalaste paquetes afectados.
OAuth 2.1 Ya Jubila Oficialmente a RFC 6749: Estas Son las Reglas Nuevas
El draft-16 de OAuth 2.1, publicado en septiembre, declara obsoletos RFC 6749 y 6750: PKCE para todos, adiós al implicit grant. Y el nuevo BCP de validación de JWT está a punto de ser RFC.
Temporal Ya Es Estándar: La API Que Por Fin Sustituye a Date
TC39 aprobó Temporal en Stage 4 y ya funciona sin flags en Chrome, Firefox y Node 26. Qué cambia para tus timestamps, zonas horarias y cálculos de fechas.