SamAcctX c75a2f60b5 server: sanitised session ids, chat length limit, websocket read limit, leaky frame queues (#712)
* server: generated video pipelines keep at most one raw frame queued

GetPipeline used plain `queue` elements, which buffer up to 1s / 200
buffers. When the encoder cannot keep up, frames pile up there and the
stream (and every reaction to input) falls behind by up to that much.
The queues now hold only the newest frame (leaky=downstream): a slow
encoder drops frames instead of adding latency.

Measured input-to-display latency (Alt+F2/Escape opens/closes a dialog,
time to the first changed received frame; xfce image built with ./build,
1920x1080, default VP8 pipeline, 30 trials per run, runs interleaved):

                  before p50/p90 ms     after p50/p90 ms
  no CPU limit    268/303, 188/225      183/217, 157/226
  --cpus=1        270/422, 362/673      155/237, 200/428

fps unchanged without a limit (25), slightly higher with one (22.5 ->
23.5-24). Pipelines given as raw gst strings are unchanged.

Tests: TestVideoConfigGetPipelineQueues; client e2e on the built image.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* server: session ids no longer carry the login name verbatim

The multiuser and noauth providers built the session id as
"<username>-<token>". The v3 API addresses sessions and members by id
in the URL path (DELETE /api/sessions/{id}, POST /api/members/{id},
POST /api/room/control/give/{id}), so a login name like
"x/../../logout?" produced an id that sent an admin's unencoded
request to another endpoint, and even when the client encodes it, an
id with "/" never matches the chi route: such a member could not be
kicked, muted or banned.

utils.SafeID maps a name to letters and digits of any script plus
".", "_" and "-": every run of other characters becomes one "-",
leading and trailing "-" and "." are trimmed, the result is cut to 64
characters, and an empty result becomes "user". Nothing with a meaning
in a URL path survives; letters outside ASCII are kept so names such as
"Müller" stay recognisable (clients percent-encode ids in paths). Both
providers now use SafeID(username) + "-" + token; the profile name
keeps the name as typed, so nothing changes on screen.

The file and object providers use the username itself as the member
id. Members there are created explicitly by an admin, so
POST /api/members now rejects a name SafeID would change with a 400
instead of silently altering it. The oauth provider derives ids from
the IdP subject ("oauth:" + sub) and is unchanged.

Tests: TestSafeID (pkg/utils).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* server: chat plugin limits message length (chat.max_length)

The chat plugin accepted text of any size, over the websocket
(chat/message) and over REST (POST /api/chat), and broadcast it to
every session. The web client caps its input box at 512 characters,
but any client can send more, and one large message stalls every
viewer's renderer.

New option chat.max_length (default 512, counted in characters with
utf8.RuneCountInString, not bytes; 0 disables the limit). Both paths
go through one check: REST answers 400 with the length and the limit,
the websocket handler logs at warn level and drops the message, as it
already does for a sender without permission. The default never
rejects what the web client can type: its maxlength counts UTF-16
units, which is never fewer than runes.

Docs: plugins.md and release notes. help.txt/help.json list no plugin
options (no chat.*, filetransfer.*, openinapp.* entries), so nothing
was added there.

Tests: TestCheckLength (internal/plugins/chat).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* server: limit the size of websocket frames a client may send

There was no read limit on the websocket, so a client could push frames
of any size; they were read and decoded in full before a handler (such
as the chat length check) could reject them. Frames above 1 MiB now end
the connection, as gorilla's SetReadLimit does. The largest legitimate
messages, an SDP answer and pasted clipboard text, stay far below that.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* server: video RTP timestamps follow the time between captured frames

ximagesrc gives a frame it captures late a buffer duration of only the
time left until the next frame slot ("Frame duration is from now until
the next expected capture time"), and frames dropped before the encoder
leave gaps. pion advances the RTP clock by Sample.Duration, so whenever
the encoder falls behind, the stream's clock runs slower than real
time. Browsers grow their jitter buffer to make up for it and lip sync
drifts. This happens with any queue in front of the encoder.

Each video sample's duration is now the gap since the previous sample's
PTS. The gap is known only when the next frame arrives, so it is
applied one frame late; the clock itself stays right. The sink also
counts frames in neko_capture_streamsink_frames: a rate below the
configured fps means the encoder falls behind.

Measured on the firefox image built with ./build, 1080p25 VP8, the
container limited to 0.5 CPU: RTP clock 0.2-0.9x real time before,
1.00x after; browser video jitter buffer 0.24-1.9 s before, 60-220 ms
after; audio up to 0.4 s (default queue) or 0.74 s (one-frame leaky
queue) ahead of the video before, within -70..+150 ms after.

Tests: TestSampleDuration; go test -race ./internal/capture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:09:43 +02:00
2024-09-06 23:21:57 +02:00
2026-08-03 13:55:42 +02:00
2026-04-08 14:59:31 +02:00
2021-02-21 00:40:52 +01:00
2025-03-29 00:54:46 +01:00
2026-04-08 14:59:31 +02:00
2024-09-06 23:53:06 +02:00
2021-02-21 00:40:52 +01:00
2025-04-21 16:03:51 +02:00
2020-01-13 08:05:38 +00:00

n.eko

Welcome to Neko, a self-hosted virtual browser that runs in Docker and uses WebRTC technology. Neko is a powerful tool that allows you to run a fully-functional browser in a virtual environment, giving you the ability to access the internet securely and privately from anywhere. With Neko, you can browse the web, run applications, and perform other tasks just as you would on a regular browser, all within a secure and isolated environment. Whether you are a developer looking to test web applications, a privacy-conscious user seeking a secure browsing experience, or simply someone who wants to take advantage of the convenience and flexibility of a virtual browser, Neko is the perfect solution.

In addition to its security and privacy features, Neko offers the ability for multiple users to access it simultaneously. This makes it an ideal solution for teams or organizations that need to share access to a browser, as well as for individuals who want to use multiple devices to access the same virtual environment. With Neko, you can easily and securely share access to a browser with others, without having to worry about maintaining separate configurations or settings. Whether you need to collaborate on a project, access shared resources, or simply want to share access to a browser with friends or family, Neko makes it easy to do so.

Neko is also a great tool for hosting watch parties and interactive presentations. With its virtual browser capabilities, Neko allows you to host watch parties and presentations that are accessible from anywhere, without the need for in-person gatherings. This makes it easy to stay connected with friends and colleagues, even when you are unable to meet in person. With Neko, you can easily host a watch party or give an interactive presentation, whether it's for leisure or work. Simply invite your guests to join the virtual environment, and you can share the screen and interact with them in real-time.

About

This app uses WebRTC to stream a desktop inside of a docker container, original author made this because rabb.it went under and his internet could not handle streaming and discord kept crashing when his friend attempted to. He just wanted to watch anime with his friends ლ(ಠ益ಠლ) so he started digging throughout the internet and found a few kinda clones, but none of them had the virtual browser, then he found Turtus and he was able to figure out the rest.

Then I found this project and started to dig into it. I really liked the idea of having collaborative browser browsing together with multiple people, so I created a fork. Initially, I wanted to merge my changes to the upstream repository, but the original author did not have time for this project anymore and it got eventually archived.

Use-cases and comparison

Neko started as a virtual browser that is streamed using WebRTC to multiple users.

  • It is not only limited to a browser; it can run anything that runs on linux (e.g. VLC). Browser only happens to be the most popular and widely used use-case.
  • In fact, it is not limited to a single program either; you can install a full desktop environment (e.g. XFCE, KDE).
  • Speaking of limits, it does not need to run in a container; you could install neko on your host, connect to your X server and control your whole VM.
  • Theoretically it is not limited to only X server, anything that can be controlled and scraped periodically for images could be used instead.
    • Like implementing RDP or VNC protocol, where neko would only act as WebRTC relay server. This is currently only future.

Primary use case is connecting with multiple people, leveraging real time synchronization and interactivity:

  • Watch party - watching video content together with multiple people and reacting to it (chat, emotes) - open source alternative to giggl.app or hyperbeam.
  • Interactive presentation - not only screen sharing, but others can control the screen.
  • Collaborative tool - brainstorming ideas, cobrowsing, code debugging together.
  • Support/Teaching - interactively guiding people in controlled environment.
  • Embed anything - embed virtual browser in your web app - open source alternative to hyperbeam API.
    • open any third-party website or application, synchronize audio and video flawlessly among multiple participants.
    • request rooms using API with neko-rooms.
  • Neko inside VR Chat - watch remote browser together with friends in VR.

Other use cases that benefit from single-user:

  • Personal workspace - streaming containerized apps and desktops to end-users - similar to kasm.
  • Persistent browser - own browser with persistent cookies available anywhere - similar to mightyapp.
    • no state is left on the host browser after terminating the connection.
    • sensitive data like cookies are not transferred - only video is shared.
  • Throwaway browser - a better solution for planning secret parties and buying birthday gifts off the internet.
    • use Tor Browser and VPN for additional anonymity.
    • mitigates risk of OS fingerprinting and browser vulnerabilities by running in container.
  • Session broadcasting - broadcast room content using RTMP (to e.g. twitch or youtube...).
  • Session recording - broadcast RTMP can be saved to a file using e.g. nginx-rtmp
    • have clean environment when recording tutorials.
    • no need to hide bookmarks or use incognito mode.
  • Jump host - access your internal applications securely without the need for VPN.
  • Automated browser - you can install playwright or puppeteer and automate tasks while being able to actively intercept them.

Compared to clientless remote desktop gateway (e.g. Apache Guacamole or websockify with noVNC), installed with remote desktop server along with desired program (e.g. linuxserver/firefox) provides neko additionally:

  • Smooth video because it uses WebRTC and not images sent over WebSockets.
  • Built in audio support, what is not part of Apache Guacamole or noVNC.
  • Multi-participant control, what is not natively supported by Apache Guacamole or noVNC.

Supported browsers

Other applications

Why neko?

I like cats 🐱 (Neko is the Japanese word for cat), I'm a weeb/nerd.

But why the cat butt? Because cats are assholes, but you love them anyways.

Multiple rooms

For neko room management software, visit neko-rooms.

It also offers Zero-knowledge installation (with HTTPS).

Documentation

Full documentation is available at neko.m1k1o.net. Key sections include:

How to Contribute

Contributions are welcome! Check the Contributing Guide for details.

Support

If you find Neko useful, consider supporting the project via GitHub Sponsors.

Languages
Go 35.7%
Shell 20.3%
TypeScript 19.6%
MDX 10.1%
JavaScript 4.7%
Other 9.5%