Releases: SINENSIA/markdown-security
Releases · SINENSIA/markdown-security
v2.3.0
Added
ALLOWLIST_FILEenv var: when set, the contents of the referenced JSON file replace the built-insanitize-htmlconfiguration. Lets different consumers run with different policies without forking. Malformed input fails fast at startup.lib/allowlist.jsmodule exportingDEFAULT_ALLOWLIST(the previous hardcoded config) andloadAllowlist({ path })for tests and programmatic use.RATE_LIMIT_RPMenv var: opt-in per-IP rate limiting onPOST /validate(requests per minute). Disabled by default./healthand/openapi.jsonare never rate-limited. 429 responses includeretry-afterandratelimit-*headers and are documented in the OpenAPI spec.- CycloneDX 1.6 SBOM (
sbom.cdx.json) generated from the production lockfile via@cyclonedx/cyclonedx-npm. Newnpm run sbomscript for local use, and a.github/workflows/sbom.ymlworkflow that runs onrelease: published(plusworkflow_dispatchfor backfilling) and uploads the SBOM as a release asset.
v2.2.0
Added
- Strict request-body validation against the OpenAPI
ValidateRequestschema, powered byajv.POST /validatenow returns a structured 400 with per-field violations for missing/extra fields, wrong types, andminLengthviolations. detailsarray on 400 responses ([{ field, message }, ...]). Documented in the OpenAPIErrorResponseschema.
Changed
- The 400 error message for invalid input is now
"Invalid request". The previous condition (missing/emptymarkdown) is still rejected, but through the schema validator rather than an ad-hoc check. - 2.1.0 documented
additionalProperties: falseandtype: stringinopenapi.jsonwithout enforcing them. 2.2.0 closes that gap: clients that already conformed to the published schema are unaffected; clients that sent extra fields or coerced types will start receiving 400s with details.
v2.1.0
Added
GET /healthliveness probe returning{ "status": "ok" }. The DockerHEALTHCHECKnow hits this endpoint instead ofPOST /validate, removing the sanitizer call from the probe path.GET /openapi.jsonserves an OpenAPI 3.1 specification covering every public endpoint, request/response schemas, status codes, and thex-request-idheader.- Structured JSON logging via
pino+pino-http. NewLOG_LEVELenv var (defaultinfo, forced tosilentunderNODE_ENV=test). x-request-idcorrelation header. Echoed when the incoming value matches^[a-zA-Z0-9_.-]{1,128}$, otherwise a server-generated UUID. Surfaced on every endpoint and included in every log line.- Property-based fuzzing suite (
fast-check) exercising sanitizer invariants: no dangerous tags ever leak tosanitized, sanitization is idempotent, the front matter never bleeds intosanitized, and HTML inside the front matter always flipssafetofalse. - CI workflow on GitHub Actions: test matrix (Node 20/22/24),
npm audit --audit-level=high --omit=devjob, CodeQL withsecurity-extendedqueries, concurrency cancellation on PR pushes. - Dependabot configuration for
npmandgithub-actionsecosystems. SECURITY.mdwith supported versions and private vulnerability reporting through GitHub Security Advisories.engines: { node: ">=20" }inpackage.jsonto align the documented floor with the CI matrix.- Regression tests for the 256kb body limit (413) and
javascript:/data:/vbscript:URL scheme stripping.
Changed
DockerfileHEALTHCHECKswitched from POSTing to/validateto GETting/health.- Test descriptions and code comments translated to English for end-to-end consistency.
- README updated to document the new endpoints, the
LOG_LEVELknob, and the request-correlation header.
Removed
- Dead
PROHIBITED_TAGSconstant inserver.js. The allowlist passed tosanitize-htmlwas always the source of truth.
v2.0.0
Breaking changes
POST /validate no longer concatenates YAML front matter back into sanitized. Front matter is now returned in a dedicated frontMatter field (raw, untrusted), and safe reflects both the body and the front matter.
Why: in 1.x, HTML inside the YAML block bypassed the sanitizer while safe still reported true.
Migration: consumers that read the YAML block from sanitized must now read it from frontMatter. If front matter is rendered as HTML, sanitize it on the consumer side.