{"id":36397602,"url":"https://github.com/atgreen/cl-sanitize-html","last_synced_at":"2026-02-01T22:33:30.688Z","repository":{"id":322116648,"uuid":"1088135323","full_name":"atgreen/cl-sanitize-html","owner":"atgreen","description":"A Common Lisp library for sanitizing HTML using OWASP-style policies","archived":false,"fork":false,"pushed_at":"2026-01-04T16:37:34.000Z","size":22,"stargazers_count":9,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-18T16:16:27.024Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atgreen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-02T11:40:30.000Z","updated_at":"2026-01-04T18:25:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/atgreen/cl-sanitize-html","commit_stats":null,"previous_names":["atgreen/cl-sanitize-html"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/atgreen/cl-sanitize-html","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atgreen%2Fcl-sanitize-html","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atgreen%2Fcl-sanitize-html/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atgreen%2Fcl-sanitize-html/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atgreen%2Fcl-sanitize-html/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atgreen","download_url":"https://codeload.github.com/atgreen/cl-sanitize-html/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atgreen%2Fcl-sanitize-html/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28993253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T22:01:47.507Z","status":"ssl_error","status_checked_at":"2026-02-01T21:58:37.335Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-11T16:00:22.554Z","updated_at":"2026-02-01T22:33:30.673Z","avatar_url":"https://github.com/atgreen.png","language":"Common Lisp","readme":"# cl-sanitize-html\n\nOWASP-style HTML sanitization library for Common Lisp, designed for safely rendering untrusted HTML content (like HTML emails or user-generated content).\n\n## Features\n\n- **Whitelist-based sanitization** - Only explicitly allowed tags and attributes pass through\n- **Multiple security policies** - Default, Strict, and Email policies included\n- **XSS prevention** - Blocks script tags, event handlers, javascript: URLs, and other attack vectors\n- **CSS sanitization** - Optional CSS property filtering for email content\n- **Safe defaults** - Automatically adds `rel=\"noopener noreferrer\"` and `target=\"_blank\"` to links\n- **Plump-based** - Built on the robust Plump HTML parser\n- **Well-tested** - Comprehensive test suite covering OWASP attack vectors\n\n## Quick Start\n\n```lisp\n(use-package :sanitize-html)\n\n;; Basic usage with default policy\n(sanitize \"\u003cscript\u003ealert('XSS')\u003c/script\u003e\u003cp\u003eHello\u003c/p\u003e\")\n;; =\u003e \"\u003cp\u003eHello\u003c/p\u003e\"\n\n;; Remove event handlers\n(sanitize \"\u003ca href='#' onclick='alert(1)'\u003eClick me\u003c/a\u003e\")\n;; =\u003e \"\u003ca href=\\\"#\\\" rel=\\\"noopener noreferrer\\\" target=\\\"_blank\\\"\u003eClick me\u003c/a\u003e\"\n\n;; Use email policy for HTML emails\n(sanitize \"\u003ctable\u003e\u003ctr\u003e\u003ctd bgcolor='red'\u003eCell\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\" *email-policy*)\n;; =\u003e \"\u003ctable\u003e\u003ctr\u003e\u003ctd bgcolor=\\\"red\\\"\u003eCell\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\"\n```\n\n## Security Policies\n\n### Default Policy (*default-policy*)\n\nBalanced security and usability for general web content:\n- **Allowed tags**: Common formatting and semantic tags (p, div, span, a, strong, em, lists, tables, etc.)\n- **Allowed protocols**: http, https, mailto, ftp\n- **Inline styles**: Blocked\n- **Comments**: Removed\n\n### Strict Policy (*strict-policy*)\n\nMaximum security with minimal formatting:\n- **Allowed tags**: Only basic formatting (a, b, em, strong, ul, ol, li, p, br, code, pre)\n- **Allowed protocols**: https, mailto only\n- **Very limited attributes**: Only href, title, and class\n\n### Email Policy (*email-policy*)\n\nDesigned for HTML emails with legacy formatting:\n- **Allowed tags**: All email-safe tags including tables, font, center\n- **Allowed protocols**: http, https, mailto, cid (inline images), data (base64)\n- **Inline styles**: Allowed with filtered CSS properties\n- **Table attributes**: bgcolor, cellpadding, cellspacing, etc.\n\n## API\n\n### Main Functions\n\n```lisp\n(sanitize html-string \u0026optional policy)\n(sanitize-html html-string \u0026optional policy)\n```\n\nSanitize HTML string according to policy. Returns sanitized HTML string.\n\n**Parameters:**\n- `html-string` - String containing HTML to sanitize\n- `policy` - Security policy to apply (defaults to `*default-policy*`)\n\n**Returns:** Sanitized HTML string\n\n**Example:**\n```lisp\n(sanitize \"\u003cscript\u003ebad\u003c/script\u003e\u003cp\u003egood\u003c/p\u003e\")\n;; =\u003e \"\u003cp\u003egood\u003c/p\u003e\"\n```\n\n### Utility Functions\n\n```lisp\n(safe-url-p url \u0026optional policy)\n```\n\nCheck if URL uses a safe protocol according to policy.\n\n```lisp\n(sanitize-url url \u0026optional policy)\n```\n\nReturn URL if safe, nil otherwise.\n\n### Custom Policies\n\n```lisp\n(make-policy \u0026key allowed-tags allowed-attributes allowed-protocols\n                  allowed-css-properties remove-comments escape-cdata)\n```\n\nCreate a custom security policy.\n\n**Example:**\n```lisp\n(defparameter *my-policy*\n  (make-policy\n   :allowed-tags '(\"p\" \"br\" \"a\" \"strong\" \"em\")\n   :allowed-attributes '((\"a\" . (\"href\" \"title\")))\n   :allowed-protocols '(\"https\")\n   :remove-comments t))\n\n(sanitize html-string *my-policy*)\n```\n\n## Security Features\n\n### XSS Prevention\n\n- ✅ Script tags removed\n- ✅ Event handlers (onclick, onload, etc.) removed\n- ✅ javascript: protocol blocked\n- ✅ data: protocol blocked (except in email policy with validation)\n- ✅ Inline styles blocked (except in email policy with CSS filtering)\n- ✅ Form elements blocked\n- ✅ iframe/object/embed blocked\n- ✅ meta/link/style/base blocked\n\n### CSS Injection Prevention\n\n- CSS properties filtered by whitelist (email policy only)\n- `javascript:`, `expression()`, `@import` blocked in CSS values\n- `behavior:` property blocked (IE-specific XSS vector)\n\n### Safe Defaults\n\n- Links automatically get `rel=\"noopener noreferrer\"` (prevents tabnabbing)\n- Links automatically get `target=\"_blank\"` (open in new tab)\n- Comments removed by default\n- CDATA sections escaped by default\n\n## Email HTML Example\n\n```lisp\n(defun render-email-html (email-html-body)\n  \"Safely render HTML email content\"\n  (sanitize-html email-html-body *email-policy*))\n\n;; Typical email HTML with inline styles and tables\n(render-email-html \"\n  \u003ctable border='1' cellpadding='10'\u003e\n    \u003ctr\u003e\n      \u003ctd bgcolor='#ff0000'\u003e\n        \u003cp style='color: white; font-size: 16px'\u003e\n          Welcome to our newsletter!\n        \u003c/p\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/table\u003e\n  \u003cp\u003e\n    \u003ca href='https://example.com'\u003eVisit our site\u003c/a\u003e\n  \u003c/p\u003e\n\")\n```\n\n## Running Tests\n\n```lisp\n(asdf:test-system :sanitize-html)\n```\n\nOr manually:\n\n```lisp\n(asdf:load-system :sanitize-html/tests)\n(fiveam:run! :sanitize-html-tests)\n```\n\n## Dependencies\n\n- **plump** - Lenient HTML/XML parser\n- **lquery** - DOM manipulation\n- **cl-ppcre** - Regular expressions for CSS parsing\n- **alexandria** - Utilities library\n\n**Test dependencies:**\n- **fiveam** - Unit testing framework\n\n## Architecture\n\n1. **Parser** - Uses Plump to parse HTML into a DOM tree\n2. **Tree Walker** - Recursively visits each node in the DOM\n3. **Policy Enforcer** - Checks each element/attribute against whitelist\n4. **Sanitizer** - Removes or modifies unsafe content\n5. **Serializer** - Converts sanitized DOM back to HTML string\n\n## Comparison with Other Libraries\n\n| Feature | sanitize-html | bluemonday (Go) | ammonia (Rust) | bleach (Python) |\n|---------|------------------|-----------------|----------------|-----------------|\n| Whitelist-based | ✅ | ✅ | ✅ | ✅ |\n| Multiple policies | ✅ | ✅ | ✅ | ❌ |\n| CSS sanitization | ✅ | ✅ | ✅ | ✅ |\n| URL validation | ✅ | ✅ | ✅ | ✅ |\n| Link safety | ✅ | ✅ | ❌ | ❌ |\n| OWASP-aligned | ✅ | ✅ | ✅ | ✅ |\n\n## References\n\n- [OWASP XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\n- [HTML5 Security Cheat Sheet](https://html5sec.org/)\n- [Plump Documentation](https://shinmera.github.io/plump/)\n\n## Author and License\n\n``sanitize-html`` was written by [Anthony Green](https://github.com/atgreen)\nand is distributed under the terms of the MIT license.\n","funding_links":[],"categories":["Interfaces to other package managers"],"sub_categories":["Isomorphic web frameworks"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatgreen%2Fcl-sanitize-html","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatgreen%2Fcl-sanitize-html","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatgreen%2Fcl-sanitize-html/lists"}