npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@libs-ui/services-sanitizer

v0.2.357-28

Published

> Service xử lý XSS (Cross-Site Scripting) sử dụng DOMPurify, cung cấp API sanitize HTML an toàn cho Angular.

Readme

@libs-ui/services-sanitizer

Service xử lý XSS (Cross-Site Scripting) sử dụng DOMPurify, cung cấp API sanitize HTML an toàn cho Angular.

Giới thiệu

SanitizerService là service Angular tích hợp DOMPurify để loại bỏ các mối đe dọa XSS trong nội dung HTML. Service cung cấp nhiều chế độ sanitize từ strict (chỉ text formatting cơ bản) đến rich text (đầy đủ HTML features cho editor), đồng thời hỗ trợ trả về Angular SafeHtml để bind trực tiếp vào [innerHTML] mà không cần thêm bước xử lý.

Tính năng

  • ✅ Sanitize HTML loại bỏ XSS threats (script, event handler, inline JS)
  • ✅ Tích hợp Angular DomSanitizer — trả về SafeHtml dùng trực tiếp với [innerHTML]
  • ✅ Chế độ strict — chỉ cho phép text formatting cơ bản (p, span, strong, em, br)
  • ✅ Chế độ rich text — giữ đầy đủ HTML structure cho editor (Quill, TinyMCE, CKEditor)
  • ✅ Strip HTML — loại bỏ toàn bộ tags, chỉ giữ plain text
  • ✅ Detect XSS — kiểm tra xem HTML có chứa nội dung độc hại không
  • ✅ Custom config — tuỳ chỉnh allowed tags, attributes, styles theo nhu cầu
  • providedIn: 'root' — không cần import vào module, inject trực tiếp

Khi nào sử dụng

  • Hiển thị nội dung HTML từ user input (comment, mô tả, bài viết)
  • Render output từ rich text editor (Quill, TinyMCE, CKEditor) an toàn
  • Cần kiểm tra nhanh xem một đoạn HTML có chứa XSS threats không
  • Lưu HTML vào database sau khi đã loại bỏ nội dung nguy hiểm
  • Hiển thị nội dung i18n có chứa HTML tags cơ bản

Cài đặt

npm install @libs-ui/services-sanitizer

Đảm bảo dompurify đã được cài đặt (peer dependency):

npm install dompurify

Import

import { SanitizerService, SanitizerConfig } from '@libs-ui/services-sanitizer';

Inject vào component (không cần khai báo trong imports[]providedIn: 'root'):

import { Component, inject } from '@angular/core';
import { SanitizerService } from '@libs-ui/services-sanitizer';

@Component({
  selector: 'app-example',
  standalone: true,
  templateUrl: './example.component.html',
})
export class ExampleComponent {
  private readonly sanitizerService = inject(SanitizerService);
}

Ví dụ sử dụng

Ví dụ 1 — Sanitize HTML cơ bản và bind với [innerHTML]

// example.component.ts
import { Component, inject, signal, computed } from '@angular/core';
import { SanitizerService } from '@libs-ui/services-sanitizer';
import { SafeHtml } from '@angular/platform-browser';

@Component({
  selector: 'app-article-detail',
  standalone: true,
  templateUrl: './article-detail.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ArticleDetailComponent {
  private readonly sanitizerService = inject(SanitizerService);

  protected rawContent = signal('<p>Nội dung bài viết</p><script>alert("XSS")</script>');

  protected safeContent = computed<SafeHtml>(() =>
    this.sanitizerService.sanitizeToSafeHtml(this.rawContent())
  );
}
<!-- article-detail.component.html -->
<div class="article-body" [innerHTML]="safeContent()"></div>

Ví dụ 2 — Strict mode cho comment người dùng

// comment-item.component.ts
import { Component, inject } from '@angular/core';
import { SanitizerService } from '@libs-ui/services-sanitizer';

@Component({
  selector: 'app-comment-item',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="comment-text">{{ safeComment }}</div>
  `,
})
export class CommentItemComponent {
  private readonly sanitizerService = inject(SanitizerService);

  // Chỉ cho phép p, span, strong, em, br — loại bỏ link, ảnh, và styles
  safeComment = this.sanitizerService.sanitizeStrict(
    '<p>Bình luận <strong>quan trọng</strong></p><a href="malicious.com">Click</a>'
  );
  // Result: '<p>Bình luận <strong>quan trọng</strong></p>Click'
}

Ví dụ 3 — Rich text editor (Quill / TinyMCE)

// editor-preview.component.ts
import { Component, inject, signal, computed } from '@angular/core';
import { SanitizerService } from '@libs-ui/services-sanitizer';
import { SafeHtml } from '@angular/platform-browser';

@Component({
  selector: 'app-editor-preview',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `<div class="ql-editor" [innerHTML]="previewHtml()"></div>`,
})
export class EditorPreviewComponent {
  private readonly sanitizerService = inject(SanitizerService);

  protected editorOutput = signal('');

  protected previewHtml = computed<SafeHtml>(() => {
    const sanitized = this.sanitizerService.sanitizeRichText(this.editorOutput());
    return this.sanitizerService.sanitizeToSafeHtml(sanitized);
  });

  protected handlerEditorChange(html: string): void {
    this.editorOutput.set(html);
  }
}

Ví dụ 4 — Kiểm tra XSS trước khi lưu

// save-content.component.ts
import { Component, inject } from '@angular/core';
import { SanitizerService } from '@libs-ui/services-sanitizer';
import { NotificationService } from '@libs-ui/services-notification';

@Component({
  selector: 'app-save-content',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SaveContentComponent {
  private readonly sanitizerService = inject(SanitizerService);
  private readonly notification = inject(NotificationService);

  protected handlerSave(userInput: string): void {
    if (this.sanitizerService.hasXSSThreats(userInput)) {
      this.notification.showError('i18n_content_contains_unsafe_html');
      return;
    }

    const cleanHtml = this.sanitizerService.sanitize(userInput);
    // Tiến hành lưu cleanHtml vào API
  }
}

Ví dụ 5 — Custom config (chỉ cho phép danh sách tags cụ thể)

// custom-sanitize.component.ts
import { Component, inject } from '@angular/core';
import { SanitizerService, SanitizerConfig } from '@libs-ui/services-sanitizer';

@Component({
  selector: 'app-custom-sanitize',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomSanitizeComponent {
  private readonly sanitizerService = inject(SanitizerService);

  private readonly strictTableConfig: SanitizerConfig = {
    allowedTags: ['table', 'thead', 'tbody', 'tr', 'th', 'td', 'caption'],
    allowedAttributes: ['class', 'colspan', 'rowspan', 'scope'],
    allowStyles: false,
    allowDataAttributes: false,
  };

  protected safeTable = this.sanitizerService.sanitize(
    '<table><tr><td onclick="steal()">Data</td></tr></table>',
    this.strictTableConfig
  );
  // Result: '<table><tr><td>Data</td></tr></table>'
}

Methods

| Method | Signature | Trả về | Mô tả | |---|---|---|---| | sanitize | sanitize(html: string, config?: SanitizerConfig): string | string | Sanitize HTML, loại bỏ XSS threats, trả về string an toàn | | sanitizeToSafeHtml | sanitizeToSafeHtml(html: string, config?: SanitizerConfig): SafeHtml | SafeHtml | Sanitize và wrap thành Angular SafeHtml dùng trực tiếp với [innerHTML] | | sanitizeStrict | sanitizeStrict(html: string): string | string | Strict mode — chỉ cho phép p, br, span, strong, b, em, i, u. Loại bỏ link, ảnh, styles | | sanitizeRichText | sanitizeRichText(html: string): string | string | Rich text mode — giữ đầy đủ HTML features kể cả iframe, phù hợp output từ editor | | stripHtml | stripHtml(html: string): string | string | Xoá toàn bộ HTML tags, chỉ giữ plain text content | | hasXSSThreats | hasXSSThreats(html: string): boolean | boolean | Trả về true nếu HTML gốc khác HTML đã sanitize (tức có nội dung độc hại bị loại bỏ) |

Types & Interfaces

import { SanitizerConfig } from '@libs-ui/services-sanitizer';

SanitizerConfig

interface SanitizerConfig {
  /** Danh sách HTML tags được phép. Khi set sẽ REPLACE (không merge) default config */
  allowedTags?: string[];

  /** Danh sách HTML attributes được phép. Khi set sẽ REPLACE (không merge) default config */
  allowedAttributes?: string[];

  /** Cho phép CSS inline styles. Mặc định: true */
  allowStyles?: boolean;

  /** Cho phép data-* attributes. Mặc định: true */
  allowDataAttributes?: boolean;

  /** Custom DOMPurify config — merge vào trên cùng của config đã build */
  customConfig?: DOMPurify.Config;
}

| Property | Type | Default | Mô tả | |---|---|---|---| | allowedTags | string[] | DOMPurify defaults (p, div, span, h1-h6, ul, ol, li, table, a, img...) | Danh sách HTML tags được phép. Set = REPLACE, không merge | | allowedAttributes | string[] | class, id, style, href, src, data-, aria-... | Danh sách HTML attributes được phép. Set = REPLACE, không merge | | allowStyles | boolean | true | false sẽ loại bỏ thuộc tính style khỏi tất cả elements | | allowDataAttributes | boolean | true | false sẽ loại bỏ toàn bộ data-* attributes | | customConfig | DOMPurify.Config | undefined | Merge thêm vào config đã build, ưu tiên cao nhất |

Default allowed tags (khi không truyền allowedTags)

Text formatting: p, br, span, div, strong, b, em, i, u, s, strike, del, ins, sub, sup, small, mark, code, pre, kbd, samp

Headings: h1, h2, h3, h4, h5, h6

Lists: ul, ol, li, dl, dt, dd

Tables: table, thead, tbody, tfoot, tr, th, td, caption, col, colgroup

Links & Media: a, img, figure, figcaption, picture, source

Semantic: blockquote, q, cite, abbr, address, time, article, section, nav, aside, header, footer, main, hr, details, summary

Lưu ý quan trọng

⚠️ Custom config REPLACE, không merge: Khi cung cấp allowedTags hoặc allowedAttributes trong SanitizerConfig, service sẽ THAY THẾ hoàn toàn default config, không gộp lại. Nếu muốn giữ default và thêm tag mới, hãy dùng customConfig.ADD_TAGS thay thế.

// ❌ SAI — sẽ mất toàn bộ default tags, chỉ còn 'p' và tag thêm
sanitize(html, { allowedTags: ['p'], customConfig: { ADD_TAGS: ['custom-tag'] } });

// ✅ ĐÚNG — giữ default, thêm tag mới qua customConfig
sanitize(html, { customConfig: { ADD_TAGS: ['custom-tag'], ADD_ATTR: ['custom-attr'] } });

⚠️ sanitizeToSafeHtml dùng bypassSecurityTrustHtml: Method này gọi DomSanitizer.bypassSecurityTrustHtml() sau khi DOMPurify đã làm sạch. Không được truyền HTML chưa sanitize vào bypassSecurityTrustHtml trực tiếp trong component — luôn dùng qua service này.

⚠️ hasXSSThreats là heuristic: Method so sánh string gốc với string đã sanitize. Có thể trả về true kể cả khi HTML chỉ khác nhau về whitespace hoặc attribute order — không phải 100% chính xác cho mọi trường hợp.

⚠️ sanitizeRichText cho phép iframe: Mode rich text thêm iframe vào allowed tags. Chỉ dùng khi thực sự cần embed video/content từ trusted sources (YouTube, Vimeo). Không dùng để sanitize user-generated content không kiểm soát được.