Comparing version 3.0.0 to 3.1.0
{ | ||
"name": "isexe", | ||
"version": "3.0.0", | ||
"version": "3.1.0", | ||
"description": "Minimal module to check if a file is executable.", | ||
@@ -5,0 +5,0 @@ "main": "./dist/cjs/index.js", |
@@ -24,2 +24,9 @@ export interface IsexeOptions { | ||
/** | ||
* effective group ID list to use when checking executable mode flags | ||
* on posix | ||
* Defaults to process.getgroups() | ||
*/ | ||
groups?: number[] | ||
/** | ||
* The ;-delimited path extension list for win32 implementation. | ||
@@ -26,0 +33,0 @@ * Defaults to process.env.PATHEXT |
@@ -34,3 +34,6 @@ /** | ||
*/ | ||
export const sync = (path: string, options: IsexeOptions = {}): boolean => { | ||
export const sync = ( | ||
path: string, | ||
options: IsexeOptions = {} | ||
): boolean => { | ||
const { ignoreErrors = false } = options | ||
@@ -50,5 +53,11 @@ try { | ||
const checkMode = (stat: Stats, options: IsexeOptions) => { | ||
if (!process.getuid || !process.getgid) { | ||
const myUid = options.uid ?? process.getuid?.() | ||
const myGroups = options.groups ?? process.getgroups?.() ?? [] | ||
const myGid = options.gid ?? process.getgid?.() ?? myGroups[0] | ||
if (myUid === undefined || myGid === undefined) { | ||
throw new Error('cannot get uid or gid') | ||
} | ||
const groups = new Set([myGid, ...myGroups]) | ||
const mod = stat.mode | ||
@@ -58,12 +67,2 @@ const uid = stat.uid | ||
const myUid = | ||
options.uid !== undefined | ||
? options.uid | ||
: process.getuid && process.getuid() | ||
const myGid = | ||
options.gid !== undefined | ||
? options.gid | ||
: process.getgid && process.getgid() | ||
const u = parseInt('100', 8) | ||
@@ -76,3 +75,3 @@ const g = parseInt('010', 8) | ||
mod & o || | ||
(mod & g && gid === myGid) || | ||
(mod & g && groups.has(gid)) || | ||
(mod & u && uid === myUid) || | ||
@@ -79,0 +78,0 @@ (mod & ug && myUid === 0) |
@@ -9,2 +9,3 @@ import {resolve} from 'path' | ||
'ours.cat':'#!/usr/bin/env cat\nours\n', | ||
'others.cat':'#!/usr/bin/env cat\nothers\n', | ||
'fail.false':'#!/usr/bin/env false\n', | ||
@@ -16,2 +17,3 @@ }) | ||
const ours = resolve(dir, 'ours.cat') | ||
const others = resolve(dir, 'others.cat') | ||
const fail = resolve(dir, 'fail.false') | ||
@@ -23,2 +25,3 @@ const enoent = resolve(dir, 'enoent.exe') | ||
[ours]:0o754, | ||
[others]:0o754, | ||
[fail]:0o644, | ||
@@ -30,3 +33,3 @@ } | ||
return { meow, mine, ours, fail, enoent, modes } | ||
return { meow, mine, ours, others, fail, enoent, modes } | ||
} |
import t from 'tap' | ||
import { createFixtures } from './fixtures/index' | ||
const { meow, fail, mine, ours, enoent, modes } = createFixtures(t) | ||
const { meow, fail, mine, ours, others, enoent, modes } = createFixtures(t) | ||
@@ -16,4 +16,4 @@ const isWindows = process.platform === 'win32' | ||
Object.assign(st, { | ||
uid: 123, | ||
gid: 321, | ||
uid: path === others || path === ours ? 987 : 123, | ||
gid: path === others ? 987 : 321, | ||
mode: !modes[path] ? st.mode : setMode(st.mode, modes[path]), | ||
@@ -24,5 +24,5 @@ }) | ||
const { getuid, getgid } = process | ||
const { getuid, getgid, getgroups } = process | ||
t.teardown(() => { | ||
Object.assign(process, { getuid, getgid }) | ||
Object.assign(process, { getuid, getgid, getgroups }) | ||
}) | ||
@@ -32,2 +32,3 @@ Object.assign(process, { | ||
getgid: () => 321, | ||
getgroups: () => [321, 987], | ||
}) | ||
@@ -50,2 +51,3 @@ | ||
t.equal(await isexe(ours), true) | ||
t.equal(await isexe(others), true) | ||
t.equal(await isexe(mine), true) | ||
@@ -56,2 +58,3 @@ t.equal(await isexe(fail), false) | ||
t.equal(sync(ours), true) | ||
t.equal(sync(others), true) | ||
t.equal(sync(mine), true) | ||
@@ -68,11 +71,13 @@ t.equal(sync(fail), false) | ||
t.test('same uid, different gid', async t => { | ||
const o = { gid: 654 } | ||
t.equal(await isexe(meow), true) | ||
t.equal(await isexe(ours), true) | ||
t.equal(await isexe(mine), true) | ||
t.equal(await isexe(fail), false) | ||
t.equal(sync(meow), true) | ||
t.equal(sync(ours), true) | ||
t.equal(sync(mine), true) | ||
t.equal(sync(fail), false) | ||
const o = { gid: 654, groups: [] } | ||
t.equal(await isexe(meow, o), true) | ||
t.equal(await isexe(ours, o), false) | ||
t.equal(await isexe(others, o), false) | ||
t.equal(await isexe(mine, o), true) | ||
t.equal(await isexe(fail, o), false) | ||
t.equal(sync(meow, o), true) | ||
t.equal(sync(ours, o), false) | ||
t.equal(sync(others, o), false) | ||
t.equal(sync(mine, o), true) | ||
t.equal(sync(fail, o), false) | ||
}) | ||
@@ -84,2 +89,3 @@ | ||
t.equal(await isexe(ours, o), true) | ||
t.equal(await isexe(others, o), true) | ||
t.equal(await isexe(mine, o), false) | ||
@@ -89,2 +95,3 @@ t.equal(await isexe(fail, o), false) | ||
t.equal(sync(ours, o), true) | ||
t.equal(sync(others, o), true) | ||
t.equal(sync(mine, o), false) | ||
@@ -95,5 +102,6 @@ t.equal(sync(fail, o), false) | ||
t.test('different uid, different gid', async t => { | ||
const o = { uid: 456, gid: 654 } | ||
const o = { uid: 456, gid: 654, groups: [] } | ||
t.equal(await isexe(meow, o), true) | ||
t.equal(await isexe(ours, o), false) | ||
t.equal(await isexe(others, o), false) | ||
t.equal(await isexe(mine, o), false) | ||
@@ -103,12 +111,28 @@ t.equal(await isexe(fail, o), false) | ||
t.equal(sync(ours, o), false) | ||
t.equal(sync(others, o), false) | ||
t.equal(sync(mine, o), false) | ||
t.equal(sync(fail, o), false) | ||
}) | ||
t.test('root can run anything runnable', async t => { | ||
const o = { uid: 0, gid: 999, groups: [] } | ||
t.equal(await isexe(meow, o), true) | ||
t.equal(await isexe(ours, o), true) | ||
t.equal(await isexe(others, o), true) | ||
t.equal(await isexe(mine, o), true) | ||
t.equal(await isexe(fail, o), false) | ||
t.equal(sync(meow, o), true) | ||
t.equal(sync(ours, o), true) | ||
t.equal(sync(others, o), true) | ||
t.equal(sync(mine, o), true) | ||
t.equal(sync(fail, o), false) | ||
}) | ||
}) | ||
t.test('getuid/getgid required', async t => { | ||
const { getuid, getgid } = process | ||
t.teardown(() => { Object.assign(process, { getuid, getgid })}) | ||
const { getuid, getgid, getgroups } = process | ||
t.teardown(() => { Object.assign(process, { getuid, getgid, getgroups })}) | ||
process.getuid = undefined | ||
process.getgid = undefined | ||
process.getgroups = undefined | ||
t.throws(() => sync(meow), { | ||
@@ -120,2 +144,5 @@ message: 'cannot get uid or gid' | ||
}) | ||
// fine as long as a group/user is specified though | ||
t.equal(sync(meow, { uid: 999, groups: [321] }), true) | ||
t.equal(await isexe(meow, { uid: 999, groups: [321] }), true) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
232443
2036
0