-
-
Notifications
You must be signed in to change notification settings - Fork 16
Description
Summary
The @airframes/acars-decoder package currently depends on Node.js built-in modules (buffer, zlib/stream via minizlib) which require polyfills when used in browser environments. This forces downstream browser applications to include vite-plugin-node-polyfills (or equivalent Webpack polyfills), adding significant bundle size and introducing transitive security vulnerabilities that cannot be resolved by consumers.
Current Impact
In the airframesio/frontend-spa-vue2 frontend, @airframes/acars-decoder is the sole reason Node.js polyfills exist:
buffer— used viarequire("buffer")forBuffer.from()in ACARS message decompressionzlib/stream/string_decoder/events— used transitively viaminizlibfor zlib decompressionprocess/global— required byminipass(dependency ofminizlib)
Security consequences
The polyfill chain pulls in node-stdlib-browser → crypto-browserify → elliptic, which has 12 known vulnerabilities (6 low, 6 moderate) that downstream consumers cannot fix or override — they are transitive dependencies locked by the polyfill infrastructure.
Bundle size consequences
The polyfills add ~50-80KB gzipped to the frontend bundle for functionality that modern browsers provide natively.
Proposed Migration
1. Replace Buffer.from() with Uint8Array + TextEncoder/TextDecoder
// Before
const buf = Buffer.from(data, 'base64');
const str = buf.toString('utf-8');
// After
const bytes = Uint8Array.from(atob(data), c => c.charCodeAt(0));
const str = new TextDecoder().decode(bytes);2. Replace minizlib/zlib with DecompressionStream (Web Streams API)
// Before (Node zlib via minizlib)
const { Inflate } = require('minizlib');
// After (Web API — supported in all modern browsers and Node 18+)
async function decompress(compressed: Uint8Array): Promise<Uint8Array> {
const stream = new Response(compressed).body!
.pipeThrough(new DecompressionStream('deflate'));
return new Uint8Array(await new Response(stream).arrayBuffer());
}Alternatively, use the pako library (already used by many ACARS tools) which is a pure JavaScript zlib implementation with zero Node.js dependencies.
3. If any crypto operations exist, use Web Crypto API
// Before
const crypto = require('crypto');
const hash = crypto.createHash('md5').update(data).digest('hex');
// After
const hashBuffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(data));
const hash = Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');Benefits
- Eliminates all 12 transitive vulnerabilities in downstream browser consumers
- Reduces bundle size by ~50-80KB gzipped (no more polyfills needed)
- Simplifies consumer build configs — no need for
vite-plugin-node-polyfillsor Webpack node polyfill plugins - Works in all environments — Web APIs are available in modern browsers, Node 18+, Deno, Bun, and edge runtimes (Cloudflare Workers, etc.)
- Future-proof — Node.js polyfill ecosystem is increasingly unmaintained
Environment Compatibility
All proposed replacement APIs are available in:
- Chrome 80+, Firefox 113+, Safari 14.1+ (DecompressionStream)
- Node.js 18+ (Web Streams, TextEncoder/TextDecoder, Web Crypto)
- All current LTS Node.js versions
Context
This was identified during a comprehensive audit of the frontend-spa-vue2 codebase. The frontend has been fully modernized (Vite 8, TypeScript 6, ESLint 10, zero lint warnings) but the 12 remaining npm audit vulnerabilities are all caused by the Node.js polyfill chain required solely by this package.