Resin compiles recurring coding-agent work into qualified tools that use less inference, lower inference cost, and complete matching work faster.
Security and privacy are fundamental load-bearing architectural constraints for Resin. This document outlines our vulnerability disclosure process, supported versions, local threat model, privacy data boundaries, supply chain integrity, and verification guarantees.
Only the latest active minor release line receives security updates and vulnerability patches.
| Version | Status | Security gate & Release Invariants |
|---|---|---|
1.0.x |
Supported after public publication | CycloneDX 1.5 SBOM; Ed25519 signature verification; zero unapproved critical/high vulnerabilities; license policy compliance |
| Pre-1.0 | Unsupported | None |
Every published release artifact undergoes automated cryptographic signing and supply chain verification before distribution.
If you discover a security vulnerability in Resin (daemon, observer, gateway, worker runtimes, CLI, or cloud contracts), please report it privately to our security team. Do not create public GitHub issues for security vulnerabilities.
- Email:
security@resin.sh - PGP Key Fingerprint:
4A82 9D1E C5B7 2209 8E3F 9912 A3BC D4E5 F607 1829 - GitHub Private Vulnerability Reporting: Submit via GitHub Security Advisories
Please include as much detail as possible to enable rapid triage and remediation:
- Detailed description of the vulnerability and potential security impact.
- Affected components, packages, or version tags.
- Step-by-step reproduction instructions or a minimal proof-of-concept (PoC).
- Any proposed mitigations, patches, or workarounds.
- Your contact information for coordination, validation, and attribution.
- Initial Acknowledgment: Within 48 hours of report receipt.
- Triage & Assessment: Within 5 business days, the security team will reproduce the issue and determine CVSS v3.1 / v4.0 severity.
- Patch Development & Release Targets:
- Critical (CVSS 9.0 – 10.0): Remediated within 14 calendar days.
- High (CVSS 7.0 – 8.9): Remediated within 30 calendar days.
- Medium (CVSS 4.0 – 6.9): Remediated within 60 calendar days.
- Low (CVSS 0.1 – 3.9): Addressed in next scheduled minor/patch release.
- Coordinated Disclosure: We adhere to coordinated vulnerability disclosure. We request a standard 90-day embargo period from initial receipt to develop, test, and distribute fixes before public disclosure.
Resin is designed with a strict local-first architecture where the local developer machine remains the authoritative boundary of execution and data ownership.
┌───────────────────────────────────────────────────────────────────────────┐
│ HOST MACHINE │
│ │
│ ┌─────────────────────────┐ session files (read locally) │
│ │ AI Coding Harness │ ───────────────────────────────────────────┐ │
│ │ (Claude / Codex / OMP) │ │ │
│ └─────────────────────────┘ │ │
│ │ (MCP tool calls over stdio) ▼ │
│ ▼ ┌─────────┐ │
│ ┌─────────────────────────┐ Unix socket / named pipe │ Observer│ │
│ │ Gateway Process │ ───────────────────────────────► │ Daemon │ │
│ └─────────────────────────┘ └─────────┘ │
│ │ │
│ ├─► Deno worker (generated tool code; Deno permission flags)│
│ ├─► Deno + Pyodide (derivation steps; read-only assets) │
│ └─► recorded commands (published tools; run directly) │
│ │
│ ┌─────────────────────────┐ │
│ │ Local SQLite / Vault DB │ │
│ └─────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────┘
│
│ Network Boundary (HTTPS)
│ Redacted, allowlisted payloads only
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ REMOTE CLOUD SERVICES │
│ │
│ - Redacted evidence events and validation decisions │
│ - Tool artifacts and signed tool certificates │
│ - Account and workspace identity │
└───────────────────────────────────────────────────────────────────────────┘
- Worker Isolation (ADR 0002):
- Generated tool code runs in a Deno child process started as the same OS user, with network, environment, subprocess and FFI access denied, reads limited to its bundle, import map and a scratch directory, and writes limited to that scratch directory. Its JavaScript heap is capped (128 MB by default) and it is stopped after a wall-clock timeout (30 s by default). There is no CPU quota.
- Derivation steps run in a separate Deno process with Pyodide; see Derivation steps.
- Capability envelopes (ADR 0007) are declarations in a tool's manifest, which arrives from the cloud with the tool; they are not an independent policy. Generated tool code gets only the permissions its manifest declares, and a recorded-workflow tool that runs programs on the host is refused unless its manifest declares command execution. No separate workspace policy is evaluated, and the envelope does not isolate processes. Invoking a published tool runs its recorded commands directly, by design; the calling harness's own permission policy governs that tool call, as for any MCP tool, and Resin adds no approval or consent step of its own.
- Local Authority & Fail-Closed Enforcement:
- The local Gateway and Runtime are authoritative. Cloud-sent workflow validation executes nothing recorded (see Workflow Validation); the only cloud-authored code it runs is sandboxed derivation steps.
- A downloaded tool artifact is activated only if its bytes match the SHA-256 digest in the catalog, which is fetched over HTTPS; a mismatch rejects the tool. The gateway also checks each tool version's signed certificate (see Tool Certificates); that check is currently report-only.
- Local IPC:
- The gateway talks to the observer daemon over a Unix domain socket (named pipe on Windows). On POSIX the socket is created in a directory with mode
0700and set to mode0600, so only the owning user can connect; there is no additional authentication. Workers exchange messages with the gateway over their stdio pipes. - IPC frames are length-framed JSON typed by
@resin/protocol.
- The gateway talks to the observer daemon over a Unix domain socket (named pipe on Windows). On POSIX the socket is created in a directory with mode
Resin enforces a fail-closed privacy boundary: raw session data stays on the device, and only redacted, allowlisted evidence is uploaded.
In Resin V1, raw interactive coding-agent session data NEVER leaves the local developer machine and is NEVER transmitted to Resin Cloud or any remote server.
Specifically, the following data types are strictly prohibited from cloud egress and remain strictly on the local host:
- Raw Conversation Transcripts & Prompts: Full agent-user interaction history, interactive prompt text, thought traces, and model inputs.
- Raw Model Outputs: Direct completions, raw generation tokens, and untruncated model responses.
- Local Source Code & File Contents: Project repository files, edited buffers, local patches and diffs. (Secret-scrubbed views of short recorded programs are the exception below.)
- Abstract Syntax Trees & Symbols: Private codebase AST representations, symbol tables, and semantic index structures.
- Full File Paths: Absolute paths and home-directory names. Path patterns (at most the last four segments, home directory removed) and command profiles that name files and directories are uploaded.
- Secrets & Credentials: Environment variables, private keys, authentication tokens, API credentials, and connection strings.
Engine-redacted evidence is not raw session data: secret-scrubbed recorded-program views and native command lines, which can name files and directories, are uploaded as learned-tool evidence. The per-event allowlist is in docs/security/privacy-inventory.md.
All local session logs, trajectory databases, and cached tool artifacts reside solely on the local filesystem (~/.resin/ or workspace-local storage) under local user permissions.
When cloud connectivity is configured, what crosses the network boundary is defined per event in docs/security/privacy-inventory.md and summarized for users in docs/user/what-leaves-your-machine.md:
| Data Category | Data Elements | Transport |
|---|---|---|
| Evidence events | Tool names, success/error flags, durations, output sizes, token counts, command profiles, path patterns, secret-scrubbed command lines and recorded-program views, opaque private references, harness call ids | Outbound HTTPS |
| Validation decisions | Step ids, verdicts, fixed reason strings, { kind: "recording", planDigest } |
Outbound HTTPS |
| Tools & activation | Tool artifacts, signed tool certificates, active-tool lists | Inbound HTTPS |
| Account & workspace | Sign-in identity, workspace and project identifiers | Bidirectional HTTPS |
Every observation batch is checked before it is sent: payloads containing prohibited raw fields (transcripts, prompts, source, outputs and similar) or matching secret patterns in their serialized form are rejected with an error and not transmitted.
The local Resin installation does not trust remote cloud endpoints as an execution authority:
- Limited Remote Code: Cloud services cannot directly instruct the local runtime to run scripts or recorded commands, alter capability envelopes, or disable security gates. Validation asks are answered from local recordings without running recorded programs or dispatching tool calls. Model-written derivation steps do run on the device, at validation and at invocation, but only inside the Deno + Pyodide sandbox described below. Invoking a published tool runs its recorded commands directly, by design; the calling harness's own permission policy governs that tool call, as for any MCP tool, and Resin adds no approval or consent step of its own.
- What a published tool runs comes from the cloud: a tool's recorded commands and manifest are delivered by the cloud, so whoever can publish tools to your workspace, including the cloud itself if it were compromised, decides what that tool runs when your agent invokes it. Tool certificates are the control being introduced to bound this.
- Integrity of downloaded tools: an artifact whose bytes do not match the catalog's SHA-256 digest is rejected and the tool is not activated.
Each published tool version carries a certificate the Resin cloud signs with an Ed25519 key that cannot be exported and that only the cloud's publishing service may use. The certificate binds the account and workspace, the tool's id, name and version, and the digests of its manifest and artifact. The gateway checks it against public keys pinned in the Resin CLI for each Resin cloud (keys are never taken from the cloud, the workspace or environment variables), against the device's own account and workspace, and against the digest of the bytes it downloaded.
This check is report-only today: resin status and resin doctor show how many tools verified, were missing a certificate, or failed, but a missing or failed certificate does not yet block a tool. Enforcement will follow once certificate issuance is confirmed across workspaces. A certificate shows that the Resin cloud published that exact tool version to your workspace; it does not attest that the tool is safe.
The cloud sends validation asks; the gateway polls, decides and submits without user interaction. Validation executes nothing recorded. For every recorded step (shell/process, program, tool-protocol, harness tool, composed invoke) it resolves the step's call exactly as an invocation would and compares it with the call this device recorded for that step: same callable (name, connection, program kind/argument) and every argument equal to the recorded value, with program templates compared after resolving the private original. A match lets the recorded output answer the step; a mismatch or missing recorded call means the plan is not verified. No recorded program is spawned, no tool call is dispatched, and no project is copied.
- Local call identity: Every recorded value compared or returned is read from the local private store under a reference the device recomputes from a session its own harness adapters discovered and a call id from the plan (
callId, orheldOut.callsfor held-out repeats); the entry must be owned by this workspace. References and literals carried in a plan are never trusted as the recording. Calls that cannot be identified locally yield "unavailable", never verified. - Hidden dependencies: A step that still carries, as literal recorded text, a value the recording shows flowing from an earlier step's output is not verified until the plan binds that position. Incidental matches fail closed.
- Decisions:
verification.replay = { kind: "recording", planDigest }, with only step ids, verdicts and fixed reason strings — never recorded values, commands or outputs. - Invocation: Invoking a published tool runs its recorded commands directly, by design; the calling harness's own permission policy governs that tool call, as for any MCP tool, and Resin adds no approval or consent step of its own.
Derivation steps — short Python a cloud model writes to compute a value a recording hard-coded — are the only plan code no local recording produced, and are never trusted. At validation and at tool invocation alike they run as Python in Pyodide (CPython compiled to WebAssembly) inside a Deno process whose only permission is read access to Resin's pinned local Pyodide assets; network, environment, subprocesses, FFI, system information, file writes, and remote or npm imports are denied, and no other file can be read. A derivation therefore sees only its inputs, written into its source: it cannot read the project, the home directory, or any secret on the device, even through Pyodide's JavaScript bridge. It may import only a fixed allowlist of pure standard-library modules; that allowlist is a guard against mistakes, not a security boundary, because Python code inside the interpreter can reach the original import machinery (for example through __import__.__closure__). Likewise, exhausting WebAssembly memory raises a MemoryError the derivation can catch. The real bounds are the Deno permissions above and the wall-clock timeout, which kills the process whatever the Python code does. Its result is the JSON object of its final expression, and it is bounded in output size, wall-clock time (the process is killed) and memory (V8 heap and 2 GiB WebAssembly limits). The Pyodide release (314.0.7) is pinned by version, lockfile integrity and per-asset SHA-256, ships inside the Resin package, and is never downloaded at run time. The verified assets and the Deno driver are copied into a private (0700) per-process directory, those copies are re-verified before every run, and Deno may read only that directory. If Deno (the installer's ~/.resin/current/deno, RESIN_DENO_EXECUTABLE, or PATH) or the pinned assets are missing or altered, the derivation step fails closed.
Public release artifacts are distributed with cryptographic integrity proofs that require zero access to private cloud infrastructure:
- Cryptographic Ed25519 Signing:
- Public distribution packages (binaries, npm bootstrap packages, release tarballs, installation helper scripts) are deterministically packaged and signed via Ed25519 private keys in protected CI release workflows (
scripts/package-release.mjs).
- Public distribution packages (binaries, npm bootstrap packages, release tarballs, installation helper scripts) are deterministically packaged and signed via Ed25519 private keys in protected CI release workflows (
- Offline & Self-Contained Verification:
- Verification is entirely offline. The verifier (
scripts/verify-release.mjsorresin verify) computes SHA-256 digests and verifies Ed25519 signatures against embedded trusted public keys. - Zero Cloud Topology Exposure: Verification operates purely on static public assets and embeds no private cloud endpoints, internal VPC references, API gateways, or proprietary serverless cloud topology.
- Verification is entirely offline. The verifier (
- Software Bill of Materials (SBOM):
- Every release ships with a CycloneDX 1.5 SBOM (
sbom.json) documenting full dependency provenance and license metadata.
- Every release ships with a CycloneDX 1.5 SBOM (
- Zero Unapproved Critical/High Findings:
- Automated release gates block publication if unapproved critical or high vulnerabilities exist in the dependency tree.
The Resin repository implements defense-in-depth for all continuous integration workflows:
- Untrusted PR Isolation: Pull request workflows triggered from external forks execute exclusively in unprivileged GitHub-hosted runner environments with zero access to internal secrets, production cloud credentials, or release signing keys. The repository registers no self-hosted runners, so a fork cannot redirect a job onto project infrastructure; tests and
actionlintreject any self-hosted label. - Ephemeral Release Runners: Release-candidate signing, channel renewal and production promotion run on fresh GitHub-hosted
ubuntu-24.04VMs, behind protected GitHub environments. Nothing persists between release jobs or is shared with other builds. - Protected Workflow Separation: Release and deployment workflows execute exclusively on protected
mainor tag refs with explicit promotion confirmations, auditable workflow dispatch, and offline verification receipts. - Optional Human Review: Human reviews are optional and are not automatically requested through code ownership rules; pull requests enforce PR-only release gates with zero required approving reviews while requiring 100% automated machine qualification.
- Branch Protection & Automated Gating: Direct pushes and force pushes are blocked on
main. Merging requiresCI Gate Rollup, which verifies that static checks, every unit-test shard and sandbox tests passed on the exact commit. Static checks include repository boundaries, secret scanning and ADR validation.
We consider good-faith security research conducted in accordance with this policy to be authorized. We will not pursue legal action against researchers who:
- Make a good-faith effort to avoid privacy violations, data destruction, and service interruption.
- Report vulnerabilities through authorized private channels without public disclosure prior to mutual agreement.
- Do not exploit identified vulnerabilities beyond what is strictly necessary to demonstrate proof-of-concept.