Ollama is the shortest path from a bare laptop to a running language model. One installer, one command to pull a model, and you have a chat prompt in the terminal and an OpenAI-compatible API on localhost:11434 that every other tool on this list can talk to. It packages llama.cpp's engine with a model library, a registry and a background service, so the GPU detection, quantisation formats and memory management that used to take an afternoon are handled for you.
It earns its place on this list for being the thing people actually run. Open WebUI, AnythingLLM, Dify and most editor plugins ship an Ollama option first, which means a model you pull today plugs into the rest of your setup without another download. The project is MIT-licensed, written in Go, and moves fast: a new model family usually runs in Ollama within days of release.
- Repository: github.com/ollama/ollama
- Licence: MIT (MIT License)
- Language: Go. Stars: 181.1K. Forks: 17.9K. Last push: Sep 16, 2026.
- Scan: clean, read the notes, Sep 15, 2026, commit a43fad1
Who it is for
Anyone who wants a private assistant that never sends a prompt off the machine, developers who need a local model endpoint for testing, and people with a decent GPU or an Apple Silicon Mac who would rather use it than pay per token.
Getting started
1. Install on macOS or Linux (Windows has an installer on ollama.com)
curl -fsSL https://ollama.com/install.sh | sh2. Pull and chat with a model
ollama run gemma43. Use it from code, on the local API
curl http://localhost:11434/api/chat -d '{"model":"gemma4","messages":[{"role":"user","content":"Why is the sky blue?"}]}'The installer is a shell script fetched from ollama.com and run as is. If that bothers you, the macOS and Windows downloads on the same site are ordinary installers, and the Linux script can be read first: it is the same file the scan lists under installer scripts.
Safety scan
We cloned ollama/ollama at commit a43fad1 on Sep 15, 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 and no packed or self-decoding code across roughly 370,000 lines of Go, C and TypeScript. The bare-IP URLs the scanner lists are test fixtures using TEST-NET addresses.
- scripts/install.sh, the curl | sh installer for Linux, is about 450 lines. It uses sudo to create an ollama user and a systemd service, and offers to install NVIDIA or AMD drivers from the vendors' own repositories. Read it before running it as root; the macOS and Windows installers are ordinary apps.
- The pattern hits are all one feature: ollama launch can install and configure a dozen coding agents for you (Claude Code, Codex, Cline, Copilot, Kimi, Hermes, Qwen and others), and for five of them it does so by running the vendor's own curl | bash installer. Convenient, and exactly the kind of command you should know is happening.
- Most of the known advisories sit in app/ui/app/package-lock.json, the desktop app's JavaScript build tooling (Vitest, Vite), which never ships to users. The ones in go.mod that rate critical concern the SSH server side of golang.org/x/crypto, a package Ollama only uses to sign registry requests with a local key.
- Five workflows, none using pull_request_target. The 17 third-party actions are pinned to tags rather than commits, which is common and slightly weaker than it could be. Security policy, licence and contributing guide present; no Dependabot or CodeQL in the repository.
What the scanner counted
| Check | Result |
|---|---|
| Secrets | None found. |
| Suspicious code | 9 pattern hits found and read; every one is listed under the raw findings. |
| Install-time code | 2 installer scripts (one can call sudo) |
| Committed binaries | None. |
| CI workflows | 5 workflows. None use pull_request_target. 17 of 17 third-party actions pinned to a tag rather than a commit. |
| Network hosts | 40 distinct hosts referenced from source; most often ollama.com, github.com, msdn.microsoft.com, chatgpt.com. 23 URLs to a bare IP address, listed under the raw findings. |
| Known vulnerabilities | 155 advisories across 954 pinned packages: 12 critical, 53 high, 56 moderate, 11 low, 23 unrated. app/ui/app/package-lock.json: 910 packages, 113 advisories; go.mod: 77 packages, 42 advisories. |
| Project hygiene | Has security policy, licence file, contributing guide. Missing automated dependency updates, 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 (9)
| Where | Rule | Match |
|---|---|---|
| app/cmd/app/app_darwin.m:1597 | persistence | // Maps to the file Ollama.app/Contents/Library/LaunchAgents/com.ollama.ollama.plist |
| cmd/launch/claude.go:157 | download-piped-to-shell | "curl -fsSL https://claude.ai/install.sh | bash", |
| cmd/launch/claude_test.go:268 | download-piped-to-shell | want: "curl -fsSL https://claude.ai/install.sh | bash", |
| cmd/launch/claude_test.go:274 | download-piped-to-shell | want: "curl -fsSL https://claude.ai/install.sh | bash", |
| cmd/launch/hermes.go:29 | download-piped-to-shell | hermesInstallScript = "curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -s -- --skip-setup" |
| cmd/launch/kimi.go:310 | download-piped-to-shell | "curl -LsSf https://code.kimi.com/install.sh | bash", |
| cmd/launch/muse.go:60 | download-piped-to-shell | var museInstallCommand = []string{"bash", "-c", "curl -fsSL https://dev.meta.ai/install.sh | bash"} |
| cmd/launch/opencode.go:17 | download-piped-to-shell | const openCodeInstallScript = "curl -fsSL https://opencode.ai/install | bash" |
| scripts/install.sh:236 | persistence | $SUDO systemctl enable ollama |
URLs to bare IP addresses (23)
| Where | Rule | Match |
|---|---|---|
| api/client_test.go:24 | ip-literal-url | "only address": {value: "1.2.3.4", expect: "http://1.2.3.4:11434"}, |
| api/client_test.go:26 | ip-literal-url | "address and port": {value: "1.2.3.4:1234", expect: "http://1.2.3.4:1234"}, |
| api/client_test.go:27 | ip-literal-url | "scheme http and address": {value: "http://1.2.3.4", expect: "http://1.2.3.4:80"}, |
| api/client_test.go:27 | ip-literal-url | "scheme http and address": {value: "http://1.2.3.4", expect: "http://1.2.3.4:80"}, |
| api/client_test.go:28 | ip-literal-url | "scheme https and address": {value: "https://1.2.3.4", expect: "https://1.2.3.4:443"}, |
| api/client_test.go:28 | ip-literal-url | "scheme https and address": {value: "https://1.2.3.4", expect: "https://1.2.3.4:443"}, |
| api/client_test.go:29 | ip-literal-url | "scheme, address, and port": {value: "https://1.2.3.4:1234", expect: "https://1.2.3.4:1234"}, |
| api/client_test.go:29 | ip-literal-url | "scheme, address, and port": {value: "https://1.2.3.4:1234", expect: "https://1.2.3.4:1234"}, |
| envconfig/config_test.go:21 | ip-literal-url | "only address": {"1.2.3.4", "http://1.2.3.4:11434"}, |
| envconfig/config_test.go:23 | ip-literal-url | "address and port": {"1.2.3.4:1234", "http://1.2.3.4:1234"}, |
| envconfig/config_test.go:33 | ip-literal-url | "extra space": {" 1.2.3.4 ", "http://1.2.3.4:11434"}, |
| envconfig/config_test.go:34 | ip-literal-url | "extra quotes": {"\"1.2.3.4\"", "http://1.2.3.4:11434"}, |
| envconfig/config_test.go:35 | ip-literal-url | "extra space+quotes": {" \" 1.2.3.4 \" ", "http://1.2.3.4:11434"}, |
| envconfig/config_test.go:36 | ip-literal-url | "extra single quotes": {"'1.2.3.4'", "http://1.2.3.4:11434"}, |
| envconfig/config_test.go:37 | ip-literal-url | "http": {"http://1.2.3.4", "http://1.2.3.4:80"}, |
| envconfig/config_test.go:37 | ip-literal-url | "http": {"http://1.2.3.4", "http://1.2.3.4:80"}, |
| envconfig/config_test.go:38 | ip-literal-url | "http port": {"http://1.2.3.4:4321", "http://1.2.3.4:4321"}, |
| envconfig/config_test.go:38 | ip-literal-url | "http port": {"http://1.2.3.4:4321", "http://1.2.3.4:4321"}, |
| envconfig/config_test.go:39 | ip-literal-url | "https": {"https://1.2.3.4", "https://1.2.3.4:443"}, |
| envconfig/config_test.go:39 | ip-literal-url | "https": {"https://1.2.3.4", "https://1.2.3.4:443"}, |
| envconfig/config_test.go:40 | ip-literal-url | "https port": {"https://1.2.3.4:4321", "https://1.2.3.4:4321"}, |
| envconfig/config_test.go:40 | ip-literal-url | "https port": {"https://1.2.3.4:4321", "https://1.2.3.4:4321"}, |
| server/codex_proxy_test.go:58 | ip-literal-url | req := httptest.NewRequest(http.MethodGet, "http://192.0.2.1:11434"+tt.path, nil) |
Installer scripts (2)
- scripts/install.ps1, 324 lines; talks to ollama.com
- scripts/install.sh, 456 lines, uses sudo; talks to developer.download.nvidia.com, dl.fedoraproject.org, docs.nvidia.com, learn.microsoft.com, ollama.com
Worst known vulnerabilities (24 of 155)
| Advisory | Severity | Package | Summary |
|---|---|---|---|
| GHSA-g8mr-85jm-7xhm | critical | @vitest/browser@3.2.4 | Vitest Browser: Exposed Browser Mode API Can Proxy CDP and Overwrite Config Files, Leading to RCE |
| GHSA-p63j-vcc4-9vmv | critical | @vitest/browser@3.2.4 | @vitest/browser: Browser Mode provider commands bypass the file-access permission gate |
| GHSA-mv8w-475r-vwqw | critical | seroval@1.3.2 | seroval: `seroval.fromJSON()` Promise resolver type confusion invokes attacker-controlled methods during deserialization |
| GHSA-23hp-3jrh-7fpw | critical | tar@7.4.3 | node-tar: Decompression/parse DoS via unlimited input |
| GHSA-5xrq-8626-4rwp | critical | vitest@3.2.4 | When Vitest UI server is listening, arbitrary file can be read and executed |
| GHSA-5cgq-3rg8-m6cv | critical | golang.org/x/crypto@0.43.0 | golang.org/x/crypto vulnerable to auth bypass via unenforced @revoked status |
| GHSA-89gr-r52h-f8rx | critical | golang.org/x/crypto@0.43.0 | golang.org/x/crypto: FIDO/U2F security key physical presence check can be bypassed |
| GHSA-f5wc-c3c7-36mc | critical | golang.org/x/crypto@0.43.0 | golang.org/x/crypto doesn't drop invoking agent constraints when forwarding keys |
| GHSA-jppx-rxg9-jmrx | critical | golang.org/x/crypto@0.43.0 | golang.org/x/crypto doesn't enforce invoking key constraints |
| GHSA-rm3j-f69w-wqmq | critical | golang.org/x/crypto@0.43.0 | golang.org/x/crypto vulnerable to infinite loop on large channel writes |
| GHSA-vgwf-h737-ff37 | critical | golang.org/x/crypto@0.43.0 | golang.org/x/crypto: Invoking client can cause server deadlock on unexpected responses |
| GHSA-x527-x647-q7gg | critical | golang.org/x/crypto@0.43.0 | golang.org/x/crypto: Invoking VerifiedPublicKeyCallback permissions skip enforcement |
| GHSA-c2c7-rcm5-vvqj | high | picomatch@4.0.2 | Picomatch has a ReDoS vulnerability via extglob quantifiers |
| GHSA-3jxr-9vmj-r5cp | high | brace-expansion@2.0.2 | brace-expansion: DoS via exponential-time expansion of consecutive non-expanding {} groups |
| 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-rgw5-rvv9-x895 | high | brace-expansion@2.0.2 | brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-14257 mitigation |
| GHSA-23c5-xmqv-rm74 | high | minimatch@9.0.5 | minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regular expressions |
| GHSA-3ppc-4f35-3m26 | high | minimatch@9.0.5 | minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern |
| GHSA-7r86-cg39-jmmj | high | minimatch@9.0.5 | minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent GLOBSTAR segments |
| GHSA-3jxr-9vmj-r5cp | high | brace-expansion@1.1.12 | brace-expansion: DoS via exponential-time expansion of consecutive non-expanding {} groups |
| 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-rgw5-rvv9-x895 | high | brace-expansion@1.1.12 | brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-14257 mitigation |
| GHSA-73wf-gq98-2v4g | high | browserslist@4.25.0 | Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats.json custom stats (normalizeStats) |
| GHSA-c83g-rgw3-j3cx | high | browserslist@4.25.0 | Browserslist: Unbounded memory growth (no cache eviction) via distinct query results, leading to eventual OOM |
By the numbers
| Stars | 181.1K |
|---|---|
| Forks | 17.9K |
| Contributors | 615 |
| Commits | 5,757 |
| Open issues | 2,492 |
| Open pull requests | 1,523 |
| Releases | 253 |
| Latest release | v0.34.1 |
| Licence | MIT |
| Main language | Go |
| Project age | 3 years |
| Last push | Sep 16, 2026 |
| Tracked files | 1,297 |
| Lines of code | 373.1K |
| Checkout size | 55 MB |
Lines by language: Go 302.6K, TypeScript 22K, C/C++ header 16.9K, Markdown 10.3K, C++ 4,161, YAML 3,755.
Questions
Is Ollama free?
Yes. Ollama is MIT-licensed and free to use for any purpose, and the models in its library are free to download, each under its own licence (Meta, Google, Alibaba and Mistral all set their own terms). There is an optional paid cloud tier for running larger models on Ollama's servers; nothing on your machine depends on it.
Does Ollama send my prompts anywhere?
Not by default. Models run on your own hardware and the API listens on localhost only. Model downloads come from ollama.com, and the cloud models are the one feature that sends prompts off the machine, and only when you choose one of them explicitly.
What hardware do I need to run Ollama?
A 4B-parameter model runs comfortably in 8 GB of RAM on a CPU, and quickly on any Apple Silicon Mac or a GPU with 6 GB of memory. A 30B model wants 24 GB. Ollama picks a quantised version by default, so the memory figures on ollama.com are what you should plan for.
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.