diff --git a/src/autolinker.ts b/src/autolinker.ts
index 5c7a3c1f..48a63d67 100644
--- a/src/autolinker.ts
+++ b/src/autolinker.ts
@@ -913,6 +913,8 @@ export default class Autolinker {
textOrHtml = textOrHtml.replace(//g, '>');
}
+ textOrHtml = this.stripUnsafeCharacters(textOrHtml);
+
let matches = this.parse(textOrHtml),
newHtml: string[] = [],
lastIndex = 0;
@@ -1020,6 +1022,16 @@ export default class Autolinker {
return tagBuilder;
}
+
+ /**
+ * Strips characters considered as unsafe
+ * SNYK-AUTOLINKER-2438289
+ * @param text
+ * @private
+ */
+ private stripUnsafeCharacters(text: string) {
+ return text.replace(/[\u202a-\u202e, \u200e-\u200f]/g, '');
+ }
}
export interface AutolinkerConfig {
diff --git a/tests/autolinker-url.spec.ts b/tests/autolinker-url.spec.ts
index 440b5481..ffea02b8 100644
--- a/tests/autolinker-url.spec.ts
+++ b/tests/autolinker-url.spec.ts
@@ -1265,4 +1265,30 @@ describe('Autolinker Url Matching -', () => {
);
});
});
+
+ describe('unicode exploits', () => {
+ it('should strip out character direction override unicodes', () => {
+ expect(autolinker.link('foo.combar.com')).toBe(
+ 'foo.combar.com'
+ );
+ expect(autolinker.link('foo.com\u202Ebar.com')).toBe(
+ 'foo.combar.com'
+ );
+ expect(autolinker.link('foo.com\u202abar.com')).toBe(
+ 'foo.combar.com'
+ );
+ expect(autolinker.link('foo.com\u202bbar.com')).toBe(
+ 'foo.combar.com'
+ );
+ expect(autolinker.link('foo.com\u202cbar.com')).toBe(
+ 'foo.combar.com'
+ );
+ expect(autolinker.link('foo.com\u202dbar.com')).toBe(
+ 'foo.combar.com'
+ );
+ expect(autolinker.link('foo.com\u202ebar.com')).toBe(
+ 'foo.combar.com'
+ );
+ });
+ });
});