Skip to content

Security: YawLabs/oam

SECURITY.md

Security policy

Reporting a vulnerability

Report privately through GitHub's private vulnerability reporting on this repository: the Security tab, then Report a vulnerability. That channel is private to the maintainers and is the one to use — do not open a public issue for anything exploitable.

Include what you need to make it reproducible: the oam version (oam --version), the platform, and a minimal script. If you have a working proof of concept, send it — it shortens triage more than a description does.

You will get an acknowledgement within 3 working days. We aim to ship a fix or give you a dated plan within 30 days, and we will tell you before the fix goes public so the disclosure is not a surprise. If you want credit in the release notes, say so; if you want to stay anonymous, that is the default.

What counts as a vulnerability

oam runs untrusted-ish JavaScript on a V8 isolate with a Node-compatible surface. In scope:

  • Escaping the permission model (see below) — reading, writing, or dialling out when the corresponding permission is denied.
  • Memory-safety failures reachable from JavaScript: a crash in the Rust or V8 layer that a script can trigger, and anything that looks like a read/write past a buffer.
  • Module-resolution attacks: a specifier that loads a file outside the intended tree, lockfile handling that fetches something other than what was pinned.
  • Anything in the release pipeline that would let a third party ship a binary users would accept as ours.

Not in scope:

  • A script doing something destructive when run without --permission. That is the documented default: oam without the permission flag has the same authority as node, i.e. full access to the user's machine.
  • Denial of service by a script that is simply allowed to run — infinite loops, deliberate memory exhaustion, process.exit.
  • Node-compatibility divergences with no security consequence. Those are ordinary bugs; file them publicly.

The permission model

oam --permission denies filesystem reads, filesystem writes, network access, and environment access unless explicitly granted. The checks are enforced in the native ops (crates/oam_engine/src/permissions.rs), not in JavaScript, so monkey-patching fs does not route around them. A denial throws Node's ERR_ACCESS_DENIED, carrying permission and resource.

Two things to be clear about, because the difference matters if you are relying on this:

  • The default is no restriction. Without --permission, every check returns granted. This matches Node, and it means the flag is opt-in hardening, not a sandbox that is on by default.
  • It is a permission model, not an isolate escape boundary. It gates the host operations oam exposes. It is not a defence against a V8 renderer exploit, and it does not make it safe to run genuinely hostile code. If you need that, run oam inside an OS-level sandbox as well.

V8 and upstream security updates

oam embeds V8 via the v8 crate (currently 150.0.0; see Cargo.lock for the exact pin of any given build). V8 security fixes reach oam when we bump that crate and cut a release — we do not carry our own V8 patches.

If you are tracking a specific CVE, oam --version plus Cargo.lock from the matching tag tells you exactly which V8 you have.

Release integrity

Every release publishes a SHA256SUMS file alongside the assets. Verify your download against it:

sha256sum -c SHA256SUMS --ignore-missing

A checksum file served from the same place as the binaries protects against corruption and mirror tampering, not against someone who has compromised the release channel itself.

From v0.18.0 on, each release also carries RELEASE-MANIFEST (the tag plus the SHA256SUMS lines) and RELEASE-MANIFEST.sig, an SSH signature made with an offline-backed ed25519 release key. The signature is what proves authenticity. Check the key fingerprints against this list, which is also published in release-keys/README.md and the release notes:

Key Fingerprint
oam-release-k1 (current) SHA256:zB7Aq4Ky/U90VJ4sAEp0e2A65KfQpiyQXJI4FuT2oss
oam-release-k2 (next, offline) SHA256:Uy7nugF5mDzfM/8/fcUti9K+sQMbn/LdRAk+sIbWYs4

To verify a release by hand, see release-keys/README.md.

install.sh and install.ps1 check this for you, against copies of these keys embedded in the scripts: a v0.18.0+ release installs only if its manifest signature verifies, names the tag being installed, and comes from a key whose range covers that tag. Releases before v0.18.0 are checked against a pinned hash of their published SHA256SUMS. install/README.md has the details. oam self-update makes the same checks with the keys compiled into oam.

The binaries are code-signed too, from v0.18.0 on:

  • Windows: both .exe assets carry an Authenticode signature from Azure Artifact Signing, publisher "Yaw Labs LLC" (a verified publisher). SmartScreen reputation for a new signature still builds up over time.
  • macOS: both binaries are signed with oam's own pinned, self-signed identity, "oam Code Signing (self-signed)", with the hardened runtime. That is not an Apple Developer ID signature and the binaries are not notarized, so Gatekeeper still blocks a quarantined (browser-downloaded) binary. curl and brew installs set no quarantine flag and are unaffected.

How fixes are disclosed

oam is in beta (pre-1.0), and it is used outside Yaw Labs. A security fix is disclosed in three places, once a release carrying it is out:

  • The CHANGELOG, under that release's Security heading, states what was wrong and what changed.
  • The GitHub Release notes summarise the release's security fixes first.
  • A GitHub Security Advisory is published for each vulnerability, naming the affected versions and the release that fixes it. Where one of oam's security boundaries failed — the permission model, TLS certificate verification, TLS client authentication, or the client address a server reports — the advisory also carries a CVE ID, so scanners and vulnerability trackers see it.

Advisories describe the weakness and its impact, not how to exploit it. A reporter is told before a fix goes public (see above), and credited in the advisory and the release notes if they ask to be.

Supported versions

Fixes land on the latest release. There is no long-term-support branch — upgrade to pick up security fixes. An advisory names the first release that carries its fix; the release to run is the latest.

There aren't any published security advisories