Skip to content

Commit 98fa2fb

Browse files
committed
Add denyNet option
1 parent 5b9b39f commit 98fa2fb

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

src/DenoWorker.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ describe('DenoWorker', () => {
1818
const pingScript = readFileSync(pingFile, { encoding: 'utf-8' });
1919
const infiniteFile = path.resolve(__dirname, './test/infinite.js');
2020
const infiniteScript = readFileSync(infiniteFile, { encoding: 'utf-8' });
21+
const fetchFile = path.resolve(__dirname, './test/fetch.js');
22+
const fetchScript = readFileSync(fetchFile, { encoding: 'utf-8' });
2123
const failFile = path.resolve(__dirname, './test/fail.js');
2224
const failScript = readFileSync(failFile, { encoding: 'utf-8' });
2325
const envFile = path.resolve(__dirname, './test/env.js');
@@ -127,6 +129,38 @@ describe('DenoWorker', () => {
127129
});
128130
});
129131

132+
it('should be able to specify network addresses to block', async () => {
133+
const host = `example.com`;
134+
135+
worker = new DenoWorker(fetchScript, {
136+
permissions: {
137+
allowNet: true,
138+
denyNet: [host],
139+
},
140+
});
141+
142+
let ret: any;
143+
let resolve: any;
144+
let promise = new Promise((res, rej) => {
145+
resolve = res;
146+
});
147+
worker.onmessage = (e) => {
148+
ret = e.data;
149+
resolve();
150+
};
151+
152+
worker.postMessage({
153+
type: 'fetch',
154+
url: `https://${host}`,
155+
});
156+
157+
await promise;
158+
159+
expect(ret).toMatchObject({
160+
type: 'error',
161+
});
162+
});
163+
130164
it('should call onexit when the script fails', async () => {
131165
worker = new DenoWorker(failScript);
132166

src/DenoWorker.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ export interface DenoWorkerOptions {
103103
*/
104104
allowNet?: boolean | string[];
105105

106+
/**
107+
* Disable network access to provided IP addresses or hostnames. Any addresses
108+
* specified here will be denied access, even if they are specified in
109+
* `allowNet`. Note that deno-vm needs a network connection between the host
110+
* and the guest, so it's not possible to fully disable network access.
111+
*/
112+
denyNet?: string[];
113+
106114
/**
107115
* Whether to allow reading from the filesystem.
108116
* If given a list of strings then only the specified file paths are allowed.
@@ -331,6 +339,16 @@ export class DenoWorker {
331339
]
332340
: [allowAddress]
333341
);
342+
// Ensures the `allowAddress` isn't denied
343+
const deniedAddresses = this._options.permissions.denyNet?.filter(
344+
(address) => address !== allowAddress
345+
);
346+
addOption(
347+
runArgs,
348+
'--deny-net',
349+
// Ensures an empty array isn't used
350+
deniedAddresses?.length ? deniedAddresses : false
351+
);
334352
addOption(
335353
runArgs,
336354
'--allow-read',

src/test/fetch.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
self.onmessage = async (e) => {
2+
if (e.data.type === 'fetch') {
3+
// NOTE: Don't fetch within tests unless an error is expected
4+
await fetch(e.data.url).then(
5+
(r) => self.postMessage({ type: 'response', status: r.status }),
6+
(e) => self.postMessage({ type: 'error', error: e.message })
7+
);
8+
}
9+
};

0 commit comments

Comments
 (0)