reset_local_password
reset_local_password
Resets the local macOS/Windows account password. IMPORTANT: requires admin privileges. Always confirm with the user before executing. Use only for local accounts — not for Active Directory accounts.
Metadata
Name
reset_local_password
Updated
3 weeks ago
Source
Risk
Critical
Requires consent
true
Affected scope
system
Code
/**
* mcp/skills/resetLocalPassword.ts — reset_local_password skill
*
* Resets the local macOS/Windows account password. IMPORTANT: requires admin
* privileges. Always confirm with the user before executing. Use only for
* local accounts — not for Active Directory accounts.
*
* Platform strategy
* -----------------
* darwin `dscl . -passwd /Users/{username} {newPassword}` (only if not dryRun)
* win32 PowerShell Set-LocalUser -Name {username} -Password (ConvertTo-SecureString ...)
*
* Smoke test
* npx tsx -r dotenv/config mcp/skills/resetLocalPassword.ts
*/
import * as os from "os";
import { exec } from "child_process";
import { promisify } from "util";
import { z } from "zod";
const execAsync = promisify(exec);
// -- Meta ---------------------------------------------------------------------
export const meta = {
name: "reset_local_password",
description:
"Resets the local macOS/Windows account password. " +
"IMPORTANT: requires admin privileges. Always confirm with the user before executing. " +
"Use only for local accounts — not for Active Directory accounts.",
riskLevel: "critical",
destructive: true,
requiresConsent: true,
supportsDryRun: true,
affectedScope: ["system"],
auditRequired: true,
escalationHint: {
darwin: "sudo dscl . -passwd /Users/<username> '<newPassword>' # substitute the user's real username and a strong temporary password; user should change at next login",
win32: "Set-LocalUser -Name '<username>' -Password (ConvertTo-SecureString '<newPassword>' -AsPlainText -Force) # run from elevated PowerShell",
},
sensitiveParams: ["new_password"] as const,
schema: {
username: z
.string()
.describe("Username whose password to reset"),
new_password: z
.string()
.describe("New password to set"),
dryRun: z
.boolean()
.optional()
.describe("If true, validate inputs without changing password. Default: true"),
},
} as const;
// -- Types --------------------------------------------------------------------
interface ResetResult {
username: string;
success: boolean;
dryRun: boolean;
message: string;
}
// -- PowerShell helper --------------------------------------------------------
async function runPS(script: string): Promise<string> {
const encoded = Buffer.from(script, "utf16le").toString("base64");
const { stdout } = await execAsync(
`powershell.exe -NoProfile -NonInteractive -EncodedCommand ${encoded}`,
{ maxBuffer: 10 * 1024 * 1024 },
);
return stdout.trim();
}
// -- darwin implementation ----------------------------------------------------
async function resetLocalPasswordDarwin(
username: string,
newPassword: string,
dryRun: boolean,
): Promise<ResetResult> {
const safeName = username.replace(/'/g, `'\''`);
try {
await execAsync(
`dscl . -read /Users/'${safeName}' UniqueID 2>/dev/null`,
{ maxBuffer: 1 * 1024 * 1024, shell: "/bin/bash" },
);
} catch {
return {
username,
success: false,
dryRun,
message: `User '${username}' not found in local directory.`,
};
}
if (!newPassword || newPassword.length === 0) {
return {
username,
success: false,
dryRun,
message: "New password must not be empty.",
};
}
if (dryRun) {
return {
username,
success: true,
dryRun: true,
message: `Dry run: user '${username}' exists. Password would be reset. Run with dryRun=false to apply.`,
};
}
try {
const safePassword = newPassword.replace(/'/g, `'\''`);
await execAsync(
`dscl . -passwd /Users/'${safeName}' '${safePassword}'`,
{ maxBuffer: 1 * 1024 * 1024, shell: "/bin/bash" },
);
return {
username,
success: true,
dryRun: false,
message: `Password for '${username}' has been reset successfully.`,
};
} catch (err) {
const msg = (err as Error).message ?? "Unknown error";
return {
username,
success: false,
dryRun: false,
message: `Failed to reset password for '${username}': ${msg.replace(/password/gi, "[password]")}`,
};
}
}
// -- win32 implementation -----------------------------------------------------
async function resetLocalPasswordWin32(
username: string,
newPassword: string,
dryRun: boolean,
): Promise<ResetResult> {
const ps_check = `
$ErrorActionPreference = 'Stop'
try {
$u = Get-LocalUser -Name '${username.replace(/'/g, "''")}' -ErrorAction Stop
Write-Output "EXISTS:$($u.Name)"
} catch {
Write-Output "NOTFOUND"
}`.trim();
let checkResult = "";
try {
checkResult = await runPS(ps_check);
} catch {
return { username, success: false, dryRun, message: `Could not verify user '${username}'.` };
}
if (checkResult.includes("NOTFOUND")) {
return { username, success: false, dryRun, message: `User '${username}' not found.` };
}
if (!newPassword || newPassword.length === 0) {
return { username, success: false, dryRun, message: "New password must not be empty." };
}
const safeUser = username.replace(/'/g, "''");
const safePw = newPassword.replace(/'/g, "''");
const ps_reset = `
$ErrorActionPreference = 'Stop'
$secPw = ConvertTo-SecureString -String '${safePw}' -AsPlainText -Force
Set-LocalUser -Name '${safeUser}' -Password $secPw
Write-Output "OK"`.trim();
try {
const result = await runPS(ps_reset);
if (result.includes("OK")) {
return { username, success: true, dryRun: false, message: `Password for '${username}' has been reset successfully.` };
}
return { username, success: false, dryRun: false, message: "Password reset command did not confirm success." };
} catch (err) {
const msg = (err as Error).message ?? "Unknown error";
return {
username,
success: false,
dryRun: false,
message: `Failed to reset password for '${username}': ${msg.replace(/password/gi, "[password]")}`,
};
}
}
// -- Exported run function ----------------------------------------------------
export async function run({
username,
new_password: newPassword,
dryRun = true,
}: {
username: string;
new_password: string;
dryRun?: boolean;
}) {
if (!username) throw new Error("[reset_local_password] username is required");
if (!newPassword) throw new Error("[reset_local_password] new_password is required");
const platform = os.platform();
const result = platform === "win32"
? await resetLocalPasswordWin32(username, newPassword, dryRun)
: await resetLocalPasswordDarwin(username, newPassword, dryRun);
return { platform, ...result };
}
// -- CLI smoke test -----------------------------------------------------------
if (false) {
run({ username: "testuser", new_password: "TestPass123!", dryRun: true })
.then(r => console.log(JSON.stringify(r, null, 2)))
.catch((err: Error) => { console.error(err.message); process.exit(1); });
}