daltoniam/Starscream
Websockets in swift for iOS and OSX
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓41+ active contributors
- ✓Distributed ownership (top contributor 38% of recent commits)
- ✓Apache-2.0 licensed
Show 3 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Stale — last commit 2y ago
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/daltoniam/starscream)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/daltoniam/starscream on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: daltoniam/Starscream
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/daltoniam/Starscream shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 41+ active contributors
- Distributed ownership (top contributor 38% of recent commits)
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 2y ago
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live daltoniam/Starscream
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/daltoniam/Starscream.
What it runs against: a local clone of daltoniam/Starscream — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in daltoniam/Starscream | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 753 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of daltoniam/Starscream. If you don't
# have one yet, run these first:
#
# git clone https://github.com/daltoniam/Starscream.git
# cd Starscream
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of daltoniam/Starscream and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "daltoniam/Starscream(\\.git)?\\b" \\
&& ok "origin remote is daltoniam/Starscream" \\
|| miss "origin remote is not daltoniam/Starscream (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "Sources/Starscream/WebSocket.swift" \\
&& ok "Sources/Starscream/WebSocket.swift" \\
|| miss "missing critical file: Sources/Starscream/WebSocket.swift"
test -f "Sources/Engine/WSEngine.swift" \\
&& ok "Sources/Engine/WSEngine.swift" \\
|| miss "missing critical file: Sources/Engine/WSEngine.swift"
test -f "Sources/Transport/FoundationTransport.swift" \\
&& ok "Sources/Transport/FoundationTransport.swift" \\
|| miss "missing critical file: Sources/Transport/FoundationTransport.swift"
test -f "Sources/Framer/Framer.swift" \\
&& ok "Sources/Framer/Framer.swift" \\
|| miss "missing critical file: Sources/Framer/Framer.swift"
test -f "Sources/Compression/WSCompression.swift" \\
&& ok "Sources/Compression/WSCompression.swift" \\
|| miss "missing critical file: Sources/Compression/WSCompression.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 753 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~723d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/daltoniam/Starscream"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Starscream is a production-grade WebSocket library for Swift that implements RFC 6455 and runs on iOS and macOS. It provides nonblocking, background-thread WebSocket communication with TLS/WSS and compression extension (RFC 7692) support, handling the full WebSocket protocol lifecycle including handshake, frame parsing, ping/pong control frames, and graceful disconnection. Single-package architecture organized by logical subsystems: Sources/Engine/ handles connection lifecycle (Engine.swift, NativeEngine.swift, WSEngine.swift), Sources/Framer/ manages WebSocket frame parsing and HTTP upgrades (Framer.swift, HTTPHandler.swift, FrameCollector.swift), Sources/Transport/ abstracts socket I/O (FoundationTransport.swift, TCPTransport.swift), Sources/Security/ handles TLS/certificate validation, Sources/Compression/ implements RFC 7692, and Sources/Starscream/WebSocket.swift is the main public API. Tests/ contains integration and fuzz tests.
👥Who it's for
iOS and macOS app developers who need to add real-time bidirectional communication to their apps (chat, notifications, live updates) without implementing WebSocket protocol details themselves. Also useful for backend Swift developers building WebSocket servers via the WebSocketServer abstraction.
🌱Maturity & risk
Production-ready and actively maintained. The repo conforms to the full Autobahn test suite (RFC 6455 compliance), includes CI/CD via GitHub Actions (see .github/workflows/release.yml), has comprehensive test coverage (Tests/ directory with CompressionTests.swift and FuzzingTests.swift), and is available as a CocoaPod (Starscream.podspec) and SPM package (Package.swift). The library is stable with a mature feature set.
Low risk for a mature library. Primary risk is single-maintainer dependency (daltoniam); however, the repo has no external build dependencies beyond Foundation/native Swift, minimizing supply chain risk. The codebase is self-contained with only internal modules (Compression, Engine, Framer, Transport, Security, Server). Swift version compatibility and OS version requirements should be verified in Package.swift before adopting.
Active areas of work
Based on file structure, the repo is in maintenance mode with active release automation (.github/workflows/release.yml). Recent work likely focused on stability and test coverage (FuzzingTests.swift present). CHANGELOG.md should be checked for recent version highlights. No specific PRs or milestones are visible in the provided data, but the presence of RFC 7692 compression support and server-side WebSocketServer.swift indicates ongoing feature completeness.
🚀Get running
git clone https://github.com/daltoniam/Starscream.git
cd Starscream
# For SPM:
swift build
# For CocoaPods:
pod install
# For Xcode project:
open Starscream.xcodeproj
Daily commands:
# Build the library
swift build
# Run tests
swift test
# Or in Xcode:
xcodebuild -scheme Starscream -configuration Debug
🗺️Map of the codebase
Sources/Starscream/WebSocket.swift— Main public API entry point for WebSocket connections; every consumer interacts through this class.Sources/Engine/WSEngine.swift— Core WebSocket protocol implementation handling frame parsing, masking, and RFC 6455 compliance.Sources/Transport/FoundationTransport.swift— Bridge to native URLSessionWebSocketTask; handles low-level socket I/O and connection lifecycle.Sources/Framer/Framer.swift— WebSocket frame serialization/deserialization logic; critical for RFC 6455 frame format correctness.Sources/Compression/WSCompression.swift— RFC 7692 compression extension implementation; required for permessage-deflate support.Sources/Security/Security.swift— TLS/WSS certificate validation and pinning abstractions; foundation for secure connections.
🧩Components & responsibilities
- WebSocket (Public API) (Swift, URLRequest) — Holds request, delegate, and engine. Routes lifecycle events and user send() calls to engine.
- Failure mode: If delegate is nil, crash on didConnect; if request is malformed URL, initialization fails.
- WSEngine (Protocol Implementation) — Manages HTTP upgrade, frame codec, state
🛠️How to make changes
Add a custom WebSocket subprotocol or header
- Create a URLRequest with custom headers before passing to WebSocket (
Sources/Starscream/WebSocket.swift) - WebSocket accepts request in initializer and forwards to engine via HTTPHandler (
Sources/Framer/HTTPHandler.swift) - HTTPHandler encodes custom headers in HTTP upgrade handshake (
Sources/Framer/FoundationHTTPHandler.swift)
Implement compression extension support
- Enable permessage-deflate in WebSocket request headers (
Sources/Starscream/WebSocket.swift) - WSEngine parses Sec-WebSocket-Extensions response header (
Sources/Engine/WSEngine.swift) - Create WSCompression instance and wrap send/receive in compress/decompress (
Sources/Compression/WSCompression.swift)
Add a custom transport layer (non-Foundation sockets)
- Implement Transport protocol (connect, disconnect, write, read methods) (
Sources/Transport/Transport.swift) - Inject custom transport into WSEngine initialization (
Sources/Engine/WSEngine.swift) - WSEngine agnostically dispatches I/O through transport.write() and transport.read() (
Sources/Engine/WSEngine.swift)
Add custom TLS certificate validation (pinning)
- Implement Security protocol with pinnedCertificates or custom validator (
Sources/Security/Security.swift) - Pass custom Security instance to WebSocket or WSEngine (
Sources/Starscream/WebSocket.swift) - FoundationSecurity (or custom impl) validates against pinned certs before connection (
Sources/Security/FoundationSecurity.swift)
🔧Why these technologies
- Swift (Foundation frameworks: URLSession, Network, CommonCrypto) — Native iOS/macOS support with zero dependencies; leverages URLSessionWebSocketTask for modern API and automatic reconnection.
- GCD (Grand Central Dispatch) — Nonblocking async I/O on background threads; prevents main-thread blocking during socket operations.
- zlib compression (Compression framework) — RFC 7692 permessage-deflate reduces bandwidth on high-volume message streams.
- RFC 6455 WebSocket Protocol — Industry standard for bidirectional communication; enables compatibility with any RFC-compliant server.
⚖️Trade-offs already made
-
Dual engine architecture (WSEngine + NativeEngine) for macOS 10.15+
- Why: NativeEngine delegates to URLSessionWebSocketTask (simpler, native) on newer OS; WSEngine provides manual frame handling for lower OS versions and edge cases.
- Consequence: Code branching increases maintenance; WSEngine and NativeEngine may diverge in behavior over time.
-
Automatic masking for client frames (RFC 6455 required)
- Why: Security requirement; prevents cache-poisoning attacks on transparent proxies.
- Consequence: 5–10% CPU and bandwidth overhead for every outbound message; unavoidable per spec.
-
Optional compression instead of mandatory
- Why: Not all servers support RFC 7692; default behavior ensures compatibility.
- Consequence: Apps must explicitly negotiate compression to realize bandwidth savings.
-
Blocking I/O on Transport abstractions; async delegation via closures/delegates
- Why: Simplifies frame assembly logic; GCD serializes I/O naturally.
- Consequence: Transport.read() blocks its dispatch queue; if read buffer is slow, message latency increases.
🚫Non-goals (don't propose these)
- Does not implement HTTP/2 server push or SPDY.
- Does not provide built-in reconnection policy (consumers must implement retry logic via delegate).
- Does not handle authentication beyond standard HTTP headers (no OAuth2, SASL, etc.).
- Not designed for ultra-low-latency or hard-realtime constraints (<10ms).
- Does not support WebSocket subprotocol negotiation beyond header forwarding (consumer interprets via custom logic).
🪤Traps & gotchas
- WebSocket must be retained as a property (see README example
var socket: WebSocket) or it will be deallocated immediately, killing the connection. 2. Delegate callbacks (didReceive) execute on background GCD queues—all UI updates must dispatch to main thread explicitly. 3. HTTP header case sensitivity: some servers expect exact casing in upgrade headers; verify in FoundationHTTPHandler.swift. 4. Compression negotiation is opt-in; clients must explicitly request permessage-deflate extension via request headers. 5. macOS requires entitlements for outbound network connections in sandboxed apps.
🏗️Architecture
💡Concepts to learn
- WebSocket Framing (RFC 6455) — Starscream's core responsibility is correctly parsing and generating WebSocket frames with proper opcode handling, payload masking, and fragmentation; misunderstanding frame format breaks protocol compliance
- Permessage-Deflate Compression (RFC 7692) — This repo implements compression negotiation and per-message compression; understanding the extension handshake and sliding window decompression is key to the Compression module
- HTTP Upgrade Mechanism — WebSocket connection starts with an HTTP GET upgrade request; Starscream's Framer module handles header validation, Sec-WebSocket-Key hashing, and 101 Switching Protocols response parsing
- Masking Key XOR Operation — Client-to-server frames must be XOR-masked with a 4-byte key; Starscream implements this in Data+Extensions.swift and Framer.swift, and it's critical for security and protocol compliance
- Grand Central Dispatch (GCD) for Async I/O — Starscream uses GCD queues and DispatchSourceRead to handle socket reads nonblockingly without threads; understanding dispatch sources is essential for modifying the Engine or Transport layers
- TLS/SSL Certificate Pinning — For WSS (WebSocket Secure), Starscream's Security module validates certificates; understanding URLSessionDelegate's didReceive challenge is needed for custom pinning implementations
- Heartbeat / Keep-Alive with Ping/Pong Frames — WebSocket ping/pong control frames (opcodes 0x9 and 0xA) are used to detect stale connections; Starscream automatically responds to pings and allows manual ping writes for keep-alive logic
🔗Related repos
vapor/websocket— Server-side WebSocket implementation for Vapor framework; complementary for building full-stack Swift WebSocket appsapple/swift-nio— Low-level async networking library that could be used as an alternative transport backend instead of Foundation URLSessionrealm/realm-swift— Real-time sync framework that often pairs with Starscream for bidirectional data synchronization over WebSocketkishikawakatsumi/KeychainAccess— Often used alongside Starscream's TLS/certificate pinning for secure credential storage in iOS appscrossbar-examples/autobahn-testsuite— Reference test suite Starscream conforms to—canonical source for RFC 6455 conformance validation
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for Sources/Framer/HTTPHandler.swift and Sources/Framer/StringHTTPHandler.swift
The Framer module is critical for HTTP handshake parsing in WebSocket connections, but Tests/StarscreamTests/StarscreamTests.swift doesn't contain dedicated tests for HTTP handler edge cases (malformed headers, missing headers, chunked encoding, etc.). This directly impacts RFC 6455 compliance and security.
- [ ] Create Tests/FramerTests.swift with test cases for FoundationHTTPHandler and StringHTTPHandler
- [ ] Test valid HTTP 101 Upgrade responses with various header combinations
- [ ] Test rejection of invalid responses (missing Upgrade header, wrong status codes)
- [ ] Test edge cases: empty headers, case-insensitive header matching, whitespace handling
- [ ] Add tests for potential header injection vulnerabilities
Add GitHub Actions workflow for running Autobahn test suite against Sources/Server/WebSocketServer.swift
The README explicitly states 'Conforms to all of the base Autobahn test suite', but there's no CI workflow in .github/workflows/ that validates this claim. Currently only release.yml exists. The examples/AutobahnTest exists but isn't automated, making regressions undetectable.
- [ ] Create .github/workflows/autobahn-tests.yml workflow file
- [ ] Configure the workflow to start WebSocketServer and run Autobahn test suite against it
- [ ] Add test result parsing and failure reporting
- [ ] Run on pull requests to catch regressions in Sources/Engine/, Sources/Framer/, and Sources/Compression/
- [ ] Document results in PR comments
Add unit tests for Sources/Compression/Compression.swift permessage-deflate implementation
RFC 7692 compression support is a feature, but Tests/CompressionTests.swift exists with minimal coverage. The Compression.swift module handles critical data transformation (compression/decompression negotiation and execution). Missing tests for edge cases could cause silent data corruption.
- [ ] Expand Tests/CompressionTests.swift with tests for compression parameter negotiation (server_no_context_takeover, client_no_context_takeover)
- [ ] Add tests for compression ratio edge cases (uncompressible data, very small payloads)
- [ ] Test decompression of multi-frame messages with context continuation
- [ ] Test compression with various message sizes (0 bytes, max frame size, multiple frames)
- [ ] Add tests for invalid compression headers and negotiation failures
🌿Good first issues
- Add unit tests for Sources/DataBytes/Data+Extensions.swift to cover bit-level masking operations used in frame encoding—currently no dedicated test file exists for this critical utility.
- Document the compression extension API with example code in README showing how to enable and verify RFC 7692 negotiation, as README only covers basic text/binary writes.
- Implement timeout handling in Sources/Engine/WSEngine.swift for initial handshake (add configurable connectTimeout property) and expose it in public WebSocket API, as some users report hanging connections.
⭐Top contributors
Click to expand
Top contributors
- @daltoniam — 38 commits
- @acmacalister — 10 commits
- @dependabot[bot] — 6 commits
- @fassko — 4 commits
- @mininny — 2 commits
📝Recent commits
Click to expand
Recent commits
c6bfd1a— chore: update release tooling (acmacalister)82d8a01— fix: update build setting to recommended (acmacalister)11c401f— fix: crash as NWEndpoint requires a min target of 12.0 (#998) (dylancom)b32c9ab— Add privacy manifest (#1008) (jonathanellis)b12442f— chore: Update install instructions (#984) (JarnoRFB)d3a0b10— Bump activesupport from 7.0.7 to 7.0.7.2 (#976) (dependabot[bot])7723d1e— Update README.md (acmacalister)ac6c0fc— fix: update README (acmacalister)ca9b122— Update SwiftPM section in Readme (#824) (wacumov)86998dd— Fix connection race when using WSEngine (#930) (yoheimuta)
🔒Security observations
- High · Potential TLS/SSL Certificate Validation Bypass —
Sources/Security/FoundationSecurity.swift, Sources/Security/Security.swift. WebSocket library implementing TLS/WSS support may have insufficient certificate validation. Without explicit review of the FoundationSecurity.swift and Security.swift files, there's risk of accepting invalid or self-signed certificates in production, making the connection vulnerable to MITM attacks. Fix: Review and enforce strict certificate pinning and validation. Ensure URLSessionDelegate properly validates server certificates and rejects invalid/self-signed certificates in production environments. Implement certificate pinning for critical connections. - High · No Visible Input Validation in Frame Processing —
Sources/Framer/FrameCollector.swift, Sources/Framer/Framer.swift. The Framer module (Sources/Framer/) processes incoming WebSocket frames. Without visible input sanitization, malformed or oversized frames could lead to buffer overflows, DoS attacks, or unexpected behavior. The FrameCollector.swift especially needs to validate frame sizes and content. Fix: Implement strict input validation for all incoming frames including: maximum frame size limits, payload length verification, proper handling of control frames, and graceful rejection of malformed data. Add rate limiting for frame processing. - Medium · Compression Extension Security Considerations —
Sources/Compression/WSCompression.swift, Sources/Compression/Compression.swift. RFC 7692 compression extensions (Sources/Compression/) may be vulnerable to compression-based attacks (e.g., CRIME attack variants). The implementation should validate that compression doesn't introduce security risks through side-channel attacks or data leakage. Fix: Review compression implementation for timing attacks and data leakage. Consider disabling compression by default for sensitive data. Implement proper context isolation between connections. Document compression security trade-offs in API documentation. - Medium · Missing Security Headers and Protocol Validation —
Sources/Framer/FoundationHTTPHandler.swift, Sources/Framer/HTTPHandler.swift. HTTP upgrade headers (Sources/Framer/HTTPHandler.swift, Sources/Framer/FoundationHTTPHandler.swift) may not properly validate all required WebSocket headers (Sec-WebSocket-Key, Sec-WebSocket-Accept). Missing validation could allow protocol smuggling or header injection attacks. Fix: Implement comprehensive validation of all WebSocket upgrade headers per RFC 6455. Validate Sec-WebSocket-Key format and Sec-WebSocket-Accept computation. Reject connections with missing or invalid headers. Add strict header parsing to prevent injection attacks. - Medium · Potential Memory Issues with Large Data Handling —
Sources/Transport/FoundationTransport.swift, Sources/Transport/TCPTransport.swift. WebSocket can handle streaming data and potentially large payloads. Without visible size limits or streaming handlers (Sources/Transport/), the application may be vulnerable to memory exhaustion DoS attacks when receiving large messages. Fix: Implement configurable maximum message size limits. Use streaming/chunked processing for large payloads instead of buffering entire messages. Add memory monitoring and connection termination for excessive resource consumption. - Medium · Server-Side Security Not Clearly Documented —
Sources/Server/WebSocketServer.swift, Sources/Server/Server.swift. The WebSocketServer and Server components (Sources/Server/) may have security implications when used to build WebSocket servers. Without clear security documentation, developers may implement insecure server configurations. Fix: Document security best practices for server implementations. Provide secure defaults for authentication, authorization, and rate limiting. Include examples of secure server configuration. Validate all client connections and messages. - Low · Test Coverage for Fuzzing Incomplete —
Tests/FuzzingTests.swift. FuzzingTests.swift exists but without access to its contents, it's unclear if fuzzing covers all edge cases, malformed frames, and protocol violations comprehensively. Fix: Expand fuzzing test coverage to include: malformed frames, oversized payloads, invalid control sequences, incomplete handshakes, and protocol violations. Consider integrating continuous fuzzing via OSS-Fuzz. - Low · No Visible Rate Limiting Implementation —
undefined. The codebase shows no obvious rate limiting mechanisms for WebSocket connections, making it potentially vulnerable to abuse and DoS attacks. Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.