File size: 3,509 Bytes
cd8bd0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
 * Regression: runElevatedPowerShell() must no longer use -EncodedCommand and
 * must write the elevated payload to a per-call temp .ps1 file referenced via
 * -File. See docs/security/SOCKET_DEV_FINDINGS.md §1.
 */
import { test } from "node:test";
import assert from "node:assert/strict";
import os from "node:os";
import fs from "node:fs";
import path from "node:path";
import {
  buildElevatedScriptWrapper,
  _runElevatedPowerShellForTest,
} from "../../../src/mitm/systemCommands.ts";

test("buildElevatedScriptWrapper does not contain -EncodedCommand fingerprint", () => {
  const wrapper = buildElevatedScriptWrapper("C:\\Temp\\omniroute-elevate-x.ps1");
  assert.ok(
    !wrapper.includes("-EncodedCommand"),
    "wrapper must not contain -EncodedCommand (Socket.dev textbook fingerprint)"
  );
  assert.ok(wrapper.includes("-File"), "wrapper must reference the payload via -File");
  assert.ok(wrapper.includes("Start-Process"), "wrapper must use Start-Process -Verb RunAs");
  assert.ok(wrapper.includes("-Verb RunAs"), "wrapper must request elevation via -Verb RunAs");
});

test("buildElevatedScriptWrapper quotes the script path safely (no shell injection)", () => {
  const wrapper = buildElevatedScriptWrapper("C:\\Temp\\path with spaces'and-quote.ps1");
  // PowerShell single-quote escaping doubles the quote — our quotePowerShell
  // helper does that. Confirm both the original and the escaped form are present.
  assert.ok(
    wrapper.includes("'C:\\Temp\\path with spaces''and-quote.ps1'"),
    "single quotes in the path must be doubled per PowerShell escaping rules"
  );
});

test("_runElevatedPowerShellForTest writes payload to a temp .ps1 file and unlinks after", async () => {
  let capturedWrapper: string | null = null;
  let capturedTempPath: string | null = null;

  await _runElevatedPowerShellForTest(
    "Write-Output 'omniroute regression test'",
    async (wrapper, tempPath) => {
      capturedWrapper = wrapper;
      capturedTempPath = tempPath;
      assert.ok(fs.existsSync(tempPath), "temp file must exist while the runner is active");
      const content = fs.readFileSync(tempPath, "utf8");
      assert.match(content, /Write-Output 'omniroute regression test'/);
      return "ok";
    }
  );

  assert.ok(capturedWrapper, "wrapper must be captured");
  assert.ok(!capturedWrapper!.includes("-EncodedCommand"), "wrapper must not use -EncodedCommand");
  assert.ok(capturedTempPath, "temp path must be captured");
  assert.ok(
    capturedTempPath!.startsWith(path.resolve(os.tmpdir())) ||
      capturedTempPath!.startsWith(os.tmpdir()),
    "temp .ps1 must live inside os.tmpdir()"
  );
  assert.ok(
    !fs.existsSync(capturedTempPath!),
    "temp .ps1 file must be unlinked after the runner returns"
  );
});

test("_runElevatedPowerShellForTest unlinks the temp file even when the runner throws", async () => {
  let capturedTempPath: string | null = null;
  let threw = false;

  try {
    await _runElevatedPowerShellForTest("Write-Output 'denied'", async (_wrapper, tempPath) => {
      capturedTempPath = tempPath;
      throw new Error("simulated UAC denial");
    });
  } catch (err) {
    threw = true;
    assert.match((err as Error).message, /simulated UAC denial/);
  }

  assert.ok(threw, "the error must propagate to the caller");
  assert.ok(capturedTempPath, "temp path must still be captured");
  assert.ok(
    !fs.existsSync(capturedTempPath!),
    "temp .ps1 must be removed by the finally block even after a failed call"
  );
});