MrTechKing

6 min read

Memos: A Self-Hosted Timeline for Your Quick Notes (GitHub, Scanned)

A self-hosted note app for quick thoughts, kept in a personal timeline on your own server. Markdown, tags and sharing.

Memos logo
✅
Scan: safe. Nothing malicious and no critical advisories. The high ones are in the web interface's build tools and libraries, and none reach the Go server. Scanned Nov 10, 2026; the full report is below.

Memos is a note app for the small stuff: a passing thought, a link, a quote, a to-do. Each memo can be a single sentence or a longer Markdown entry, and it stays filed under the day you wrote it, so your notes build up into a timeline you can scroll back through. Tags connect related memos across days. It feels closer to a private social feed than a document editor.

It runs on your own server, so your notes stay in one folder you control. You decide what stays private, what to share with family or friends and what to publish on the web, and shared spaces let several people write side by side. There is a web clipper for Chrome and Firefox, a Telegram bot, an API and an MCP server for connecting AI tools, plus optional speech-to-text that works with an OpenAI or Gemini key you add.

Memos is MIT-licensed and written in Go, with about 64,000 stars and 418 contributors since 2021. Version 26.11.0 came out on 1 November 2026.

  • Repository: github.com/usememos/memos
  • Licence: MIT (MIT License)
  • Language: Go. Stars: 64.4K. Forks: 4,946. Last push: Nov 9, 2026.
  • Scan: safe, Nov 10, 2026, commit e4f3fb2

Who it is for

People who run a home server or a small VPS and want a private place for quick notes, families who want a shared notebook, and anyone who likes the feel of a timeline but not handing their thoughts to a social network.

Getting started

1. Try the public demo first

https://demo.usememos.com

2. Run it with Docker, keeping all data in ~/.memos

docker run -d --name memos -p 5230:5230 -v ~/.memos:/var/opt/memos neosmemo/memos:stable

3. Open it and create the first account

http://localhost:5230

Everything Memos keeps is in that one folder, so back it up. If you open it to the internet, put it behind HTTPS. There is also a curl | sh installer for a plain binary; it uses sudo, so read it first or stick with Docker.

Safety scan

We cloned usememos/memos at commit e4f3fb2 on Nov 10, 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 secret hits and no committed binaries across 1,356 files and about 321,000 lines. Of the 9 pattern hits, 2 are usage comments in scripts/install.sh showing its curl | sh command, and 7 are long lines in machine-generated protobuf files under web/src/types/proto.
  • scripts/install.sh is about 300 lines. It downloads a release from GitHub and uses sudo to install the binary and a system service. The Docker image is the documented route and needs none of that.
  • 62 advisories, none critical. The Go server's lockfile has just 1 low and 4 unrated. All 20 high ones are in web/pnpm-lock.yaml, the web interface: 10 in undici, plus browserslist, nanoid, PostCSS, Vite and source-map-js, which are build tools. The 2 in React Router concern its server-rendering mode and route matching in the browser; Memos uses it as a plain single-page app.
  • No analytics service among the hosts. The AI hosts, api.openai.com and generativelanguage.googleapis.com, are defaults for the optional speech-to-text, which stays off until an admin adds a provider and key.
  • 8 workflows, none using pull_request_target. None of the 22 third-party actions is pinned to a commit. There is a security policy; no Dependabot or CodeQL. The README opens with a featured sponsor, CodeRabbit, an AI code review service, which has nothing to do with using Memos.

What the scanner counted

