marked does not sanitize what it parses, and its package has no CommonJS entry
A markdown parser and compiler. Built for speed.
At a glance
- What is it?
- marked is a JavaScript markdown parser that turns text into HTML without caching, ships a CLI and a browser build, and states in a warning that the output is unsanitized. It is a compiler rather than a rendering layer, which means sanitising and caching are both your code to write.
- Who is it for?
- marked fits if you want the whole Markdown specification parsed quickly, need the same code in Node and in the browser, and are willing to own the two things it deliberately leaves out. Sanitising the output is not optional for anything a user can type, and the project says so plainly.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The usage section opens with a warning, not an example
The most important line in the file is the one that says marked does not sanitize the output HTML. The advice is to run a sanitize library over the output, naming DOMPurify as the recommended choice and also sanitize-html and insane, and the single line of code shown wraps the parse call inside a sanitize call. Two things follow from that placement. The fix is a second dependency you have to choose and add yourself, because marked ships no sanitiser of its own. And the cleaning happens on the output rather than on the input, so the pipeline is parse then clean, and any call site in your application that invokes the parser without the cleaning step is an injection point. On a documentation site where the author is you, that is an inconvenience. On a comment renderer or a wiki that accepts markdown from anyone, that call is the entire security model, and it is your code holding it up rather than the library's.
DOMPurify.sanitize(marked.parse(``));No caching means every render pays for the parse again
One of the listed characteristics is that marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time. Read that as two separate properties. No caching means every call re-reads and re-parses the text, so a page that renders the same document on each navigation pays the full parse each time unless you put a cache in front of it yourself. No long blocking means the parser is not built to sit in front of a very large document inside a synchronous server request, and if you hand it one the latency lands on your request rather than somewhere else. The project also describes itself as light-weight while implementing all the markdown features from the supported flavours and specifications, so the scope is the full specification and not a convenient subset. The practical conclusion is narrow: the caching layer, if your render path needs one, is code you write, and marked is the thing underneath it.
npm install -g markednpm install markedBoth the main and the module entry point at the same ESM file
The package manifest is ESM-first in a way that matters if you are on CommonJS. The type field is module, and both the main field and the module field point at the same file, the ESM build, with types resolved from a declaration file. The exports map offers one default entry, also the ESM build, plus an explicit subpath for the CLI binary and one for the package manifest. The UMD build exists but is not an entry point: it is reachable through the browser field or by importing its path directly, which is exactly what the browser example does with a script tag pointing at a UMD file on a CDN. So a project still calling require has nothing to resolve, and would need a dynamic import instead. Bundlers and Node receive identical code rather than separate builds, which is simpler but removes the escape hatch. Note also that the two documented install lines cover the CLI and a bundler, not a plain script tag; the browser route in the documentation is a CDN URL.
import { marked } from 'marked';
const html = marked.parse('# Marked in Node.js');
console.log(html);Three directories ship and everything else stays in the repository
The publishing file list names the binary directory, the library output directory, and the man directory, and that is the entire surface a consumer can reach. The repository root also holds an api directory, a docs directory, a source directory, a test directory, an esbuild configuration, an eslint configuration, two TypeScript configurations, a devcontainer definition, and a Vercel configuration, none of which you can import after installing. Two of those entries say something about how the project is policed. A separate type test configuration sits next to the main one, and the development dependencies include a tool that checks whether a package's type entry points resolve correctly, which is a project treating its own declaration output as something to test. A man directory paired with a man entry in the manifest means the command line tool ships with a manual page. The publishing configuration also requests provenance, so the published artifacts carry a build attestation.
# Example with stdin input
$ marked -o hello.html
hello world
^D
$ cat hello.html
<p>hello world</p>Node support tracks the release schedule rather than a stated range
The compatibility statement is short and contains no version numbers. Node.js support is limited to current and LTS releases, and the file adds that end of life versions may become incompatible with marked at any point in time. That is a different kind of promise from a stated minimum, because the floor moves with Node's own schedule and nobody in your organisation controls it. If a legacy service is pinned to an old runtime, the constraint does not arrive as an install failure; it arrives as a marked upgrade that breaks that service for reasons that have nothing to do with your code. On the browser side the stated target is the Baseline Widely Available level, which is a moving compatibility definition rather than a list of browser versions, so support follows the baseline as the platform changes. Neither statement tells you which marked version first dropped a given runtime, so if that matters you have to find it in the changelog.
# Print all options
$ marked --helpTwo copyright lines are why the licence does not resolve automatically
The licence is where the repository metadata and the file itself disagree. The manifest declares MIT, and the README closes with two copyright lines, one for MarkedJS covering 2018 onward and one for Christopher Jeffrey covering 2011 to 2018, both marked as MIT. That is accurate history, since the project changed hands, and it is also the reason automated licence detection reports no recognised identifier for this repository: a classifier reading a file with two holders and two date ranges has nothing it can confidently label. Nothing about the grant changes, because the terms are MIT either way, but a compliance tool in your organisation that blocks packages whose licence does not resolve will stop here for a reason that is entirely clerical. Opening the LICENSE file settles the question in a minute. The repository does carry one, alongside a security policy, a change log, and a semantic release configuration that automates version bumps.
A clone has nothing to run, because the library directory is build output
Every path the documentation tells you to import lives in a library directory that is not among the top-level entries of the repository, because that directory is produced by the build. The ESM and UMD files are assembled by the esbuild configuration, and the UMD wrapper in particular comes from a dedicated plugin, so the global name the browser example relies on is a build artifact rather than a constant written in the source. To use marked from a checkout you have to run the build, and the build depends on the toolchain in the development dependencies. That is the normal arrangement for a published library, and it is worth stating plainly because every example in the documentation points at built files. What the root also reveals is how releases happen: a semantic release configuration with the matching plugins, the version currently at 18.0.14, and patches published on 2026-09-07, 2026-09-12, and 2026-09-22, so the newest tag moves within a single month.
Editorial conclusion
marked fits if you want the whole Markdown specification parsed quickly, need the same code in Node and in the browser, and are willing to own the two things it deliberately leaves out. Sanitising the output is not optional for anything a user can type, and the project says so plainly. Caching is yours if a document is parsed more than once. Before you adopt it, confirm your build runs a current or LTS Node release, since end of life versions can stop working for reasons that have nothing to do with your code, and confirm your project can consume an ESM-only package, because there is no CommonJS entry to require.
Frequently asked questions
What does "marked" mean?
In this repository marked is a markdown parser and compiler, described as built for speed, published on npm as marked and documented at marked.js.org. It is MIT licensed and provides a library entry, a command line binary with a man page, and a browser build. It parses markdown into HTML and does not sanitize that HTML.
Does marked sanitize the HTML it produces?
No. The project states plainly that marked does not sanitize the output HTML and recommends running a sanitize library over the output, naming DOMPurify as the recommended choice, with sanitize-html and insane as alternatives. The documented pattern wraps the parse call inside a sanitize call, so both steps are yours to add.
How do I install marked?
Two lines are documented: npm install -g marked for the command line tool, and npm install marked for use in a project. The browser route is not an npm install at all but a script tag pointing at the UMD build on a CDN, or an ES module import from the same CDN. The CLI reads standard input and writes with an output flag.
Which Node.js versions does marked support?
Only current and LTS Node.js versions, and the project warns that end of life versions may become incompatible at any point in time. For browsers the stated target is the Baseline Widely Available level, so support follows that definition rather than a fixed version list. The current release is 18.0.14, published 2026-09-22.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/markedjs-marked)