@neotales/is-elevated 0.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +16 -0
- package/README.md +78 -0
- package/esm/ffi_bun.js +59 -0
- package/esm/ffi_deno.js +67 -0
- package/esm/ffi_koffi.js +51 -0
- package/esm/ffi_node.js +56 -0
- package/esm/index.js +56 -0
- package/esm/node.js +20 -0
- package/package.json +56 -0
- package/types/ffi_bun.d.ts +13 -0
- package/types/ffi_deno.d.ts +18 -0
- package/types/ffi_koffi.d.ts +13 -0
- package/types/ffi_node.d.ts +13 -0
- package/types/index.d.ts +13 -0
- package/types/node.d.ts +11 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright 2024-2026 Mr. Neobeard
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
6
|
+
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
7
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
8
|
+
persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
11
|
+
Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
14
|
+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
15
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
16
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# @neotales/is-elevated
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`@neotales/is-elevated` detects whether the current process is running with elevated privileges.
|
|
6
|
+
On Unix-like systems this typically means root. On Windows it checks whether the current token is elevated.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
[](https://jsr.io/@neotales/is-elevated)
|
|
11
|
+
[](https://badge.fury.io/js/@neostd%2Fis-elevated)
|
|
12
|
+
[](https://badge.fury.io/gh/neostd%2Fjs)
|
|
13
|
+
|
|
14
|
+
## Documentation
|
|
15
|
+
|
|
16
|
+
Documentation is available on [jsr.io](https://jsr.io/@neotales/is-elevated/doc).
|
|
17
|
+
|
|
18
|
+
A list of other modules can be found at [github.com/neotales/js-os](https://github.com/neotales/js-os).
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Deno
|
|
24
|
+
deno add jsr:@neotales/is-elevated
|
|
25
|
+
|
|
26
|
+
# npm from jsr
|
|
27
|
+
npx jsr add @neotales/is-elevated
|
|
28
|
+
|
|
29
|
+
# from npmjs.org
|
|
30
|
+
npm install @neotales/is-elevated
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { isElevated } from "@neotales/is-elevated";
|
|
37
|
+
|
|
38
|
+
if (!isElevated()) {
|
|
39
|
+
throw new Error("Run this as admin/root");
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Exports
|
|
44
|
+
|
|
45
|
+
| Export | Subpath | Description |
|
|
46
|
+
| ------------ | ----------------------- | ------------------------------------------------ |
|
|
47
|
+
| `isElevated` | `@neotales/is-elevated` | Detects whether the current process is elevated. |
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { isElevated } from "@neotales/is-elevated";
|
|
51
|
+
|
|
52
|
+
const elevated = isElevated();
|
|
53
|
+
|
|
54
|
+
if (elevated) {
|
|
55
|
+
console.log("ready for privileged work");
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Elevation Detection
|
|
60
|
+
|
|
61
|
+
On Unix-like systems, elevation means an effective user ID of `0`. Node and Bun check `process.geteuid()` when available, then fall back to `process.getuid()`. The result is cached so repeated checks do not need to query the runtime again.
|
|
62
|
+
|
|
63
|
+
On Windows, the package opens the current process token and calls `GetTokenInformation` with `TokenElevation`. Node uses native `node:ffi` when available and otherwise the optional `koffi` dependency; Bun and Deno use their native FFI implementations. The FFI implementations are loaded only on Windows.
|
|
64
|
+
|
|
65
|
+
This intentionally does not use `Shell32.IsUserAnAdmin`. That API checks administrator-group membership rather than the current process token, so it can disagree under User Account Control when an administrator account is running with a filtered, non-elevated token. `TokenElevation` reports the process state directly.
|
|
66
|
+
|
|
67
|
+
## Runtime Notes
|
|
68
|
+
|
|
69
|
+
Node.js uses either `node:ffi` or the optional `koffi` peer dependency when available. Bun and Deno use their native FFI support.
|
|
70
|
+
Tests for OS-specific behavior are skipped when the current runtime does not support the required platform semantics.
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
[MIT License](./LICENSE.md)
|
|
75
|
+
|
|
76
|
+
## Runtime Support
|
|
77
|
+
|
|
78
|
+
This npm package supports Node, Bun, and Deno. Deno users can import it with `npm:@neotales/is-elevated`; use the JSR package for the Deno-only implementation.
|
package/esm/ffi_bun.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/// <reference types="@types/bun" />
|
|
2
|
+
import { dlopen, FFIType, ptr } from "bun:ffi";
|
|
3
|
+
let elevated;
|
|
4
|
+
/**
|
|
5
|
+
* Reports whether the current process is running with elevated privileges.
|
|
6
|
+
*
|
|
7
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
8
|
+
* @returns Whether the process has elevated privileges.
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { evalIsProcessElevated } from "./ffi_bun.js";
|
|
12
|
+
*
|
|
13
|
+
* const elevated = evalIsProcessElevated();
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function evalIsProcessElevated(cache = true) {
|
|
17
|
+
if (cache && elevated !== undefined) {
|
|
18
|
+
return elevated;
|
|
19
|
+
}
|
|
20
|
+
elevated = globalThis.process?.getuid?.() === 0;
|
|
21
|
+
if (!globalThis.Bun) {
|
|
22
|
+
return elevated;
|
|
23
|
+
}
|
|
24
|
+
if (globalThis.process?.platform !== "win32") {
|
|
25
|
+
return elevated;
|
|
26
|
+
}
|
|
27
|
+
const advapi32 = dlopen("Advapi32.dll", {
|
|
28
|
+
OpenProcessToken: { args: [FFIType.ptr, FFIType.u32, FFIType.ptr], returns: FFIType.bool },
|
|
29
|
+
GetTokenInformation: {
|
|
30
|
+
args: [FFIType.u64, FFIType.u32, FFIType.ptr, FFIType.u32, FFIType.ptr],
|
|
31
|
+
returns: FFIType.bool,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
const kernel32 = dlopen("Kernel32.dll", {
|
|
35
|
+
GetCurrentProcess: { args: [], returns: FFIType.ptr },
|
|
36
|
+
CloseHandle: { args: [FFIType.ptr], returns: FFIType.bool },
|
|
37
|
+
GetLastError: { args: [], returns: FFIType.i32 },
|
|
38
|
+
});
|
|
39
|
+
const TOKEN_QUERY = 0x0008;
|
|
40
|
+
const TOKEN_ELEVATION = 20;
|
|
41
|
+
const processHandle = kernel32.symbols.GetCurrentProcess();
|
|
42
|
+
const tokenHandle = new BigUint64Array(1);
|
|
43
|
+
const tokenHandlePtr = ptr(tokenHandle);
|
|
44
|
+
const success = advapi32.symbols.OpenProcessToken(processHandle, TOKEN_QUERY, tokenHandlePtr);
|
|
45
|
+
if (!success)
|
|
46
|
+
throw new Error("Failed to open process token");
|
|
47
|
+
try {
|
|
48
|
+
const tokenInfo = new Uint8Array(4);
|
|
49
|
+
const returnLength = new Uint32Array(1);
|
|
50
|
+
const result = advapi32.symbols.GetTokenInformation(tokenHandle[0], TOKEN_ELEVATION, ptr(tokenInfo), 4, ptr(returnLength));
|
|
51
|
+
if (!result)
|
|
52
|
+
throw new Error(`Failed to get token information ${kernel32.symbols.GetLastError()}`);
|
|
53
|
+
elevated = tokenInfo[0] !== 0;
|
|
54
|
+
return elevated;
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
kernel32.symbols.CloseHandle(tokenHandlePtr);
|
|
58
|
+
}
|
|
59
|
+
}
|
package/esm/ffi_deno.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implements native Windows elevation detection for Deno.
|
|
3
|
+
*
|
|
4
|
+
* @module @neotales/is-elevated/ffi_deno
|
|
5
|
+
*/
|
|
6
|
+
let elevated;
|
|
7
|
+
const deno = globalThis.Deno;
|
|
8
|
+
/**
|
|
9
|
+
* Reports whether the current process is running with elevated privileges.
|
|
10
|
+
*
|
|
11
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
12
|
+
* @returns Whether the process has elevated privileges.
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { evalIsProcessElevated } from "./ffi_deno.js";
|
|
16
|
+
*
|
|
17
|
+
* const elevated = evalIsProcessElevated();
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function evalIsProcessElevated(cache = true) {
|
|
21
|
+
if (!cache || elevated === undefined) {
|
|
22
|
+
elevated = deno.uid() === 0;
|
|
23
|
+
}
|
|
24
|
+
if (deno.build.os !== "windows") {
|
|
25
|
+
return elevated;
|
|
26
|
+
}
|
|
27
|
+
const advapi32 = deno.dlopen("Advapi32.dll", {
|
|
28
|
+
OpenProcessToken: { parameters: ["pointer", "u32", "pointer"], result: "bool" },
|
|
29
|
+
GetTokenInformation: {
|
|
30
|
+
parameters: ["u64", "u32", "pointer", "u32", "pointer"],
|
|
31
|
+
result: "bool",
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
const kernel32 = deno.dlopen("Kernel32.dll", {
|
|
35
|
+
GetCurrentProcess: { parameters: [], result: "pointer" },
|
|
36
|
+
CloseHandle: { parameters: ["pointer"], result: "bool" },
|
|
37
|
+
GetLastError: { parameters: [], result: "i32" },
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
const TOKEN_QUERY = 0x0008;
|
|
41
|
+
const TOKEN_ELEVATION = 20;
|
|
42
|
+
const processHandle = kernel32.symbols.GetCurrentProcess();
|
|
43
|
+
const tokenHandle = new BigUint64Array(1);
|
|
44
|
+
const tokenHandlePtr = deno.UnsafePointer.of(tokenHandle);
|
|
45
|
+
const success = advapi32.symbols.OpenProcessToken(processHandle, TOKEN_QUERY, tokenHandlePtr);
|
|
46
|
+
if (!success) {
|
|
47
|
+
throw new Error("Failed to open process token");
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const tokenInfo = new Uint8Array(4);
|
|
51
|
+
const returnLength = new Uint32Array(1);
|
|
52
|
+
const result = advapi32.symbols.GetTokenInformation(tokenHandle[0], TOKEN_ELEVATION, deno.UnsafePointer.of(tokenInfo), 4, deno.UnsafePointer.of(returnLength));
|
|
53
|
+
if (!result) {
|
|
54
|
+
throw new Error("Failed to get token information " + kernel32.symbols.GetLastError());
|
|
55
|
+
}
|
|
56
|
+
elevated = tokenInfo[0] !== 0;
|
|
57
|
+
return elevated;
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
kernel32.symbols.CloseHandle(tokenHandlePtr);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
advapi32.close();
|
|
65
|
+
kernel32.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
package/esm/ffi_koffi.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
const { createRequire } = process.getBuiltinModule("node:module");
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const koffi = require("koffi");
|
|
5
|
+
const advapi32 = koffi.load("Advapi32.dll");
|
|
6
|
+
const kernel32 = koffi.load("Kernel32.dll");
|
|
7
|
+
const OpenProcessToken = advapi32.func("int __stdcall OpenProcessToken(void *ProcessHandle, uint32 DesiredAccess, _Out_ void **TokenHandle)");
|
|
8
|
+
const GetTokenInformation = advapi32.func("int __stdcall GetTokenInformation(void *TokenHandle, uint32 TokenInformationClass, void *TokenInformation, uint32 TokenInformationLength, _Out_ uint32 *ReturnLength)");
|
|
9
|
+
const GetCurrentProcess = kernel32.func("void * __stdcall GetCurrentProcess()");
|
|
10
|
+
const CloseHandle = kernel32.func("int __stdcall CloseHandle(void *hObject)");
|
|
11
|
+
const GetLastError = kernel32.func("uint32 __stdcall GetLastError()");
|
|
12
|
+
let elevated;
|
|
13
|
+
/**
|
|
14
|
+
* Reports whether the current process is running with elevated privileges.
|
|
15
|
+
*
|
|
16
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
17
|
+
* @returns Whether the process has elevated privileges.
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { evalIsProcessElevated } from "./ffi_koffi.js";
|
|
21
|
+
*
|
|
22
|
+
* const elevated = evalIsProcessElevated();
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function evalIsProcessElevated(cache = true) {
|
|
26
|
+
if (cache && elevated !== undefined) {
|
|
27
|
+
return elevated;
|
|
28
|
+
}
|
|
29
|
+
const TOKEN_QUERY = 0x0008;
|
|
30
|
+
const TOKEN_ELEVATION = 20;
|
|
31
|
+
const processHandle = GetCurrentProcess();
|
|
32
|
+
const tokenOut = [null];
|
|
33
|
+
const opened = OpenProcessToken(processHandle, TOKEN_QUERY, tokenOut);
|
|
34
|
+
if (!opened) {
|
|
35
|
+
throw new Error(`Failed to open process token (${GetLastError()})`);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const tokenInfo = new Uint8Array(4);
|
|
39
|
+
const returnLength = [0];
|
|
40
|
+
const ok = GetTokenInformation(tokenOut[0], TOKEN_ELEVATION, tokenInfo, 4, returnLength);
|
|
41
|
+
if (!ok) {
|
|
42
|
+
throw new Error(`Failed to get token information (${GetLastError()})`);
|
|
43
|
+
}
|
|
44
|
+
elevated = tokenInfo[0] !== 0;
|
|
45
|
+
return elevated;
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
if (tokenOut[0])
|
|
49
|
+
CloseHandle(tokenOut[0]);
|
|
50
|
+
}
|
|
51
|
+
}
|
package/esm/ffi_node.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
const { createRequire } = process.getBuiltinModule("node:module");
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const ffi = require("node:ffi");
|
|
5
|
+
const advapi32 = ffi.dlopen("Advapi32.dll", {
|
|
6
|
+
OpenProcessToken: { arguments: ["pointer", "u32", "pointer"], return: "u8" },
|
|
7
|
+
GetTokenInformation: {
|
|
8
|
+
arguments: ["pointer", "u32", "pointer", "u32", "pointer"],
|
|
9
|
+
return: "u8",
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
const kernel32 = ffi.dlopen("Kernel32.dll", {
|
|
13
|
+
GetCurrentProcess: { arguments: [], return: "pointer" },
|
|
14
|
+
CloseHandle: { arguments: ["pointer"], return: "u8" },
|
|
15
|
+
GetLastError: { arguments: [], return: "u32" },
|
|
16
|
+
});
|
|
17
|
+
let elevated;
|
|
18
|
+
/**
|
|
19
|
+
* Reports whether the current process is running with elevated privileges.
|
|
20
|
+
*
|
|
21
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
22
|
+
* @returns Whether the process has elevated privileges.
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { evalIsProcessElevated } from "./ffi_node.js";
|
|
26
|
+
*
|
|
27
|
+
* const elevated = evalIsProcessElevated();
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function evalIsProcessElevated(cache = true) {
|
|
31
|
+
if (cache && elevated !== undefined) {
|
|
32
|
+
return elevated;
|
|
33
|
+
}
|
|
34
|
+
const TOKEN_QUERY = 0x0008;
|
|
35
|
+
const TOKEN_ELEVATION = 20;
|
|
36
|
+
const processHandle = kernel32.functions.GetCurrentProcess();
|
|
37
|
+
const tokenHandleBuf = new Uint8Array(8);
|
|
38
|
+
const opened = advapi32.functions.OpenProcessToken(processHandle, TOKEN_QUERY, tokenHandleBuf);
|
|
39
|
+
if (!opened) {
|
|
40
|
+
throw new Error(`Failed to open process token (${kernel32.functions.GetLastError()})`);
|
|
41
|
+
}
|
|
42
|
+
const tokenHandle = new DataView(tokenHandleBuf.buffer).getBigUint64(0, true);
|
|
43
|
+
try {
|
|
44
|
+
const tokenInfo = new Uint8Array(4);
|
|
45
|
+
const returnLength = new Uint8Array(4);
|
|
46
|
+
const ok = advapi32.functions.GetTokenInformation(tokenHandle, TOKEN_ELEVATION, tokenInfo, 4, returnLength);
|
|
47
|
+
if (!ok) {
|
|
48
|
+
throw new Error(`Failed to get token information (${kernel32.functions.GetLastError()})`);
|
|
49
|
+
}
|
|
50
|
+
elevated = tokenInfo[0] !== 0;
|
|
51
|
+
return elevated;
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
kernel32.functions.CloseHandle(tokenHandle);
|
|
55
|
+
}
|
|
56
|
+
}
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
let elevated;
|
|
3
|
+
function evalUnixElevation(cache = true) {
|
|
4
|
+
if (cache && elevated !== undefined) {
|
|
5
|
+
return elevated;
|
|
6
|
+
}
|
|
7
|
+
const uid = process.geteuid?.() ?? process.getuid?.();
|
|
8
|
+
elevated = uid === 0;
|
|
9
|
+
return elevated;
|
|
10
|
+
}
|
|
11
|
+
let impl = evalUnixElevation;
|
|
12
|
+
const runtime = globalThis;
|
|
13
|
+
if (process.platform === "win32") {
|
|
14
|
+
const { createRequire } = process.getBuiltinModule("node:module");
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
if (runtime.Deno) {
|
|
17
|
+
impl = require("./ffi_deno.js").evalIsProcessElevated;
|
|
18
|
+
}
|
|
19
|
+
else if (runtime.Bun) {
|
|
20
|
+
impl = require("./ffi_bun.js").evalIsProcessElevated;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
try {
|
|
24
|
+
if (process.getBuiltinModule("node:ffi")) {
|
|
25
|
+
impl = require("./ffi_node.js").evalIsProcessElevated;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
impl = require("./ffi_koffi.js").evalIsProcessElevated;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
try {
|
|
33
|
+
impl = require("./ffi_koffi.js").evalIsProcessElevated;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
if (process.env.DEBUG === "true")
|
|
37
|
+
console.debug(error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Reports whether the current process is running with elevated privileges.
|
|
44
|
+
*
|
|
45
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
46
|
+
* @returns Whether the process has elevated privileges.
|
|
47
|
+
* @example
|
|
48
|
+
* import { isElevated } from "@neotales/is-elevated";
|
|
49
|
+
*
|
|
50
|
+
* if (isElevated()) {
|
|
51
|
+
* console.log("The process is elevated.");
|
|
52
|
+
* }
|
|
53
|
+
*/
|
|
54
|
+
export function isElevated(cache = true) {
|
|
55
|
+
return impl(cache);
|
|
56
|
+
}
|
package/esm/node.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
let elevated;
|
|
3
|
+
/**
|
|
4
|
+
* Reports whether the current process has an effective user ID of zero.
|
|
5
|
+
*
|
|
6
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
7
|
+
* @returns Whether the process has an effective user ID of zero.
|
|
8
|
+
* @example
|
|
9
|
+
* import { evalIsProcessElevated } from "./node.js";
|
|
10
|
+
*
|
|
11
|
+
* const elevated = evalIsProcessElevated();
|
|
12
|
+
*/
|
|
13
|
+
export function evalIsProcessElevated(cache = true) {
|
|
14
|
+
if (cache && elevated !== undefined) {
|
|
15
|
+
return elevated;
|
|
16
|
+
}
|
|
17
|
+
const uid = process.geteuid?.() ?? process.getuid?.();
|
|
18
|
+
elevated = uid === 0;
|
|
19
|
+
return elevated;
|
|
20
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@neotales/is-elevated",
|
|
3
|
+
"version": "0.0.0-alpha.0",
|
|
4
|
+
"description": "Detect whether the current process is elevated.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"admin",
|
|
7
|
+
"elevated",
|
|
8
|
+
"root",
|
|
9
|
+
"std",
|
|
10
|
+
"sudo",
|
|
11
|
+
"windows"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/neotales/js-os",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/neotales/js-os/issues"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/neotales/js-os.git",
|
|
21
|
+
"directory": "npm/is-elevated"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"esm",
|
|
25
|
+
"types"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./types/index.d.ts",
|
|
31
|
+
"import": "./esm/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/bun": "^1.3.14",
|
|
39
|
+
"@types/node": "^25.9.3",
|
|
40
|
+
"typescript": "^6.0.3"
|
|
41
|
+
},
|
|
42
|
+
"optionalDependencies": {
|
|
43
|
+
"koffi": "^2.9.0"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc -p tsconfig.json",
|
|
50
|
+
"build:test": "tsc -p tsconfig.test.json",
|
|
51
|
+
"test": "pnpm run build:test && node --test .test/tests/*.test.js",
|
|
52
|
+
"test:ffi": "pnpm run build:test && node --experimental-ffi --test .test/tests/*.test.js",
|
|
53
|
+
"test:bun": "pnpm run build:test && bun test ./.test/tests",
|
|
54
|
+
"test:deno": "pnpm run build:test && deno test -A .test/tests"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reports whether the current process is running with elevated privileges.
|
|
3
|
+
*
|
|
4
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
5
|
+
* @returns Whether the process has elevated privileges.
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { evalIsProcessElevated } from "./ffi_bun.js";
|
|
9
|
+
*
|
|
10
|
+
* const elevated = evalIsProcessElevated();
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function evalIsProcessElevated(cache?: boolean): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implements native Windows elevation detection for Deno.
|
|
3
|
+
*
|
|
4
|
+
* @module @neotales/is-elevated/ffi_deno
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Reports whether the current process is running with elevated privileges.
|
|
8
|
+
*
|
|
9
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
10
|
+
* @returns Whether the process has elevated privileges.
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { evalIsProcessElevated } from "./ffi_deno.js";
|
|
14
|
+
*
|
|
15
|
+
* const elevated = evalIsProcessElevated();
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function evalIsProcessElevated(cache?: boolean): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reports whether the current process is running with elevated privileges.
|
|
3
|
+
*
|
|
4
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
5
|
+
* @returns Whether the process has elevated privileges.
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { evalIsProcessElevated } from "./ffi_koffi.js";
|
|
9
|
+
*
|
|
10
|
+
* const elevated = evalIsProcessElevated();
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function evalIsProcessElevated(cache?: boolean): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reports whether the current process is running with elevated privileges.
|
|
3
|
+
*
|
|
4
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
5
|
+
* @returns Whether the process has elevated privileges.
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { evalIsProcessElevated } from "./ffi_node.js";
|
|
9
|
+
*
|
|
10
|
+
* const elevated = evalIsProcessElevated();
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function evalIsProcessElevated(cache?: boolean): boolean;
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reports whether the current process is running with elevated privileges.
|
|
3
|
+
*
|
|
4
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
5
|
+
* @returns Whether the process has elevated privileges.
|
|
6
|
+
* @example
|
|
7
|
+
* import { isElevated } from "@neotales/is-elevated";
|
|
8
|
+
*
|
|
9
|
+
* if (isElevated()) {
|
|
10
|
+
* console.log("The process is elevated.");
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
export declare function isElevated(cache?: boolean): boolean;
|
package/types/node.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reports whether the current process has an effective user ID of zero.
|
|
3
|
+
*
|
|
4
|
+
* @param cache - Whether to reuse the result from the first evaluation.
|
|
5
|
+
* @returns Whether the process has an effective user ID of zero.
|
|
6
|
+
* @example
|
|
7
|
+
* import { evalIsProcessElevated } from "./node.js";
|
|
8
|
+
*
|
|
9
|
+
* const elevated = evalIsProcessElevated();
|
|
10
|
+
*/
|
|
11
|
+
export declare function evalIsProcessElevated(cache?: boolean): boolean;
|