CheckResult
SecretsNone found.
Suspicious code9 pattern hits found and read; every one is listed under the raw findings.
Install-time code1 installer script (one fetches and runs a remote script; one can call sudo)
Committed binariesNone.
CI workflows8 workflows. None use pull_request_target. 22 of 22 third-party actions pinned to a tag rather than a commit.
Network hosts40 distinct hosts referenced from source; most often github.com, s3.example.com, usememos.com, idp.example.com. 24 URLs to a bare IP address, listed under the raw findings.
Known vulnerabilities62 advisories across 458 pinned packages: 0 critical, 20 high, 28 moderate, 10 low, 4 unrated. go.mod: 144 packages, 5 advisories; web/pnpm-lock.yaml: 314 packages, 57 advisories.
Project hygieneHas security policy, licence file. Missing automated dependency updates, CodeQL, contributing guide.
OpenSSF ScorecardNot 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)
WhereRuleMatch
scripts/install.sh:27download-piped-to-shellcurl -fsSL https://raw.githubusercontent.com/usememos/memos/main/scripts/install.sh | sh
scripts/install.sh:28download-piped-to-shellcurl -fsSL https://raw.githubusercontent.com/usememos/memos/main/scripts/install.sh | sh -s -- --version 26.10.0
web/src/types/proto/api/attachment_service_pb.ts:19very-long-line5564 chars
web/src/types/proto/api/idp_service_pb.ts:19very-long-line3233 chars
web/src/types/proto/api/instance_service_pb.ts:23very-long-line9035 chars
web/src/types/proto/api/memo_service_pb.ts:23very-long-line9926 chars
web/src/types/proto/api/space_service_pb.ts:19very-long-line7088 chars
web/src/types/proto/api/user_service_pb.ts:25very-long-line20524 chars
web/src/types/proto/google/api/client_pb.ts:31very-long-line5087 chars
URLs to bare IP addresses (24)
WhereRuleMatch
internal/linkmeta/html_meta_test.go:181ip-literal-urlmeta, err := fetcher.Get(context.Background(), "http://93.184.216.34/post")
internal/linkmeta/html_meta_test.go:186ip-literal-urlImage: "http://93.184.216.34/oembed.png",
internal/linkmeta/html_meta_test.go:221ip-literal-urlmeta, err := fetcher.Get(context.Background(), "http://93.184.216.34/post")
internal/linkmeta/html_meta_test.go:240ip-literal-urlmeta, err := fetcher.Get(context.Background(), "http://93.184.216.34/spa")
internal/linkmeta/html_meta_test.go:255ip-literal-url_, err := fetcher.Get(context.Background(), "http://93.184.216.34/page")
internal/linkmeta/html_meta_test.go:267ip-literal-urlmeta, err := fetcher.Get(context.Background(), "http://93.184.216.34/original")
internal/linkmeta/html_meta_test.go:287ip-literal-url_, err := fetcher.Get(context.Background(), "http://93.184.216.34/page")
internal/linkmeta/html_meta_test.go:302ip-literal-urlmeta, err := fetcher.Get(context.Background(), "http://93.184.216.34/page")
internal/linkmeta/html_meta_test.go:318ip-literal-urlmeta, err := fetcher.Get(context.Background(), "http://93.184.216.34/page")
internal/linkmeta/html_meta_test.go:321ip-literal-urlrequire.Equal(t, "http://93.184.216.34/early.png", meta.Image)
internal/linkmeta/html_meta_test.go:340ip-literal-urlmeta, err := fetcher.Get(context.Background(), "http://93.184.216.34/post")
internal/linkmeta/html_meta_test.go:343ip-literal-urlrequire.Equal(t, "http://93.184.216.34/late.png", meta.Image)
internal/linkmeta/html_meta_test.go:358ip-literal-url_, err := fetcher.Get(ctx, "http://93.184.216.34/page")
internal/linkmeta/html_meta_test.go:375ip-literal-urlfirst, err := successFetcher.Get(context.Background(), "HTTP://93.184.216.34:80/page#one")
internal/linkmeta/html_meta_test.go:378ip-literal-urlsecond, err := successFetcher.Get(context.Background(), "http://93.184.216.34/page#two")
internal/linkmeta/html_meta_test.go:384ip-literal-url_, err = successFetcher.Get(context.Background(), "http://93.184.216.34/page")
internal/linkmeta/html_meta_test.go:395ip-literal-url_, err := failureFetcher.Get(context.Background(), "http://93.184.216.34/failure")
internal/linkmeta/html_meta_test.go:400ip-literal-url_, err = failureFetcher.Get(context.Background(), "http://93.184.216.34/failure")
internal/linkmeta/html_meta_test.go:436ip-literal-urlmeta, err := fetcher.Get(context.Background(), "http://93.184.216.34/shared")
internal/linkmeta/html_meta_test.go:476ip-literal-url_, _ = fetcher.Get(context.Background(), "http://93.184.216.34/page?id="+string(rune('a'+index)))
internal/webhook/webhook_test.go:47ip-literal-urlrequire.Error(t, ValidateURL("http://100.100.100.200/hook"))
internal/webhook/webhook_test.go:49ip-literal-urlrequire.NoError(t, ValidateURL("http://100.100.100.200/hook"))
internal/webhook/webhook_test.go:50ip-literal-urlrequire.Error(t, ValidateURL("http://100.100.100.201/hook"))
internal/webhook/webhook_test.go:340ip-literal-urlrequire.Error(t, ValidateURL("http://100.100.100.200/hook"))
Installer scripts (1)
  • scripts/install.sh, 300 lines, uses sudo, fetches and runs a remote script; talks to api.github.com, github.com, raw.githubusercontent.com
