PHPackages                             piplup/sanitize - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. piplup/sanitize

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

piplup/sanitize
===============

WordPress-like sanitization and escaping utilities for PHP — framework-agnostic, secure by design.

v1.1.0(3mo ago)01MITPHPPHP ^8.1

Since Apr 19Pushed 3mo agoCompare

[ Source](https://github.com/sadik-malik/piplup-sanitize-php)[ Packagist](https://packagist.org/packages/piplup/sanitize)[ RSS](/packages/piplup-sanitize/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (1)Versions (2)Used By (0)

piplup/sanitize
===============

[](#piplupsanitize)

A **framework-agnostic PHP 8.1+ Composer library** providing WordPress-style sanitization and escaping utilities — rebuilt on modern PHP standards, without any WordPress dependency.

---

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Quick Start](#quick-start)
- [API Reference](#api-reference)
    - [Core](#core)
    - [TextSanitizer](#textsanitizer)
    - [FileSanitizer](#filesanitizer)
    - [EmailSanitizer](#emailsanitizer)
    - [UrlSanitizer](#urlsanitizer)
    - [HtmlEscaper](#htmlescaper)
    - [JsEscaper](#jsescaper)
    - [Kses](#kses)
    - [AllowedHtml presets](#allowedhtml-presets)
    - [StringUtils](#stringutils)
    - [NumberUtils](#numberutils)
    - [Global helper functions](#global-helper-functions)
- [Security Model](#security-model)
- [Testing](#testing)
- [Requirements](#requirements)

---

Installation
------------

[](#installation)

```
composer require piplup/sanitize
```

The `ext-mbstring` PHP extension is required. Installing `ext-intl` is strongly recommended — it enables full Unicode transliteration in `StringUtils::removeAccents()`.

---

Quick Start
-----------

[](#quick-start)

### Class-based (recommended)

[](#class-based-recommended)

```
use Piplup\Sanitize\Sanitize\TextSanitizer;
use Piplup\Sanitize\Escape\HtmlEscaper;
use Piplup\Sanitize\Kses\Kses;
use Piplup\Sanitize\Kses\AllowedHtml;

// Sanitize incoming data
$title   = TextSanitizer::sanitizeTextField($_POST['title']);
$content = $_POST['content'];  // raw, will be filtered on output

// Escape on the way out
echo '' . HtmlEscaper::escHtml($title) . '';

// Filter HTML through an allow-list
echo Kses::filter($content, AllowedHtml::post());
```

### WordPress-style global helpers

[](#wordpress-style-global-helpers)

The library ships optional global functions that mirror WordPress's API. They are auto-loaded by Composer when the `"files"` entry is present in `composer.json`.

```
$title   = sanitize_text_field($_POST['title']);
$content = wp_kses_post($_POST['content']);

echo '' . esc_html($title) . '';
echo esc_url($url);
```

> **Tip:** Remove the `"files"` key from `composer.json` if you prefer to avoid global function pollution and use the classes directly instead.

---

API Reference
-------------

[](#api-reference)

### Core

[](#core)

#### `Encoding` — `Piplup\Sanitize\Core\Encoding`

[](#encoding--piplupsanitizecoreencoding)

Low-level UTF-8 helpers. Called internally by every other class.

MethodDescription`toUtf8(string): string`Ensure valid UTF-8; replace invalid bytes`isValidUtf8(string): bool`Check validity without modifying`stripNullBytes(string): string`Remove `\x00` bytes`stripControlCharacters(string): string`Remove C0 controls (except HT, LF, CR)`byteLength(string): int`Raw byte count`charLength(string): int`Unicode character count#### `Normalization` — `Piplup\Sanitize\Core\Normalization`

[](#normalization--piplupsanitizecorenormalization)

MethodDescription`normalizeLineEndings(string): string`Normalize `\r\n` / `\r` → `\n``collapseWhitespace(string): string`Collapse runs of horizontal space; trim`removeAllWhitespace(string): string`Strip every whitespace character`trimUnicode(string): string`Trim including non-breaking spaces`toLower(string): string`Multibyte-safe lowercase`toUpper(string): string`Multibyte-safe uppercase`clean(string): string`toUtf8 + stripNullBytes + stripControl + collapse---

### TextSanitizer

[](#textsanitizer)

`Piplup\Sanitize\Sanitize\TextSanitizer`

```
use Piplup\Sanitize\Sanitize\TextSanitizer;

TextSanitizer::sanitizeTextField('  Hello  ');   // → 'Hello'
TextSanitizer::sanitizeTextareaField("line1\r\nline2");  // → "line1\nline2"
TextSanitizer::sanitizeKey('My Key!');                   // → 'my-key'  (wait: 'mykey')
TextSanitizer::sanitizeTitle('Post Title');     // → 'Post Title'
TextSanitizer::sanitizeSlug('Hello Wörld');              // → 'hello-world'
```

MethodWordPress equivalent`sanitizeTextField(string): string``sanitize_text_field()``sanitizeTextareaField(string): string``sanitize_textarea_field()``sanitizeKey(string): string``sanitize_key()``sanitizeTitle(string): string``sanitize_title()` (display)`sanitizeSlug(string): string``sanitize_title()` (save/slug)---

### FileSanitizer

[](#filesanitizer)

`Piplup\Sanitize\Sanitize\FileSanitizer`

```
use Piplup\Sanitize\Sanitize\FileSanitizer;

FileSanitizer::sanitizeFileName('../../etc/passwd');  // → 'etcpasswd'
FileSanitizer::sanitizeFileName('My Photo.JPG');      // → 'My-Photo.jpg'
FileSanitizer::sanitizeFileName('CON.txt');           // → '_CON.txt'
```

MethodWordPress equivalent`sanitizeFileName(string): string``sanitize_file_name()`Handles path traversal, null bytes, Windows-reserved names, forbidden filesystem characters, and normalises the extension to lowercase.

Note: `FileSanitizer::sanitizeFileName()` strips dangerous embedded extensions from the base name to prevent multi-extension bypasses (for example `shell.php8.jpg` → `shell.jpg`). The blocklist includes versioned PHP suffixes and other server-side/executable extensions (for example: `php2`, `php6`, `php8`, `php9`, `phtml`, `phar`, `shtml`, `cgi`, `pl`, `py`, `rb`, `sh`, `exe`, `bat`, `ps1`, `htaccess`). This reduces risk but does not replace server-side MIME/type validation; validate uploads with `finfo` and prefer an explicit allowlist of permitted extensions when possible.

---

### EmailSanitizer

[](#emailsanitizer)

`Piplup\Sanitize\Sanitize\EmailSanitizer`

```
use Piplup\Sanitize\Sanitize\EmailSanitizer;

EmailSanitizer::sanitizeEmail('USER@EXAMPLE.COM');  // → 'user@example.com'
EmailSanitizer::sanitizeEmail('not-an-email');      // → ''
EmailSanitizer::isValidEmail('user@example.com');   // → true
```

MethodWordPress equivalent`sanitizeEmail(string): string``sanitize_email()``isValidEmail(string): bool`*(no WP equivalent)*---

### UrlSanitizer

[](#urlsanitizer)

`Piplup\Sanitize\Sanitize\UrlSanitizer`

```
use Piplup\Sanitize\Sanitize\UrlSanitizer;

// For HTML attributes — output is HTML-encoded
UrlSanitizer::escUrl('https://example.com/?a=1&b=2');
// → 'https://example.com/?a=1&amp;b=2'

// For HTTP redirects / storage — NOT HTML-encoded
UrlSanitizer::escUrlRaw('https://example.com/?a=1&b=2');
// → 'https://example.com/?a=1&b=2'

// Dangerous protocols rejected
UrlSanitizer::escUrl('javascript:alert(1)');  // → ''

// Custom protocol allow-list
UrlSanitizer::escUrl('myapp://deep-link', ['myapp']);
```

MethodWordPress equivalent`escUrl(string $url, array $allowedProtocols = [], bool $allowProtocolRelative = false): string``esc_url()``escUrlRaw(string $url, array $allowedProtocols = [], bool $allowProtocolRelative = false): string``esc_url_raw()`Default allowed protocols: `http`, `https`, `ftp`, `ftps`, `mailto`, `news`, `irc`, `gopher`, `nntp`, `feed`, `telnet`, `mms`, `rtsp`, `sms`, `svn`, `tel`, `fax`, `xmpp`, `webcal`.

Notes:

- `UrlSanitizer` decodes HTML entities and numeric character references before checking the scheme (defeats obfuscations such as `javascript&#58;`), strips null bytes and control/whitespace characters, and percent-encodes unsafe characters while preserving existing `%XX` escapes.
- Protocol-relative URLs (`//example.com/path`) are treated as external and are rejected by default; pass `$allowProtocolRelative = true` to allow them explicitly.

---

### CssSanitizer

[](#csssanitizer)

`Piplup\Sanitize\Sanitize\CssSanitizer`

```
use Piplup\Sanitize\Sanitize\CssSanitizer;

// Default usage (Kses::filter() passes ['same-origin'] by default):
$clean = CssSanitizer::sanitize('cursor: url("/c.cur"), auto', ['same-origin']);

// Allow specific hosts for url(...) tokens:
$clean = CssSanitizer::sanitize($css, ['example.com', 'cdn.example.com']);
```

MethodNotes`sanitize(string, array $allowedUrlHosts = []): string`The optional second parameter controls which hosts are permitted in `url()` tokens. When passed `['same-origin']` (used by `Kses::filter()` by default), absolute URLs that include a scheme or host are removed and only relative URLs are allowed. Passing a non-empty list allows only those hostnames; an empty array (default) permits all cleaned URLs.---

### HtmlEscaper

[](#htmlescaper)

`Piplup\Sanitize\Escape\HtmlEscaper`

```
use Piplup\Sanitize\Escape\HtmlEscaper;

echo ''         . HtmlEscaper::escHtml($text)      . '';
echo '';
echo ''  . HtmlEscaper::escTextarea($val)   . '';

// Undo escaping (do NOT echo result directly into HTML)
$decoded = HtmlEscaper::decodeEntities($encoded);
```

MethodWordPress equivalent`escHtml(string): string``esc_html()``escAttr(string): string``esc_attr()``escTextarea(string): string``esc_textarea()``decodeEntities(string): string`*(utility)*---

### JsEscaper

[](#jsescaper)

`Piplup\Sanitize\Escape\JsEscaper`

```
use Piplup\Sanitize\Escape\JsEscaper;

// Embed a PHP string in a JS string literal
$safe = JsEscaper::escJs($userInput);
// Use in template: var msg = '';

// Serialize a PHP value as JSON for inline script
$json = JsEscaper::jsonEncode(['key' => $value]);
// Use in template: var data = ;
```

MethodWordPress equivalent`escJs(string): string``esc_js()``jsonEncode(mixed): string``wp_json_encode()``jsonEncode()` automatically escapes ``, `&`, `'`, `"` so the output is safe inside a `` block without additional escaping.

---

### Kses

[](#kses)

`Piplup\Sanitize\Kses\Kses`

```
use Piplup\Sanitize\Kses\Kses;
use Piplup\Sanitize\Kses\AllowedHtml;

// Filter with a custom allow-list
$clean = Kses::filter($html, [
  'a'  => ['href' => true, 'title' => true],
  'b'  => [],
  'em' => [],
]);

// Or use a preset
$clean = Kses::filter($html, AllowedHtml::post());
```

MethodWordPress equivalent`Kses::filter(string, array): string``wp_kses()`Uses **DOMDocument** (not regex) for parsing. Event handler attributes (`onclick`, `onerror`, etc.) are **always** stripped regardless of the allow-list. URL-bearing attributes (`href`, `src`, `action`, …) are run through `UrlSanitizer::escUrlRaw()` to block `javascript:` and other dangerous schemes.

Additional notes:

- When an `` element has `target="_blank"` and the allow-list permits the `rel` attribute, `Kses::filter()` will ensure the `rel`value includes `noopener` and `noreferrer` to prevent reverse tabnapping attacks.
- Inline `style` attributes are sanitized via `CssSanitizer::sanitize()`. `Kses::filter()` passes a conservative `['same-origin']` sentinel by default which removes absolute external `url()` tokens from inline CSS (only relative URLs are permitted). If your application legitimately requires external CSS resources, pre-sanitize style values with `CssSanitizer::sanitize($css, ['example.com'])` or modify the sanitizer call to allow specific hosts.

---

### AllowedHtml presets

[](#allowedhtml-presets)

`Piplup\Sanitize\Kses\AllowedHtml`

MethodWordPress equivalentDescription`AllowedHtml::post()``wp_kses_post()` allow-listFull rich-text: headings, links, images, tables, …`AllowedHtml::data()``wp_kses_data()` allow-listMinimal inline: ``, ``, ``, ``, …`AllowedHtml::inline()`*(no direct equivalent)*Inline only, no block elements---

### StringUtils

[](#stringutils)

`Piplup\Sanitize\Utils\StringUtils`

```
use Piplup\Sanitize\Utils\StringUtils;

StringUtils::removeAccents('café');           // → 'cafe'
StringUtils::stripAllTags('Hello');    // → 'Hello'
StringUtils::truncate('Long string…', 10);   // → 'Long str…'
StringUtils::startsWith('Hello', 'He');       // → true
StringUtils::endsWith('Hello', 'lo');         // → true
```

MethodWordPress equivalent`removeAccents(string): string``remove_accents()``stripAllTags(string, bool): string``wp_strip_all_tags()``truncate(string, int, string): string`*(no direct equivalent)*---

### NumberUtils

[](#numberutils)

`Piplup\Sanitize\Utils\NumberUtils`

```
use Piplup\Sanitize\Utils\NumberUtils;

NumberUtils::absint(-5);              // → 5
NumberUtils::absint('3.9');           // → 3
NumberUtils::clampInt(15, 1, 10);     // → 10
NumberUtils::clampFloat(-0.5, 0, 1); // → 0.0
NumberUtils::toFloat('3.14');         // → 3.14
NumberUtils::toInt('42abc');          // → 42
```

MethodWordPress equivalent`absint(mixed): int``absint()`---

### Global helper functions

[](#global-helper-functions)

When the `"files": ["src/functions.php"]` autoload entry is present, the following global functions are available:

FunctionProxies to`sanitize_text_field($v)``TextSanitizer::sanitizeTextField()``sanitize_textarea_field($v)``TextSanitizer::sanitizeTextareaField()``sanitize_key($v)``TextSanitizer::sanitizeKey()``sanitize_title($v)``TextSanitizer::sanitizeTitle()``sanitize_title_with_dashes($v)``TextSanitizer::sanitizeSlug()``sanitize_email($v)``EmailSanitizer::sanitizeEmail()``sanitize_file_name($v)``FileSanitizer::sanitizeFileName()``esc_html($v)``HtmlEscaper::escHtml()``esc_attr($v)``HtmlEscaper::escAttr()``esc_textarea($v)``HtmlEscaper::escTextarea()``esc_js($v)``JsEscaper::escJs()``esc_url($v, $protocols)``UrlSanitizer::escUrl()``esc_url_raw($v, $protocols)``UrlSanitizer::escUrlRaw()``wp_kses($html, $allowed)``Kses::filter()``wp_kses_post($html)``Kses::filter(…, AllowedHtml::post())``wp_kses_data($html)``Kses::filter(…, AllowedHtml::data())``absint($v)``NumberUtils::absint()``remove_accents($v)``StringUtils::removeAccents()``wp_strip_all_tags($v, $breaks)``StringUtils::stripAllTags()`All functions are guarded with `function_exists()` checks so they will not conflict if you load this library alongside WordPress.

---

Security Model
--------------

[](#security-model)

### Escape on output; sanitize on input

[](#escape-on-output-sanitize-on-input)

- **Sanitize** when data enters your system (form submission, API response, file upload). Strip or transform characters that shouldn't be stored.
- **Escape** immediately before output. Encode characters that have special meaning in the target context (HTML, JS, SQL, …).

### What this library does NOT do

[](#what-this-library-does-not-do)

- **SQL escaping** — use parameterised queries / prepared statements.
- **Shell escaping** — use `escapeshellarg()` / `escapeshellcmd()`.
- **Path validation** — use `realpath()` and compare against an allowed base directory.
- **Content-type validation** — validate MIME type with `finfo` for file uploads.
- **DNS / MX validation** — use a dedicated SMTP library to verify deliverability.

### KSES implementation notes

[](#kses-implementation-notes)

- Parsing is done with `DOMDocument` — not regex — to correctly handle adversarial markup.
- `on*` event-handler attributes are blocked unconditionally.
- URL-bearing attributes (`href`, `src`, `action`, `cite`, `formaction`, …) are passed through `UrlSanitizer` to block `javascript:`, `data:`, and `vbscript:` schemes.
- The ``, ``, ``, ``, and `` tags are not included in any preset.

---

Testing
-------

[](#testing)

```
composer install
./vendor/bin/phpunit
```

Generate an HTML coverage report:

```
./vendor/bin/phpunit --coverage-html coverage/
```

The test suite covers:

- XSS payloads (OWASP Top 10 vectors)
- Malformed and adversarial HTML
- Invalid / partial UTF-8 byte sequences
- Null bytes and control characters
- Windows-reserved filenames and path traversal
- Edge cases: empty strings, `null`, booleans, arrays

---

Requirements
------------

[](#requirements)

RequirementVersionPHP^8.1ext-mbstringrequiredext-intloptional (better accent removal)phpunit/phpunit^10 (dev only)License
-------

[](#license)

MIT

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance82

Actively maintained with recent releases

Popularity1

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

96d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/4924096?v=4)[piplup](/maintainers/piplup)[@piplup](https://github.com/piplup)

---

Top Contributors

[![sadik-malik](https://avatars.githubusercontent.com/u/38027249?v=4)](https://github.com/sadik-malik "sadik-malik (9 commits)")

---

Tags

securityhtmlxssEscapesanitizekses

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/piplup-sanitize/health.svg)

```
[![Health](https://phpackages.com/badges/piplup-sanitize/health.svg)](https://phpackages.com/packages/piplup-sanitize)
```

###  Alternatives

[xemlock/htmlpurifier-html5

HTML5 support for HTML Purifier

1053.2M18](/packages/xemlock-htmlpurifier-html5)[htmlawed/htmlawed

Official htmLawed PHP library for HTML filtering

411.2M18](/packages/htmlawed-htmlawed)[erlandmuchasaj/sanitize

A package to sanitize your input.

146.8k](/packages/erlandmuchasaj-sanitize)[soosyze/kses

An HTML/XHTML filter written in PHP. Checks on attribute values. Can be used to avoid Cross-Site Scripting (XSS), Buffer Overflows and Denial of Service attacks, among other things.

1263.6k1](/packages/soosyze-kses)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
