A Node.js permission modellje (a --permission flag) 2023 végén, a v22.13.0 és v23.5.0 kiadásokban lépett ki kísérleti státuszból – ma stabil API. Bekapcsolva egy Node-folyamat hozzáférését korlátozza a fájlrendszerhez, a hálózathoz, a child processekhez és néhány más erőforráshoz, mielőtt a kódod egyáltalán futni kezdene. Végigteszteltem pár konkrét esetet helyi Node 22.23.2-n, és két dolog meglepett: az egyik egy dokumentált, de kevesek által ismert kikerülési út, a másik pedig az, hogy egy „korlátozott” erőforrás a jelenlegi LTS-eken valójában egyáltalán nincs korlátozva.

Biztonsági öv, nem sandbox
A dokumentáció szóhasználata pontos: a permission modell egy „seat belt” – megakadályozza, hogy megbízható kód véletlenül olyan fájlhoz vagy erőforráshoz nyúljon, amihez nem kapott explicit engedélyt. Nem véd rosszindulatú kód ellen: ha a folyamat futtatja a kódot, az a Node biztonsági szabályzata szerint eleve megbízik benne, és a korlátozás megkerülhető natív addonokkal vagy más trükkökkel. Ez a keretezés fontos, mert sokan „sandboxként” gondolnak rá npm-postinstall scriptek vagy felhasználói fájlokat feldolgozó workerek elszigetelésére – valójában inkább egy hibafogó, ami egy elgépelt fs.rm-et vagy egy figyelmetlen third-party importot állít meg, nem egy ellenséges támadót.
A --permission flag nyolc erőforráskategóriát különböztet meg, mindegyikhez saját --allow-* kapcsolóval:
- fájlrendszer olvasás/írás –
--allow-fs-read/--allow-fs-write - hálózat –
--allow-net - child process –
--allow-child-process - worker thread –
--allow-worker - natív addon –
--allow-addons - WASI –
--allow-wasi - FFI –
--allow-ffi - OpenSSL STORE loader –
--allow-openssl-store
Amit valóban megállít
Flag nélkül minden engedélyezett. Bekapcsolva alapból minden tilos, amíg explicit nem engedélyezed:
$ node --permission -e "require('fs').readFileSync('/etc/hostname')"
Error: Access to this API has been restricted. Use --allow-fs-read to manage permissions.
code: 'ERR_ACCESS_DENIED',
permission: 'FileSystemRead',
resource: '/etc/hostname'
$ node --permission --allow-fs-read=/etc/hostname -e "console.log(require('fs').readFileSync('/etc/hostname','utf8'))"
# most már kiírja a fájl tartalmát
Ugyanígy elzárja a child_process-t és a worker_threads-et is – mindkettőt hitelesen leteszteltem, ERR_ACCESS_DENIED-del állnak meg, hacsak nem adod hozzá az --allow-child-process vagy --allow-worker flaget. Néhány kényelmi részlet is van a rendszerben: a belépési pont fájlja (és a -r-rel betöltött preload scriptek) automatikusan olvasási engedélyt kapnak, és az --allow-fs-read=/mappa automatikusan felveszi a végére a * wildcardot, ha a mappa már létezik a folyamat indulásakor – ha még nem létezik, ezt explicit ki kell írnod (/mappa/*), különben csak a pontos elérési útra kapsz jogot, a benne később létrehozott fájlokra nem.
A node:sqlite átsétál a tiltáson
A dokumentáció maga írja le, elég szárazon: a permission modell alapból a node:fs modulon keresztüli hozzáférést korlátozza, és „nem garantálja, hogy a felhasználók ne érjenek el fájlrendszert más eszközökön keresztül, mint például a node:sqlite modul”. Ez nem elméleti figyelmeztetés – helyben kipróbáltam:
$ node --permission -e "
const { DatabaseSync } = require('node:sqlite');
const db = new DatabaseSync('/tmp/adat.db');
db.exec('CREATE TABLE IF NOT EXISTS t (x INT)');
console.log('sikeres írás, --allow-fs-write nélkül');
"
sikeres írás, --allow-fs-write nélkül
Semmilyen --allow-fs-write flag nélkül a node:sqlite létrehozta és írta a fájlt a diszken. A node:fs-en átmenő hívásokat a permission modell natívan lefogja, de minden más útvonalat – natív addonok, más beépített modulok – neked kell számításba venned. Ha egy build scriptet vagy user-uploadot feldolgozó workert akarsz körbezárni, ne elégedj meg azzal, hogy „van rajta --permission„, nézd át, milyen modulokat importál.
A hálózati tiltás nem az, aminek hiszed
A dokumentáció ugyanúgy felsorolja a hálózatot a korlátozott erőforrások között, mint a fájlrendszert. Csakhogy a --allow-net flag hivatalos changelogja szerint ez csak a v25.0.0-ban jelent meg, és ott is „Stability: 1.1 – Active development” besorolással, ami a legalacsonyabb stabilitási szint, mielőtt valami deprecated lenne. Node 22.23.2-n (a v22 Jod LTS aktuális kiadása) a flag simán nem létezik:
$ node --permission --allow-net -e "1"
node: bad option: --allow-net
$ node --permission -e "
const http = require('node:http');
http.get('http://127.0.0.1:18234', res => console.log('kapcsolódott, status', res.statusCode));
"
kapcsolódott, status 200
Vagyis a --permission önmagában, flag-kombináció nélkül nem állítja meg a kimenő hálózati kapcsolatot a jelenlegi LTS-ágakon (v22 Jod, v24 Krypton) – a kérés simán lefut. Ez alapjaiban más, mint a fájlrendszer vagy a child process eset, ahol az alapértelmezett viselkedés a tiltás. A hálózati enforcement csak a v26 Current ágban létezik, ami a Node saját ajánlása szerint nem production-ra való (a v25-öt, ahol a flag debütált, 2026 márciusában EOL-olták, mire beérhetett volna egy LTS-be). Ha most futtatsz LTS-t és a hálózati oldalt is le akarod zárni egy folyamat körül, arra ma konténer- vagy hoszt-szintű egress szabály kell, nem a Node saját permission modellje.
Amit a legújabb kiadás már tud, az LTS még nem
Két további, kényelmesnek tűnő funkció is csak a legfrissebb release-ekben van meg. Az --permission-audit mód – ami nem dob hibát, csak egy node:diagnostics_channel csatornán jelzi, mit tiltott volna meg – a v25.8.0-ban érkezett, tehát ugyanúgy egy már EOL-olt ágban. A process.permission.drop(), amivel futásidőben, visszafordíthatatlanul lemondhatsz egy már megkapott jogosultságról (pl. a konfig beolvasása után eldobod a fájlolvasási jogot), a v26-ban jelent meg először. Helyben leteszteltem: v22.23.2-n a process.permission.drop egyszerűen undefined, TypeError-t dob, ha meghívod. Ha egy cikk vagy tutorial ezekkel demózik, érdemes megnézni, milyen Node-verzióhoz köti – LTS-en még nem indul el.
Ez is csak egy security boundary – kapott már CVE-t
A permission modell nem „állítsd be egyszer és felejtsd el” jellegű védelem, ugyanúgy hibázhat, mint bármelyik security határ. Jó példa a CVE-2025-55132: az fs.futimes() – az utimes() file-descriptoros változata – nem futtatta le a szükséges írási jogosultság-ellenőrzést, így csak olvasási joggal is meg lehetett változtatni egy fájl módosítási időbélyegét egy amúgy írásvédett mappában. A hibát a 20.20.0, 22.22.0, 24.13.0 és 25.3.0 kiadásokban javították. A tanulság nem az, hogy a permission modell haszontalan, hanem hogy ugyanolyan patch-fegyelmet igényel, mint a TLS stack vagy bármelyik más security-kritikus komponens – nem attól biztos, hogy bekapcsoltad, hanem attól, hogy naprakész Node-on fut.
Mikor van ennek gyakorlati haszna
A legkényelmesebb belépési pont egy olyan folyamat, amelynek pontosan tudod, mire van szüksége: egy feltöltött képet átméretező worker, egy build-lépés, ami csak a dist/ mappába ír, vagy egy CLI, ami CSV-t konvertál. Ezeknél reális cél --allow-fs-read=/app/src/* --allow-fs-write=/app/dist/* mellett minden mást (child process, worker, addon) alapállásban tiltani – ha egy transitive dependency supply-chain támadás áldozata lesz és shell-t próbálna spawnolni vagy máshova írni, itt akad el, mielőtt bármi történne. A hálózatot – a fentiek fényében – ne a Node permission modelljétől várd LTS-en; azt oldd meg a konténer vagy a szolgáltatás szintjén.
Források
- Node.js dokumentáció – Permissions
- Node.js CLI dokumentáció –
--allow-net - nodejs/node #56201 – Permission Model is now stable
- nodejs/node #61869 – add
--permission-audit - nodejs/node #62672 – add
permission.drop - GitHub Advisory GHSA-pm9v-wcw9-xgpv – CVE-2025-55132
- Node.js dokumentáció – node:sqlite
- Node.js Release lines (Current/LTS állapotok)