UFO is a Microsoft research project that lets a language model use your Windows desktop. Give it a request in plain English and a host agent picks the right applications, while app agents read each window through screenshots and Windows UI Automation and click, type and call app APIs to get it done, from filling in a spreadsheet to sending an email from Outlook.
The repository now holds two layers. UFO² is the single-machine Windows agent, marked as long-term support and the easier place to start. UFO³ Galaxy, newer and still in active development, plans a task as a graph of steps and hands them to agents on several devices, including Linux and Android, at once.
About 10,100 stars, MIT, at v3.0.10 when scanned, with two arXiv papers behind it. It is a research framework rather than a polished product: you bring your own model API key, setup is by config file, and a vision-capable model such as GPT-4o class gives the best results.
- Repository: github.com/microsoft/UFO
- Licence: MIT (MIT License)
- Language: Python. Stars: 10.1K. Forks: 1,080. Last push: Oct 23, 2026.
- Scan: safe, Oct 26, 2026, commit eae3c0a
Who it is for
Developers and researchers experimenting with computer-use agents, and Windows power users who want to automate multi-app chores and are comfortable editing YAML.
Getting started
1. Get the code and install the requirements (Python 3.10 or 3.11)
git clone https://github.com/microsoft/UFO.git && cd UFO && pip install -r requirements.txt2. Create your model config, then add your API key
copy config\ufo\agents.yaml.template config\ufo\agents.yaml3. Run a task
python -m ufo --task <your_task_name>UFO² needs Windows. Run it in a virtual environment or a spare Windows account or VM, since it moves the mouse and types into whatever is on screen.
Safety scan
We cloned microsoft/UFO at commit eae3c0a on Oct 26, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.
- No secrets, no committed binaries and no bare-IP URLs. The hosts in the code are model providers (OpenAI, Azure OpenAI, DeepSeek, Alibaba DashScope) and Bing search for the optional online help feature, plus .test domains in tests.
- The one pattern hit, /dev/tcp/ in ufo/client/mcp/http_servers/linux_mcp_server.py, is in a list of dangerous patterns the Linux command server refuses to run, a reverse-shell guard rather than a reverse shell.
- The agent works by taking screenshots and reading the UI tree, and those go to your model provider with each step; logs and screenshots are also saved locally under logs. Do not leave private documents open while it runs.
- 133 known advisories. The ones that ship are in requirements.txt, which pins versions you install: 7 critical, in Pillow 11.3.0, sentence-transformers 2.6.0 and fastmcp 2.11.3. The other 59 are in the Galaxy web UI's npm build tooling.
- One workflow, no pull_request_target, no third-party actions. Security policy, Dependabot, contributing guide and code of conduct present.
What the scanner counted
| Check | Result |
|---|---|
| Secrets | None found. |
| Suspicious code | 1 pattern hit found and read; every one is listed under the raw findings. |
| Install-time code | None: nothing runs at install beyond the package manager itself. |
| Committed binaries | None. |
| CI workflows | 1 workflow. None use pull_request_target. No third-party actions. |
| Network hosts | 13 distinct hosts referenced from source; most often api.openai.com, test.openai.azure.com, vitejs.dev, rebinding.test. 7 URLs to a bare IP address, listed under the raw findings. |
| Known vulnerabilities | 133 advisories across 500 pinned packages: 7 critical, 79 high, 43 moderate, 4 low. galaxy/webui/frontend/package-lock.json: 474 packages, 59 advisories; requirements.txt: 39 packages, 74 advisories. |
| Project hygiene | Has security policy, automated dependency updates, licence file, contributing guide. Missing CodeQL. |
| OpenSSF Scorecard | Not scored: the project is not in Scorecard's weekly index. |
The raw findings
Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.
Pattern hits (1)
| Where | Rule | Match |
|---|---|---|
| ufo/client/mcp/http_servers/linux_mcp_server.py:201 | raw-socket-shell | re.compile(r"/dev/tcp/"), |
URLs to bare IP addresses (7)
| Where | Rule | Match |
|---|---|---|
| tests/test_url_security.py:47 | ip-literal-url | "http://8.8.8.8/", |
| tests/test_url_security.py:104 | ip-literal-url | url_security.safe_get("http://8.8.8.8/", session=session) |
| tests/test_url_security.py:134 | ip-literal-url | url_security.safe_get("http://8.8.8.8/") |
| tests/test_url_security.py:156 | ip-literal-url | response.headers["Location"] = "http://8.8.4.4/final" |
| tests/test_url_security.py:166 | ip-literal-url | url_security.safe_get("http://8.8.8.8/start", session=session) |
| tests/test_url_security.py:223 | ip-literal-url | response.headers["Location"] = "http://8.8.4.4/final" |
| tests/test_url_security.py:233 | ip-literal-url | "http://8.8.8.8/start", |
Worst known vulnerabilities (24 of 133)
| Advisory | Severity | Package | Summary |
|---|---|---|---|
| GHSA-332p-7hrc-92wf | critical | pillow@11.3.0 | Pillow: Heap buffer overflow in _tiffWriteProc when saving TIFF to BytesIO |
| GHSA-5x8w-8jj5-q52h | critical | pillow@11.3.0 | Pillow: Heap buffer overflow in FlashPix (FPX) JPEG decoding leads to code execution |
| GHSA-8g5g-8vmr-9782 | critical | pillow@11.3.0 | Pillow: Heap buffer overflow in ImagingJpegDecode |
| GHSA-v9pv-5gc8-w2m6 | critical | pillow@11.3.0 | Pillow multi-frame loaders can reuse stale native image storage after mode transitions |
| GHSA-w889-685w-c8fh | critical | pillow@11.3.0 | Pillow: Argument Injection in Ghostscript call, potentially leading into RCE |
| GHSA-jhr6-gm9c-rqjv | critical | sentence-transformers@2.6.0 | sentence-transformers local model loading bypasses trust_remote_code and executes custom Python |
| GHSA-vv7q-7jx5-f767 | critical | fastmcp@2.11.3 | FastMCP OpenAPI Provider has an SSRF & Path Traversal Vulnerability |
| GHSA-3jxr-9vmj-r5cp | high | brace-expansion@1.1.12 | brace-expansion: DoS via exponential-time expansion of consecutive non-expanding {} groups |
| GHSA-6j4f-fj2g-mc7p | high | brace-expansion@1.1.12 | brace-expansion: DoS via uncontrolled recursion in parseCommaParts causing stack exhaustion |
| GHSA-mh99-v99m-4gvg | high | brace-expansion@1.1.12 | brace-expansion: DoS via unbounded expansion length causing an out-of-memory process crash |
| GHSA-qhr7-859c-m2p7 | high | brace-expansion@1.1.12 | brace-expansion: DoS via uncontrolled recursion on nested brace groups causing stack exhaustion |
| GHSA-rgw5-rvv9-x895 | high | brace-expansion@1.1.12 | brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-14257 mitigation |
| GHSA-23c5-xmqv-rm74 | high | minimatch@3.1.2 | minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regular expressions |
| GHSA-3ppc-4f35-3m26 | high | minimatch@3.1.2 | minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern |
| GHSA-7r86-cg39-jmmj | high | minimatch@3.1.2 | minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent GLOBSTAR segments |
| GHSA-3jxr-9vmj-r5cp | high | brace-expansion@2.0.2 | brace-expansion: DoS via exponential-time expansion of consecutive non-expanding {} groups |
| GHSA-6j4f-fj2g-mc7p | high | brace-expansion@2.0.2 | brace-expansion: DoS via uncontrolled recursion in parseCommaParts causing stack exhaustion |
| GHSA-mh99-v99m-4gvg | high | brace-expansion@2.0.2 | brace-expansion: DoS via unbounded expansion length causing an out-of-memory process crash |
| GHSA-qhr7-859c-m2p7 | high | brace-expansion@2.0.2 | brace-expansion: DoS via uncontrolled recursion on nested brace groups causing stack exhaustion |
| GHSA-rgw5-rvv9-x895 | high | brace-expansion@2.0.2 | brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-14257 mitigation |
| GHSA-73wf-gq98-2v4g | high | browserslist@4.27.0 | Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats.json custom stats (normalizeStats) |
| GHSA-c83g-rgw3-j3cx | high | browserslist@4.27.0 | Browserslist: Unbounded memory growth (no cache eviction) via distinct query results, leading to eventual OOM |
| GHSA-25h7-pfq9-p65f | high | flatted@3.3.3 | flatted vulnerable to unbounded recursion DoS in parse() revive phase |
| GHSA-rf6f-7fwh-wjgh | high | flatted@3.3.3 | Prototype Pollution via parse() in NodeJS flatted |
By the numbers
| Stars | 10.1K |
|---|---|
| Forks | 1,080 |
| Contributors | 30 |
| Commits | 1,932 |
| Open issues | 45 |
| Open pull requests | 49 |
| Releases | 19 |
| Latest release | v3.0.10 |
| Licence | MIT |
| Main language | Python |
| Project age | 2 years |
| Last push | Oct 23, 2026 |
| Tracked files | 932 |
| Lines of code | 255.4K |
| Checkout size | 72 MB |
Lines by language: Python 133.4K, Markdown 109.8K, TypeScript 6,009, YAML 4,815, JSON 756, CSS 412.
Questions
Is UFO free?
Yes. UFO is open source under the MIT licence. Running it costs whatever your chosen model provider charges, since every step sends a request and usually a screenshot.
Does UFO work on Mac or Linux?
UFO², the main desktop agent, is Windows only. UFO³ Galaxy can coordinate agents on Linux and Android devices too, but it is newer and harder to set up.
Is it safe to let UFO control my computer?
It only does what it is asked, but a model can misread a screen and click the wrong thing. Try it in a virtual machine or a spare account first, and keep sensitive windows closed while it works.
This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.
