Skip to content

Commit

Permalink
Prevent html injection using user tag (#452)
Browse files Browse the repository at this point in the history
* Prevent html injection using user tag

* use encodeUrl
  • Loading branch information
Mitchdev authored May 20, 2024
1 parent c35c4d4 commit a7114d6
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 20 deletions.
17 changes: 17 additions & 0 deletions assets/chat/js/encodeUrl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// stolen from angular.js
// https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435
function encodeUrl(value) {
return value
.replace(/&/g, '&')
.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, (v) => {
const hi = v.charCodeAt(0);
const low = v.charCodeAt(1);
return `&#${(hi - 0xd800) * 0x400 + (low - 0xdc00) + 0x10000};`;
})
.replace(/([^#-~| |!])/g, (v) => `&#${v.charCodeAt(0)};`)
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}

export default encodeUrl;
20 changes: 3 additions & 17 deletions assets/chat/js/formatters/UrlFormatter.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
import $ from 'jquery';
import { linkregex } from '../regex';
import { HashLinkConverter } from '../hashlinkconverter';
import encodeUrl from '../encodeUrl';

export default class UrlFormatter {
constructor() {
this.hashLinkConverter = new HashLinkConverter();
this.elem = $('<div></div>');
}

// stolen from angular.js
// https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435
encodeUrl(value) {
return value
.replace(/&/g, '&amp;')
.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, (v) => {
const hi = v.charCodeAt(0);
const low = v.charCodeAt(1);
return `&#${(hi - 0xd800) * 0x400 + (low - 0xdc00) + 0x10000};`;
})
.replace(/([^#-~| |!])/g, (v) => `&#${v.charCodeAt(0)};`)
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}

format(chat, str) {
if (!str) return undefined;
const self = this;
Expand All @@ -35,7 +21,7 @@ export default class UrlFormatter {
const decodedUrl = self.elem.html(url).text();
const m = decodedUrl.match(linkregex);
if (m) {
const normalizedUrl = self.encodeUrl(this.normalizeUrl(m[0]));
const normalizedUrl = encodeUrl(this.normalizeUrl(m[0]));

let embedHashLink = '';
try {
Expand All @@ -53,7 +39,7 @@ export default class UrlFormatter {
urlText = `${urlText.slice(0, 40)}...${urlText.slice(-40)}`;
}

const extra = self.encodeUrl(decodedUrl.substring(m[0].length));
const extra = encodeUrl(decodedUrl.substring(m[0].length));
const href = `${scheme ? '' : 'http://'}${normalizedUrl}`;

const embedTarget = chat.isBigscreenEmbed() ? '_top' : '_blank';
Expand Down
7 changes: 4 additions & 3 deletions assets/chat/js/messages/ChatUserMessage.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import encodeUrl from '../encodeUrl';
import ChatMessage from './ChatMessage';
import MessageTypes from './MessageTypes';

Expand Down Expand Up @@ -61,9 +62,9 @@ export default class ChatUserMessage extends ChatMessage {
else if (this.slashme || this.continued) ctrl = '';

const colorFlair = usernameColorFlair(chat.flairs, this.user);
const user = `${this.buildFeatures(this.user, chat)} <a title="${
this.title
}" class="${['user', colorFlair?.name].filter(Boolean).join(' ')}">${
const user = `${this.buildFeatures(this.user, chat)} <a title="${encodeUrl(
this.title,
)}" class="${['user', colorFlair?.name].filter(Boolean).join(' ')}">${
this.user.displayName
}</a>`;
return this.wrap(
Expand Down

0 comments on commit a7114d6

Please sign in to comment.