Skip to content

Commit

Permalink
fix: do not bind content as innerHTML by default (#126)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
Previously, cell values were bound using `innerHTML`.
With this change they are now bound using normal data binding.
This means that any html markup will no longer be rendered.
To restore the previous behavior set `bindAsUnsafeHtml`
on columns where needed.

We decided to change this behavior,
as binding `innerHTML` can lead to HTML injection.
Especially in table content which are often untrusted
user generated content.

BREAKING CHANGE:
Header cell names are now bound using data binding
instead of `innerHTML`.
Use a `headerTemplate` to provide custom html markup.
  • Loading branch information
spike-rabbit authored Nov 21, 2024
1 parent ab910c3 commit e818477
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ import { AsyncPipe, NgTemplateOutlet } from '@angular/common';
}
@if (!column.cellTemplate) {
<span [title]="sanitizedValue" [innerHTML]="value"> </span>
@if (column.bindAsUnsafeHtml) {
<span [title]="sanitizedValue" [innerHTML]="value"> </span>
} @else {
<span [title]="sanitizedValue">{{ value }}</span>
}
} @else {
<ng-template
#cellTemplate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class DataTableColumnDirective<TRow> implements TableColumn, OnChanges {
private columnChangesService = inject(ColumnChangesService);
@Input() name: string;
@Input() prop: TableColumnProp;
@Input({ transform: booleanAttribute }) bindAsUnsafeHtml?: boolean;
@Input({ transform: booleanAttribute }) frozenLeft: boolean;
@Input({ transform: booleanAttribute }) frozenRight: boolean;
@Input({ transform: numberAttribute }) flexGrow: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ import { NgTemplateOutlet } from '@angular/common';
</ng-template>
} @else {
<span class="datatable-header-cell-wrapper">
<span class="datatable-header-cell-label draggable" (click)="onSort()" [innerHTML]="name">
<span class="datatable-header-cell-label draggable" (click)="onSort()">
{{ name }}
</span>
</span>
}
Expand Down
8 changes: 8 additions & 0 deletions projects/ngx-datatable/src/lib/types/table-column.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ export interface TableColumn<TRow = any> {
*/
prop?: TableColumnProp;

/**
* By default, the property is bound using normal data binding `<span>{{content}}</span>`.
* If this property is set to true, the property will be bound as `<span [innerHTML]="content" />`.
*
* **DANGER** If enabling this feature, make sure the source of the data is trusted. This can be a vector for HTML injection attacks.
*/
bindAsUnsafeHtml?: boolean;

/**
* Cell template ref
*/
Expand Down

0 comments on commit e818477

Please sign in to comment.