Worst known vulnerabilities (24 of 62)
AdvisorySeverityPackageSummary
GHSA-73wf-gq98-2v4ghighbrowserslist@4.28.2Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats.json custom stats (normalizeStats)
GHSA-c83g-rgw3-j3cxhighbrowserslist@4.28.2Browserslist: Unbounded memory growth (no cache eviction) via distinct query results, leading to eventual OOM
GHSA-28wg-ghj8-5hjvhighnanoid@3.3.11nanoid: non-secure generators can loop indefinitely with negative size
GHSA-2v37-7h3g-55p8highnanoid@3.3.11nanoid: custom generators can loop indefinitely when size is zero
GHSA-xwg4-73v4-xw9whighnanoid@3.3.11nanoid: Integer Overflow or Wraparound
GHSA-r28c-9q8g-f849highpostcss@8.5.14PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) leads to Arbitrary .map File Disclosure
GHSA-chx6-hx7r-mcp5highreact-router@7.15.0React Router: Unauthenticated Denial of Service via Inefficient Route Matching
GHSA-qwww-vcr4-c8h2highreact-router@7.15.0React Router: RSC Mode CSRF Bypass Allows Action Execution Before 400 Response
GHSA-68fv-2mgg-jv7qhighsource-map-js@1.2.1source-map-js allows event-loop denial of service through indexed source-map section offsets
GHSA-2m5v-pch6-74hxhighundici@7.25.0undici vulnerable to TLS certificate validation bypass via dropped tls options in Agent
GHSA-4cwx-7wf7-3272highundici@7.25.0undici vulnerable to cross-user information disclosure and parse-time crash via degenerate private cache directives
GHSA-4w7w-5xrc-9h26highundici@7.25.0undici vulnerable to cache poisoning and cross-user disclosure via cross-origin redirects
GHSA-hm92-r4w5-c3mjhighundici@7.25.0undici vulnerable to cross-origin request routing via SOCKS5 proxy pool reuse
GHSA-qrxm-fqhp-jwvmhighundici@7.25.0undici vulnerable to Denial of Service via TLS 1.2 certificate-changing renegotiation
GHSA-rfgv-xxqx-mfg5highundici@7.25.0undici vulnerable to Denial of Service via unrequested WebSocket subprotocol
GHSA-vmh5-mc38-953ghighundici@7.25.0undici vulnerable to TLS certificate validation bypass via dropped requestTls in SOCKS5 ProxyAgent
GHSA-vxpw-j846-p89qhighundici@7.25.0undici WebSocket client vulnerable to denial of service via fragment count bypass
GHSA-w293-vg96-wgc3highundici@7.25.0undici vulnerable to TLS certificate validation bypass via dropped connect options in BalancedPool
GHSA-xjj6-f33q-929chighundici@7.25.0undici vulnerable to Denial of Service via unhandled error on excessive content-encodings
GHSA-587h-7wmj-h5pmhighvite@8.0.11launch-editor: `fs.existsSync()` existence check can be bypassed on Windows
GHSA-82fw-gwwq-j7x9moderate@vitest/mocker@4.1.5Vitest: Path Traversal / Arbitrary File Read via @vitest/mocker Redirect Mock
GHSA-qxg6-89mg-rqv8moderate@vitest/mocker@4.1.5Vitest: Code injection via unauthenticated manual mock registration
GHSA-w5vr-8v7q-w6rvmoderatebaseline-browser-mapping@2.10.23baseline-browser-mapping process termination on invalid input causes denial of service
GHSA-fxqj-rqcc-2cmpmoderatepostcss@8.5.14PostCSS: incomplete fix of GHSA-6g55-p6wh-862q - attacker-controlled sourceMappingURL reads arbitrary .map files when `f…

By the numbers

Stars64.4K
Forks4,946
Contributors418
Commits4,935
Open issues26
Open pull requests36
Releases103
Latest release26.11.0
LicenceMIT
Main languageGo
Project age4 years
Last pushNov 9, 2026
Tracked files1,356
Lines of code320.9K
Checkout size14 MB

Lines by language: Go 155.5K, TypeScript 79.8K, JSON 66.8K, YAML 7,166, Protobuf 4,953, Markdown 4,508.

Questions

Is Memos free?

Yes. Memos is free and open source under the MIT licence. You pay only for the server you run it on, if any.

Do I need a server to use Memos?

You need somewhere to run it, such as a home server, a NAS that supports Docker, a small cloud VPS or your own computer. The README covers self-hosting and offers a public demo to try first.

Can I use Memos on my phone?

Yes, through your phone's browser pointed at your server. The web clipper and Telegram bot are other ways to send notes in.


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.