# What changed in plist

> 15 changes in plist 5 from its official release notes, upgrade guides and advisories: 1 breaking, 1 security, 3 new APIs and options. Each one cited. Sources checked 2026-11-06. HTML: https://unstale.sh/npm/plist/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## plist 5

### Breaking changes

- build() now skips null values, matching undefined behavior and the Apple plist DTD; parsing <null/> remains supported for backwards compatibility. (5.0.0) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.0)

### Security

- Prevents uncontrolled resource consumption by parsing multiply referenced objects only once, rejecting circular references, and validating trailer, offset table, and object references against input bounds. (5.0.1) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.1)

### New APIs and options

- Adds an API for writing binary plists. (5.0.0) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.0)
- Adds an API for reading binary plists. (5.0.0) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.0)
- Adds support for parsing OpenStep/ASCII plists. (5.0.0) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.0)

### Performance

- Bundlers supporting the browser export condition use browser-native parsing and XML-building implementations, reducing bundle size by eliminating @xmldom/xmldom and xmlbuilder. (5.0.0) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.0)

### Behavior and default changes

- parse() now auto-detects XML, binary, and OpenStep plist formats. (5.0.0) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.0)

### Tooling

- The project is rewritten in TypeScript and now provides full type declarations. (5.0.0) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.0)

### Fixes and other changes

- Browser build() emits empty strings as <string/> to match Node build() output. (5.0.1) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.1)
- Browser build() escapes carriage returns so strings and keys containing CR survive a round-trip. (5.0.1) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.1)
- Fixes double indentation in browser build() output. (5.0.1) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.1)
- XML build() preserves sub-second precision when serializing Date values instead of silently dropping non-zero milliseconds. (5.0.1) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.1)
- XML build() emits integer-valued numbers with absolute values at least 1e21 as <real>, preventing corruption on a build-to-parse round-trip. (5.0.1) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.1)
- Adds a default condition to the exports map for VSCode compatibility. (5.0.1) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.1)
- Fixes exponential parse blowup on deeply nested plist files caused by eagerly evaluating dict-parser error message arguments. (5.0.0) — [release notes](https://github.com/TooTallNate/plist.js/releases/tag/plist%405.0.0)
