Skip to content

Commit

Permalink
5.0.0 - Security fix.
Browse files Browse the repository at this point in the history
If you had a malformed URL when using the OSC URL sequence,
it would not be properly escaped.
Also, html escaping is now mandatory, so the API changed.
The 'escape_for_html' property was removed.
  • Loading branch information
drudru committed Jan 29, 2021
1 parent 6e19ac4 commit c8c726e
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 203 deletions.
17 changes: 3 additions & 14 deletions Readme.md
Expand Up @@ -119,14 +119,6 @@ See the examples directory for a complete CSS theme for these classes.

## Properties

#### escape_for_html
(default: true)

This does the minimum escaping of text to make it compliant with HTML.
In particular, the '&','<', and '>' characters are escaped. It is
** highly ** recommended that you do not set this to false. It will open
the door security vulnerabilities.

#### use_classes
(default: false)

Expand All @@ -140,12 +132,9 @@ This mapping is a whitelist of URI schemes that will be allowed to render HTML a

## Buffering

In general, the ansi_to_html *should* emit HTML when invoked with a non-empty string.
The only exceptions are an incomplete ESC sequence or an incomplete escaped URL.
For those cases, the library will buffer the escape or the sequence for the escaped URL.

The library is also stateful. If a color is set in a prior invocation, then it will
continue to emit that color in further invocations until the color/SGR attribute is changed.
In general, the ansi_to_html *should* emit HTML output when invoked with a non-empty string.
The only exceptions are an incomplete ESC sequence or an incomplete OSC URL sequence.
For those cases, the library will buffer (not emit output), until it receives input that completes those sequences.

### Example of a Use Case

