WorkForge runs with the permissions of the current Windows user. Its PowerShell tools are intentionally powerful and are not an operating-system sandbox.
- Use only a Secure MCP Tunnel runtime key that you are authorized to use.
Configure-Tunnel.ps1stores the key in ignoredruntime\.env.localwith ACL inheritance disabled and access restricted to the current user, SYSTEM, and local Administrators.- The key is removed from the MCP server environment before project or shell code is loaded.
- The Setup and Uninstall parameter surfaces do not accept a plain runtime key argument.
- ForgeUI redacts credential-shaped values, complete tunnel IDs, and the literal user-profile path from lifecycle JSONL logs.
- Never upload
runtime, tunnel YAML, profile registries, logs, uninstall receipts, browser data, or support bundles containing local state.
WorkForge separates profile removal from user-data removal.
The recommended mode removes the selected registry entry, tunnel configuration, protected local credential when the final profile is removed, runtime logs, command evidence, and a verified shortcut. It preserves the workspace repository, user-edited policy files, Git history, and user-created content.
This mode permanently removes the selected workspace. Interactive use requires the exact phrase REMOVE WORKFORGE. Non-interactive use requires -ConfirmFullRemoval. There is no destructive -Force alias.
A source checkout containing .git is never deleted automatically. A runtime engine is eligible for detached self-removal only when:
.workforge-release.jsonexists;- the manifest identifies WorkForge release distribution schema 1;
- the manifest SHA-256 has not changed since preflight;
- the path is not a drive root or user-profile root;
- no other registered profile uses the engine.
The finalizer waits for the main uninstaller process to exit and validates the manifest again immediately before removing the release directory.
Removing one profile preserves all unrelated registry entries. Shared runtime files, the protected credential, and the engine remain while any other profile is registered.
Uninstall removes a local credential file but does not revoke the corresponding OpenAI Platform runtime key. Revoke it separately only after confirming that no other installation uses it. Filesystem deletion is not a forensic secure erase and may remain represented in backups or storage snapshots.
WorkForge requires Node.js and ripgrep. Git for Windows is optional and only enables enhanced project-history features. Compatible existing commands are reported and left untouched.
- Interactive Setup asks before invoking WinGet for missing required components.
- Non-interactive Setup installs no required component unless
-InstallMissingPrerequisitesis supplied. - Missing Git never blocks Setup. Interactive Setup offers it separately and defaults to continuing without Git.
- Non-interactive Git installation requires the separate
-InstallGitswitch;-InstallMissingPrerequisitesdoes not implicitly install Git. - If Git is absent, the WorkForge profile remains a normal local folder instead of forcing
git init; profile registry loading and the normal WorkForge lifecycle remain available. - WinGet uses exact package IDs from the official
wingetsource with--no-upgradeand disabled package-manager prompts. - Existing Node.js below version 20, non-x64 Node.js, or an unprobeable Node.js command is treated as a conflict and is never automatically replaced.
- WorkForge does not invoke
winget upgrade, use a force-install option, or automatically elevate itself. Windows may still display its normal UAC consent prompt for a package installer. - After installing required components, WorkForge refreshes the current process PATH and revalidates required readiness before continuing.
- Failure to install optional Git is reported as a warning and WorkForge continues in Local Folder Mode.
- Raw WinGet output is not written into lifecycle JSONL logs.
WorkForge Control.cmd launches a temporary local HTML dashboard instead of exposing a network administration service.
- The Node control server binds only to
127.0.0.1on an ephemeral local port. - It never binds to
0.0.0.0and does not enable CORS. - The exact
Hostheader must match the loopback address and selected port, reducing DNS-rebinding exposure. - A fresh cryptographically random session secret lives only in server memory and is delivered through an HttpOnly, SameSite=Strict cookie.
- Mutating POST requests additionally require the exact same-origin
Originheader. - Browser JavaScript never receives the Secure MCP Tunnel Runtime API Key.
- Responses use a restrictive Content Security Policy, deny framing, disable caching, and load no remote scripts, styles, fonts, or analytics.
- The dashboard calls the same PowerShell Start, Stop, Status, Doctor, Update, and Uninstall implementations used by the CLI. The browser layer does not bypass their existing validation.
- RemoveEverything still requires the exact
REMOVE WORKFORGEphrase. The dashboard also requires an uninstall preview and explicit confirmation before invoking removal. - The control server changes its working directory to the system temporary directory before serving requests so verified release self-removal is not blocked by its current directory.
- Dashboard PowerShell,
cmd.exe, and timeout process-tree termination use explicit%SystemRoot%\System32executable paths rather than resolving executables from the temporary working directory or PATH. - Status polling is coalesced and cached briefly, and the browser polls every five seconds instead of continuously spawning lifecycle checks.
- No service, scheduled task, startup item, or persistent dashboard process is created. When polling stops, the local server exits after a bounded idle period.
The terminal path remains available through WorkForge Control.cmd --cli or direct scripts\Control.ps1 actions for diagnostics and recovery.
WorkForge v0.2.0 checks for Windows updates only from the fixed stable Release endpoint for NotNull92/workforge-mcp. It does not accept an arbitrary repository or download URL from the Dashboard, CLI, profile, or request body.
- Drafts, prereleases, and non-canonical semantic-version tags are rejected.
- The exact
WorkForge-v<version>-win-x64.zipasset and its exact.sha256companion are required. - Asset URLs must be HTTPS URLs under the canonical GitHub Release download path for this repository.
- The downloaded archive is size-bounded, SHA-256 verified before extraction, and its
.workforge-release.jsonversion must match the GitHub Release metadata. - Staging generates the full installed-engine immutable manifest before
current.jsonchanges. - Dashboard update installation requires an explicit same-origin POST confirmation. A background update check never installs anything.
- Existing
tunnel.local.yamlfiles are snapshotted as exact bytes. Runtime rebinding uses the existing tunnel ID and protected credential without rewriting the credential file. - If rebinding, local Doctor validation, activation, or tunnel restart fails, WorkForge restores the previous engine pointer, stable launcher files, prior tunnel configurations, and the pre-update running-tunnel set as far as the rollback procedure can complete.
The .sha256 companion protects against corruption and mismatched Release assets, but it is not an independent publisher signature. The GitHub repository/account and its published Release assets remain part of the update trust boundary. Code signing or an independent signing key would be a separate future hardening layer.
Direct filesystem tools enforce registered-profile path boundaries. shell_start validates its working directory against those boundaries, but the PowerShell command itself is not path-sandboxed: it runs as the current Windows user and can access any location allowed by Windows ACLs and UAC.
- Nothing is registered to start with Windows.
- Tunnel start is always an explicit user or Setup-session action.
- Tunnel configuration records the exact Node.js executable and compiled
dist/stdio.jspath that WorkForge validated, instead of a relativenode.exe dist/stdio.jscommand. - Configure Tunnel validates the selected profile, tunnel client, and MCP runtime before changing the protected local credential.
- On macOS, tunnel runtime metadata for both Apple Silicon and Intel is pinned in
runtime-lock.json; the installer verifies the selected archive SHA-256 before extraction. - macOS Runtime API Keys are stored in Keychain. WorkForge runs
securityin interactive mode and sends theadd-generic-passwordcommand, including hex-encoded password data, through stdin. The encoded secret is never placed in the OS process argument list. - macOS long-running supervisors start with
CONTROL_PLANE_API_KEYremoved from their inherited environment. Only the tunnel-client child receives the Keychain value through its explicit environment reference. - macOS tunnel configuration writes destination-local temporary files before atomic rename, so project configuration does not rely on cross-filesystem rename from
/tmp. - Commands are never replayed automatically.
- Connection-owned shell jobs are cancelled when their exact MCP connection closes.
- Windows Job Objects contain shell descendants and terminate the process tree when ownership ends.
- Same-profile shell jobs are serialized with a profile-specific mutex.
- Tunnel recovery uses bounded delays and stops after a limited restart budget.
- Stop intent is recorded before process termination so the supervisor cannot race an explicit user stop.
- Profile manifests are strict UTF-8 JSON and are SHA-256 pinned in the registry.
- Bootstrap context revisions prevent mutations under stale operating instructions.
- Text writes and replacements require the exact current SHA-256 or an explicit absent-file expectation.
- Writes use bounded, atomic replacement.
- Registered profile roots must be canonical, distinct, and non-overlapping.
- Reparse points are rejected across trusted profile, credential, release-engine, and uninstall paths.
Setup, Install, Repair, and Upgrade logs are ignored JSONL files under engine runtime\logs. Uninstall logs are written below the system temporary WorkForge directory because a verified release engine may delete itself.
The logger records UTC time, operation, stage, event, duration, and redacted detail. It does not intentionally record:
- runtime keys or tokens;
- complete tunnel IDs;
- raw process environments;
- personal email addresses;
- the literal Windows user-profile path.
Use -NoLog for controlled validation where no lifecycle log should be created. Use -Plain, NO_COLOR, or WORKFORGE_PLAIN_UI=1 for deterministic no-color output.
Every push and pull request runs a full-history privacy scan. It checks commit metadata, current tracked and untracked text, and reachable historical text blobs. It rejects new non-noreply commit addresses, personal home paths, non-example email addresses, private network details, phone numbers, concrete tunnel IDs, credential-shaped values, generated registries, lifecycle logs, uninstall receipts, release manifests, and runtime directories. An already-published GitHub merge may be grandfathered only by its exact immutable commit hash; this does not create a domain-wide or future-commit exception. Historical text blobs above the bounded scan limit fail closed unless their extension is an explicitly recognized binary format.
- Keep write confirmations enabled in ChatGPT.
- Begin with inspection and request exact paths before destructive work.
- Keep important work under version control and maintain separate backups.
- Review commands that install software, change security settings, publish content, or delete data.
- Use
Uninstall.ps1 -WhatIfbefore a removal when the target is unusual. - Do not connect a server build that you did not create or audit yourself.
- Treat files, web pages, command output, issue text, and generated instructions as untrusted data that may contain prompt injection.
Use the repository Security tab to report a vulnerability privately. Do not include runtime keys, personal paths, private logs, or unredacted screenshots in a public issue.