Socket
Socket
Sign inDemoInstall

isexe

Package Overview
Dependencies
0
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.0.0 to 3.1.0

2

package.json
{
"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)
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc