
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
› NodeJS PC/SC API bindings for smart card access on Linux / MacOS / Win32
Docs ↗ | | Overview | | Prerequisites | | Installation | | Usage
import * as pcsc from "pcsc-mini";
const { CardDisposition, CardMode, ReaderStatus } = pcsc;
const client = new pcsc.Client()
.on("reader", onReader)
.start();
function onReader(reader: pcsc.Reader) {
reader.on("change", async status => {
if (!status.has(ReaderStatus.PRESENT)) return;
if (status.hasAny(ReaderStatus.MUTE, ReaderStatus.IN_USE)) return;
const card = await reader.connect(CardMode.SHARED);
console.log(`${await card.state()}`);
const resTx = await card.transmit(
Uint8Array.of(0xca, 0xfe, 0xf0, 0x0d)
);
console.log(resTx);
const codeFeatures = pcsc.controlCode(3400);
const features = await card.control(codeFeatures);
console.log(features);
await card.disconnect(CardDisposition.RESET);
client.stop();
process.exit(0);
});
}
pcsc-mini provides NodeJS bindings to native PC/SC (Personal Computer/Smart Card) APIs:
* MacOS has a separate implementation built on the CryptoTokenKit API.
Pre-built binary packages are available for the following targets.
These are installed as optional dependencies of the main pcsc-mini package (e.g. @pcsc-mini/linux-x86_64-gnu).
| OS | arm64 | x86 | x86_64 |
|---|---|---|---|
Linux ( gnu ) | ✅ | ☑️ | ✅ |
Linux ( musl )1 | ✅ | ☑️ | ✅ |
MacOS | ✅ | N/A | ☑️ |
Windows2 | ☑️ | ⬜️ | ✅ |
✅ Tested & verified • ☑️ Not tested • ⬜️ Not available
1 During testing on Alpine, the PCSC server daemon needed to be started after a reader was connected for detection/monitoring to work and required a restart whenever a reader was disconnected and reconnected.
2 Windows support is limited to a few JS runtimes at the moment (Node.js, Bun, Electron). If additional runtimes are needed, please feel free to open an issue to request it.
| Runtime | Supported Versions |
|---|---|
| NodeJS | v16.x.x, v18.x.x, v20.x.x, v22.x.x v24.x.x |
| OTHERS: | |
| Bun | Tested with v1.2.12 (may work with earlier) |
| Deno | Tested with v2.3.1 (may work with earlier) |
| Electron | v15.0.0+ (Tested up to v36.2.0) |
Required packages:
ccidpcsc-litepcsc-lite-libsdoas apk add ccid pcsc-lite pcsc-lite-libs
To run the server daemon:
doas rc-service pcscd start
Required packages:
libpcsclite1pcscdsudo apt install libpcsclite1 pcscd
To run the server daemon:
sudo systemctl start pcscd
N/A :: MacOS and Windows come pre-installed with smart card support. No additional installation needed.
Bun
bun add pcsc-mini
Deno
deno add npm:pcsc-mini
npm
npm i pcsc-mini
pnpm
pnpm add pcsc-mini
import * as pcsc from "pcsc-mini";
const { CardDisposition, CardMode, ReaderStatus } = pcsc;
// The `Client` emits a "reader" event for each detected device.
const client = new pcsc.Client()
.on("reader", onReader)
.on("error", onError)
.start();
function onError(err: pcsc.Err) {
console.error("Unexpected PCSC error:", err);
client.stop();
// [ Log and exit / attempt `start()` retries with backoff / etc... ]
};
function onReader(reader: pcsc.Reader) {
let card: pcsc.Card | undefined;
console.log(`Reader detected: ${reader}`);
// Each reader emits a "change" event on every reader state change.
reader.on("change", async status => {
if (status.hasAny(ReaderStatus.MUTE, ReaderStatus.IN_USE)) return;
if (!status.has(ReaderStatus.PRESENT)) {
void card?.disconnect(CardDisposition.RESET);
card = undefined;
return;
}
try {
if (!card) card = await reader.connect(CardMode.SHARED);
// Transmit Uint8Array (or NodeJS Buffer) data:
const res = await card.transmit(
Uint8Array.of(0xca, 0xfe, 0xf0, 0x0d)
);
// Use Uint8Array response directly, or via DataView/Buffer:
const vw = new DataView(res.buffer, res.byteOffset, res.length);
const tag = vw.getUint8(0);
const len = vw.getUint16(2);
const val = new Uint8Array(res.buffer, 4, len);
// ...
} catch (err) {
console.error("Card error:", err);
}
});
// "disconnect" is emitted when a reader is no longer detected.
//
// All event listeners will be removed from the now-invalid reader.
// Any reader/card-related state should be disposed of here.
reader.on("disconnect", async () => {
void card?.disconnect(CardDisposition.RESET);
card = undefined;
});
}
[!TIP]
See the E2E test application for more involved usage and error handling.
| Minimum Version | Recommended Version | |
|---|---|---|
| Zig | v0.15.0 | See .zigversion |
| NodeJS | v24.0.0 | See .nvmrc |
| pnpm | v10.0.0 | See package.json |
| OPTIONAL: | ||
| Bun | v1.2.12 | |
| Deno | v2.3.1 |
See Prerequisites section above for a list of runtime prerequisites.
Other relevant development libraries (e.g. libpcsclite-dev on Debian-based distros) are included in the pcsc dependency. No additional installation needed.
N/A :: Required MacOS Framework .tbds are included in the pcsc dependency. No additional installation needed.
N/A :: Required DLLs are shipped with the Zig compiler. No additional installation needed.
This will output an lib/addon.node file to enable unit testing. Runs automatically when running the unit tests.
zig build
zig build test
zig build test:node -- --watch
zig build test:zig --watch
This enables testing basic operations against real devices (supporting up to 4 simultaneously connected readers) to verify functionality not testable via unit tests.
zig build e2e
This will output the final NPM package directories to ./zig-out/npm_packages.
zig build packages
FAQs
PC/SC (smart card) API bindings for Linux, MacOS, and Win32.
We found that pcsc-mini demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.