Expand Down
1 change: 1 addition & 0 deletions VERSION
@@ -0,0 +1 @@
0.1
26 changes: 9 additions & 17 deletions ansi_up.js
Expand Up @@ -34,10 +34,9 @@ var PacketKind;
})(PacketKind || (PacketKind = {}));
var AnsiUp = (function () {
function AnsiUp() {
this.VERSION = "4.0.3";
this.VERSION = "5.0.0";
this.setup_palettes();
this._use_classes = false;
this._escape_for_html = true;
this.bold = false;
this.fg = this.bg = null;
this._buffer = '';
Expand All @@ -50,17 +49,7 @@ var AnsiUp = (function () {
set: function (arg) {
this._use_classes = arg;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AnsiUp.prototype, "escape_for_html", {
get: function () {
return this._escape_for_html;
},
set: function (arg) {
this._escape_for_html = arg;
},
enumerable: true,
enumerable: false,
configurable: true
});
Object.defineProperty(AnsiUp.prototype, "url_whitelist", {
Expand All @@ -70,7 +59,7 @@ var AnsiUp = (function () {
set: function (arg) {
this._url_whitelist = arg;
},
enumerable: true,
enumerable: false,
configurable: true
});
AnsiUp.prototype.setup_palettes = function () {
Expand Down Expand Up @@ -120,13 +109,17 @@ var AnsiUp = (function () {
}
};
AnsiUp.prototype.escape_txt_for_html = function (txt) {
return txt.replace(/[&<>]/gm, function (str) {
return txt.replace(/[&<>"']/gm, function (str) {
if (str === "&")
return "&amp;";
if (str === "<")
return "&lt;";
if (str === ">")
return "&gt;";
if (str === "\"")
return "&quot;";
if (str === "'")
return "&#x27;";
});
};
AnsiUp.prototype.append_buffer = function (txt) {
Expand Down Expand Up @@ -341,8 +334,7 @@ var AnsiUp = (function () {
var txt = fragment.text;
if (txt.length === 0)
return txt;
if (this._escape_for_html)
txt = this.escape_txt_for_html(txt);
txt = this.escape_txt_for_html(txt);
if (!fragment.bold && fragment.fg === null && fragment.bg === null)
return txt;
var styles = [];
Expand Down
27 changes: 8 additions & 19 deletions ansi_up.ts
Expand Up @@ -50,7 +50,7 @@ interface TextPacket {

class AnsiUp
{
VERSION = "4.0.3";
VERSION = "5.0.0";

//
// *** SEE README ON GITHUB FOR PUBLIC API ***
Expand All @@ -66,7 +66,6 @@ class AnsiUp
private bold:boolean;

private _use_classes:boolean;
private _escape_for_html;

private _csi_regex:RegExp;

Expand All @@ -82,7 +81,6 @@ class AnsiUp
// All construction occurs here
this.setup_palettes();
this._use_classes = false;
this._escape_for_html = true;

this.bold = false;
this.fg = this.bg = null;
Expand All @@ -102,16 +100,6 @@ class AnsiUp
return this._use_classes;
}

set escape_for_html(arg:boolean)
{
this._escape_for_html = arg;
}

get escape_for_html():boolean
{
return this._escape_for_html;
}

set url_whitelist(arg:{})
{
this._url_whitelist = arg;
Expand Down Expand Up @@ -183,10 +171,12 @@ class AnsiUp

private escape_txt_for_html(txt:string):string
{
return txt.replace(/[&<>]/gm, (str) => {
if (str === "&") return "&amp;";
if (str === "<") return "&lt;";
if (str === ">") return "&gt;";
return txt.replace(/[&<>"']/gm, (str) => {
if (str === "&") return "&amp;";
if (str === "<") return "&lt;";
if (str === ">") return "&gt;";
if (str === "\"") return "&quot;";
if (str === "'") return "&#x27;";
});
}

Expand Down Expand Up @@ -631,8 +621,7 @@ class AnsiUp
if (txt.length === 0)
return txt;

if (this._escape_for_html)
txt = this.escape_txt_for_html(txt);
txt = this.escape_txt_for_html(txt);

// If colors not set, default style is used
if (!fragment.bold && fragment.fg === null && fragment.bg === null)
Expand Down
8 changes: 4 additions & 4 deletions dist/ansi_up.d.ts
Expand Up @@ -30,16 +30,16 @@ export default class AnsiUp {
private bg;
private bold;
private _use_classes;
private _escape_for_html;
private _csi_regex;
private _osc_st;
private _osc_regex;
private _url_whitelist;
private _buffer;
constructor();
use_classes: boolean;
escape_for_html: boolean;
url_whitelist: {};
set use_classes(arg: boolean);
get use_classes(): boolean;
set url_whitelist(arg: {});
get url_whitelist(): {};
private setup_palettes;
private escape_txt_for_html;
private append_buffer;
Expand Down
26 changes: 9 additions & 17 deletions dist/ansi_up.js.include
Expand Up @@ -15,10 +15,9 @@ var PacketKind;
})(PacketKind || (PacketKind = {}));
var AnsiUp = (function () {
function AnsiUp() {
this.VERSION = "4.0.3";
this.VERSION = "5.0.0";
this.setup_palettes();
this._use_classes = false;
this._escape_for_html = true;
this.bold = false;
this.fg = this.bg = null;
this._buffer = '';
Expand All @@ -31,17 +30,7 @@ var AnsiUp = (function () {
set: function (arg) {
this._use_classes = arg;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AnsiUp.prototype, "escape_for_html", {
get: function () {
return this._escape_for_html;
},
set: function (arg) {
this._escape_for_html = arg;
},
enumerable: true,
enumerable: false,
configurable: true
});
Object.defineProperty(AnsiUp.prototype, "url_whitelist", {
Expand All @@ -51,7 +40,7 @@ var AnsiUp = (function () {
set: function (arg) {
this._url_whitelist = arg;
},
enumerable: true,
enumerable: false,
configurable: true
});
AnsiUp.prototype.setup_palettes = function () {
Expand Down Expand Up @@ -101,13 +90,17 @@ var AnsiUp = (function () {
}
};
AnsiUp.prototype.escape_txt_for_html = function (txt) {
return txt.replace(/[&<>]/gm, function (str) {
return txt.replace(/[&<>"']/gm, function (str) {
if (str === "&")
return "&amp;";
if (str === "<")
return "&lt;";
if (str === ">")
return "&gt;";
if (str === "\"")
return "&quot;";
if (str === "'")
return "&#x27;";
});
};
AnsiUp.prototype.append_buffer = function (txt) {
Expand Down Expand Up @@ -322,8 +315,7 @@ var AnsiUp = (function () {
var txt = fragment.text;
if (txt.length === 0)
return txt;
if (this._escape_for_html)
txt = this.escape_txt_for_html(txt);
txt = this.escape_txt_for_html(txt);
if (!fragment.bold && fragment.fg === null && fragment.bg === null)
return txt;
var styles = [];
Expand Down

1 comment on commit c8c726e

@b-c-ds
Copy link

@b-c-ds b-c-ds commented on c8c726e Mar 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assigned CVE-2021-3377

Please sign in to comment.