Commit Graph

23 Commits

Author SHA1 Message Date
ig
5a290e45df ci: Node 20 + bun 1.3.14 for windows-arm64
Node 18 has no official windows-arm64 build (setup-node fails on the arm64 leg); Node 20 is Active LTS. bun 1.3.1 deterministically segfaults (0xC0000005) on win-arm64 during winsrt.test.ts setup — bump to latest stable 1.3.14. engines stays >=18.0.0. Also fixes main's latently-broken arm64 leg.
2026-05-26 23:02:56 -04:00
ig
a5c255639d feat(windows): wire SandboxManager to srt-win network sandbox
TS integration for the Windows network sandbox built in #278/#279/#280
(+ `srt-win install`/`uninstall` from 02b/02c):

- windows-sandbox-utils.ts: getSrtWinPath, getWindowsGroupStatus,
  getWindowsWfpStatus; installWindowsSandbox / uninstallWindowsSandbox
  (one self-elevating process, one UAC prompt; filter-0 PERMITs
  non-members so network is undisturbed before the post-install
  logout); deleteWindowsGroup; createWindowsGroup / createWindowsWfp
  kept as granular primitives for enterprise/CI;
  wrapCommandWithSandboxWindows (returns argv);
  checkWindowsDependencies with state-tailored install instructions.
  Exit-code contract for install: 0 ok, 10 UAC-cancelled (returned,
  not thrown), 11 group fail, 12 WFP fail, 13 different-config
  (use force).
- sandbox-config.ts: SandboxRuntimeConfig.windows {groupName, groupSid,
  wfpSublayerGuid, proxyPortRange}.
- sandbox-manager.ts: isSupportedPlatform/checkDependencies include
  windows; initialize() validates group=ready ∧ wfp=installed then
  binds the JS http/socks proxies inside the WFP-permitted port range
  (default 60080-60089) via listenInRange(); new wrapWithSandboxArgv()
  on all platforms; wrapWithSandbox() throws on Windows.
- cli.ts: argv-mode spawn ({shell:false}) on Windows; new
  `windows-install` and `windows-uninstall` subcommands.
- index.ts: export new types/functions.
- test/sandbox/winsrt.test.ts: helper round-trips, install/uninstall
  round-trip (cancelled undefined; idempotent re-run; exit-13
  different-config refusal + force), initialize() preflight,
  wrapWithSandboxArgv shape, proxy allow/block via allowedDomains,
  in/out-of-range loopback, tool-compat (git/npm), bypass-pinning
  (nslookup/ping). Uses S-1-5-32-544 as discriminator under a
  dedicated test sublayer.
- CI: Node/Bun setup now runs on Windows too; new step npm ci +
  npm run build + bun test winsrt.test.ts after smoke-exec.ps1.

Filesystem (denyRead/denyWrite) lands in PR 4-6.
2026-05-26 23:02:56 -04:00
ig
850eee21a1 feat(windows): srt-win exec — restricted token, job, hardening stack
Adds the `srt-win exec` subcommand: spawn a target process under a
deny-only-group restricted token inside a locked-down job, on a
non-interactive desktop, with process-creation mitigation policies
and an explicit handle whitelist. The broker process self-protects
its own DACL before spawning so the child cannot OpenProcess it.

  srt-win exec (--name <N> | --group-sid <S>)
               [--http-proxy <port>] [--socks-proxy <port>]
               [--skip-group-check]
               -- <target> [args...]

Token (token.rs): CreateRestrictedToken with SidsToDisable =
[<group>, BUILTIN\Administrators], LUA_TOKEN, no restricting list,
IL=Medium, all privileges deleted except SeChangeNotify. Default
DACL grants SYSTEM + the logon-session SID so siblings inside the
sandbox can still IPC. ConvertStringSidToSidW SIDs are owned via
the LocalPsid RAII wrapper (LocalFree on drop). When group_sid is
itself BUILTIN\Administrators (the CI configuration), the
SidsToDisable list is deduped.

Job (job.rs): JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE +
JOBOBJECT_BASIC_UI_RESTRICTIONS (clipboard, atoms, sysparams,
display, desktop, exitwindows, cross-job USER/GDI handles). The
Job struct owns the handle from CreateJobObjectW onward so a
failed SetInformationJobObject still closes it.

Window station / desktop (winsta.rs): anonymous WS + single 'desk'
desktop; the child attaches via STARTUPINFOW.lpDesktop and so
cannot enumerate or message WinSta0 windows. Both the
CreateDesktopW outcome and the SetProcessWindowStation(restore)
outcome are handled together so neither object leaks on either
error path.

Self-protect (self_protect.rs): broker process DACL rewritten to
ALLOW <group>, SYSTEM, Admins, OWNER_RIGHTS=0, with
PROTECTED_DACL_SECURITY_INFORMATION so the inherited user grant is
stripped. Same-user sandbox children (group deny-only, Admins
deny-only) cannot OpenProcess the broker at any access mask. The
applied SDDL is read back and written to stderr after success.

Launch (launch.rs): STARTUPINFOEXW with
PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY (extension-point disable,
font disable, no-remote-image-load, no-low-label-image-load — the
PREFER_SYSTEM32 and CFG_ALWAYS_ON bits are intentionally omitted
because they break mingw-built shells) and
PROC_THREAD_ATTRIBUTE_HANDLE_LIST (std handles only). RAII handle
ownership throughout: OwnedHandle wraps the three token handles
and SpawnedChild wraps PROCESS_INFORMATION, terminating the
suspended child on drop unless defuse()d after assign+resume — so
a failed AssignProcessToJobObject cannot orphan it.

Environment block: parent's env with HTTP_PROXY/HTTPS_PROXY ->
http://127.0.0.1:<--http-proxy> and ALL_PROXY ->
socks5h://127.0.0.1:<--socks-proxy> (both upper- and lower-case);
NO_PROXY blanked; SANDBOX_RUNTIME_WIN_BROKER_PID exported for the
self-protect test. Sorted by uppercase key for dedup.

cmd.exe /c quoting is PASSTHROUGH: build_cmdline joins the post-/c
argv with spaces and wraps the whole thing in one outer pair of
double-quotes for /s to strip; the content is delivered to cmd
verbatim. & chains, double-quoted spans quote — exactly as the
user typed. The post-/c string IS the user's cmd command; the
sandboxed cmd's metacharacters are the user's tool, not an escape
vector (the host-shell injection concern is the outer spawn,
addressed by argv-mode in the next PR).

--skip-group-check is an explicit fail-open CLI flag (NOT an env
var) for ephemeral CI runners that create the group in-job and
cannot logout/login mid-run. With it set and the group absent
from the broker token, exec proceeds with a stderr warning;
production refuses by default.

CI: vendor/srt-win/ci/smoke-exec.ps1 (E1-E10b incl. E4b/E7b),
self-contained under fixed sublayer 5b0e64f4-...-9b7d with
--group-sid S-1-5-32-544 and --proxy-port-range 60080-60089. The
Exec helper splits srt-win:-prefixed broker diagnostics from the
child's actual output. Rows: exit-code propagation; group
deny-only in child token (whoami /groups /FO CSV); outbound
blocked; loopback in-range permitted (real broker-side listener);
loopback out-of-range blocked; proxy-env injected (one set VAR per
variable); self-protect blocks OpenProcess(PROCESS_VM_READ) from
the child via P/Invoke; cmd /c passthrough (user-quoted payload
literal, & chains); --name resolution; nested-exec refused;
--skip-group-check silent-when-ready / warns-when-absent.
cleanup.ps1 gains the smoke-exec sublayer.
2026-05-22 23:53:48 -04:00
ig
098d3ec741 fix(windows): SD primary-group for AccessCheck, propagate cargo-test exit, smoke uses test sublayer
Three fixes, the first two found because the third was masked:

1) SDDL primary group. The filter SDs were O:LSD:(...) — owner +
   DACL but no G:. WFP's kernel-side ALE_USER_ID match accepts
   that, but user-mode AccessCheck (which the sd_access_check_matrix
   test uses to prove the filter-0 trick) rejects it with
   ERROR_INVALID_SECURITY_DESCR. All three SDDL builders now emit
   O:LSG:LSD:(...). The G: value is irrelevant to DACL evaluation;
   LS is just a stable principal. Doc-comments + tests updated to
   match.

2) CI exit-code propagation. The build step's pwsh ran cargo
   build/test/clippy sequentially; cargo test failed with the
   above, pwsh continued, clippy exited 0, the step reported
   success. Now sets $PSNativeCommandUseErrorActionPreference so
   any non-zero native exit aborts the step. (smoke.ps1 already
   guards every native call via the Run helper's $LASTEXITCODE
   check.)

3) smoke.ps1 / cleanup.ps1 target a fixed test sublayer GUID
   ($TestSublayer param), not the production default. The
   idempotent-install path purges all srt-win-tagged filters under
   its sublayer before re-adding, so a local run against the
   default would have silently clobbered a real install on the
   same dev box. The random-GUID alt-sublayer isolation test keeps
   its own GUID; the unperturbed-check now compares against
   $TestSublayer.
2026-05-22 18:25:32 -04:00
ig
0c5f878d68 fix(windows): address review r2 — edition 2024, extract smoke to ci/smoke.ps1, CLI polish
Cargo:
- Bump to edition 2024. No fixups needed — the crate has no
  `unsafe fn` (only unsafe blocks in safe fns) and no `gen`
  identifiers.

CLI:
- Drop unused GroupRef from `wfp status` — tag-based detection
  only needs --user-sid / --sublayer-guid.
- Validate caller-supplied --group-sid / --user-sid up front via
  ConvertStringSidToSidW so a typo surfaces as
  "invalid --user-sid 'X'" rather than an SDDL parse error three
  calls deep.

CI:
- Extract the entire group/WFP smoke test out of the workflow yaml
  into vendor/srt-win/ci/smoke.ps1, runnable locally on a Windows
  dev box as `pwsh ci/smoke.ps1 <path-to-srt-win.exe>`. Likewise
  the always() teardown moves to ci/cleanup.ps1.
- smoke.ps1 incorporates the new coverage rows: invalid-SID
  negative tests (MustFail helper), idempotent-no-op
  uninstall/delete, and writes the alt-sublayer GUID to GITHUB_ENV
  so cleanup.ps1 can remove it on failure.
- Toolchain step now requests the clippy component explicitly
  rather than relying on the runner image's preinstalled rustup.
2026-05-22 17:37:55 -04:00
ig
0e626c470b fix(windows): address review r1 — error handling, CI coverage, nits
Rust:
- wfp.rs delete_tagged_filters: propagate FwpmFilterEnum0 errors
  instead of breaking silently. Inside install_filters' txn a
  swallowed enum error would skip stale-filter cleanup and grow the
  filter set on every install.
- wfp.rs: only count successful FwpmFilterDeleteByKey0 in the
  removed-filters tally.
- wfp.rs: drop dead group_exists() and its imports.
- wfp.rs: sublayer display name is the tool ("srt-win"), not the
  group name.
- sid.rs: add sid_account_exists() (LookupAccountSidW reverse
  lookup) so 'group status --group-sid <bogus>' reports
  state=absent rather than created-not-on-token. Tolerates
  transient lookup failure (DC unreachable) by falling through to
  the token check.
- main.rs: wire the above into the --group-sid status path.

CI:
- Build step now runs clippy with -D warnings.
- Smoke test covers: pre-install absent; group create idempotency;
  --group-sid status path (incl. unmapped-SID -> absent);
  --user-sid install path; --sublayer-guid isolation (alt GUID
  gets its own filter set and default is unperturbed); per-user
  wfp uninstall as primary teardown.
- always() cleanup step removes WFP filters + test group even when
  the smoke test throws.
2026-05-22 17:24:48 -04:00
ig
a071a4ccfd ci(windows): build + smoke-test srt-win on x64 and arm64 runners
Adds windows-latest and windows-11-arm legs to the integration-test
matrix. Each leg builds the srt-win crate, runs cargo test, then
exercises the full group/wfp lifecycle:

  group create  -> status (created-not-on-token; no logout in CI)
  wfp install   -> status (installed, >=6 filters)
  wfp install   -> status (idempotent; same filter count)
  wfp uninstall -> status (absent)
  group delete  -> status (absent)

Existing Linux/macOS steps are gated to skip on Windows; TS-side
Windows integration arrives in a later PR.
2026-05-22 17:09:17 -04:00
Dylan Conway
9e06e804cb fix(sandbox): set CLOUDSDK_PROXY_TYPE=http (was invalid "https") (#237)
* fix(sandbox): set CLOUDSDK_PROXY_TYPE=http (was invalid "https")

gcloud rejects CLOUDSDK_PROXY_TYPE=https with:
  Invalid value for property [proxy/type]: The proxy type property
  value [https] is not valid. Possible values: [http, http_no_tunnel,
  socks4, socks5].

The proxy/type setting names the protocol the proxy itself speaks, not
the traffic it tunnels. The sandbox proxy at httpProxyPort is an HTTP
CONNECT proxy (HTTPS_PROXY is already set to http://localhost:<port>
for the same reason), so "http" is the correct value.

Adds a unit test for generateProxyEnvVars covering this.

Fixes #151

* ci: revert bun to 1.3.1

The 1.3.13 bump exposed two new flakes (linux/x86-64 reset() bridge exit
delivery; linux/arm64 http.Server listen/address race in
configurable-proxy-ports). Reverting to 1.3.1 until those are addressed
upstream. The spawnAsync test changes from #243 remain — they are
correct on both versions.
2026-05-05 15:15:35 -07:00
Dylan Conway
703741b618 test(integration): use async spawn so the in-process proxy can respond; bump bun to 1.3.13 (#243)
* test(integration): use async spawn so the in-process proxy can respond

The integration tests run sandboxed curl commands against the HTTP/SOCKS
proxy that lives in the same process. Driving them with spawnSync blocks
this event loop for the duration of the wrapped command, so the proxy
request handler cannot run — curl is waiting on a server whose JS thread
is parked inside the very spawnSync that is waiting for curl. The suite
only passed because some bun versions happen to let the loop tick during
spawnSync; on linux/x86-64 that has been intermittent (the recent CI
flakes), and on newer bun it stops entirely.

Replace spawnSync with a small async spawnAsync helper that mirrors the
{stdout, stderr, status, signal} return shape. The event loop stays
alive, the proxy responds, and reset() between describes no longer hits
its 5s fallback.

Also bump CI bun to 1.3.13.

* test: move spawnAsync to shared helper, close stdin, convert remaining proxy tests

- Extract spawnAsync into test/helpers/spawn.ts so configurable-proxy-ports
  and update-config tests can share it (both drive curl through an
  in-process proxy and hit the same deadlock on bun >=1.3.2).
- Close child stdin so the child sees EOF immediately, matching spawnSync
  with no `input`. Without this, `su` in the privilege-escalation test
  waits on the open pipe.
- Convert the remaining proxy-hitting spawnSync call sites in those two
  files.
2026-05-05 13:14:19 -07:00
Dylan Conway
7f650392ee Bake BPF filter into apply-seccomp, build in CI (#199)
* Bake BPF filter into apply-seccomp, build in CI

The unix-block BPF filter is now generated as a C header at build time
and compiled directly into apply-seccomp. The separate .bpf file is gone,
as is the TS machinery that found, loaded, and tracked it.

vendor/seccomp/build.ts compiles the BPF generator, runs it for both
x64 and arm64, writes the bytes into unix-block-bpf.h, then compiles
apply-seccomp with that header #included. An #if defined(__x86_64__) /
#elif defined(__aarch64__) block in the header picks the right filter
at compile time.

The built binaries are no longer committed. release.yml runs a matrix
job on both an x64 and an arm64 runner, each building apply-seccomp
for its own architecture, uploading the result as an artifact. The
publish job downloads both into vendor/seccomp/{x64,arm64}/ before
npm publish, keeping the tarball layout unchanged.

* Build seccomp binaries in docker-tests CI job

* Remove stale references to on-disk BPF filter file

The two fail-closed tests in pid-namespace-isolation now test execve
failure instead of filter-file validation, since apply-seccomp no longer
takes a filter argument. README still described .bpf files in
vendor/seccomp/.

* Bump version to 0.0.47
2026-04-02 10:58:33 -07:00
Dylan Conway
e94c5fd01d Run full test suite in CI and migrate platform skips to describe.if (#197)
* Run full test suite in CI and migrate platform skips to describe.if

CI was running test:unit + test:integration, a curated subset of 5 files.
Most test files were never run in CI. Switch to `npm test` which runs
everything. Drop the test:unit/test:integration scripts.

Migrate the inline `if (skipIfNotLinux()) return` pattern to bun's native
`describe.if()`/`it.if()`. The old pattern made wrong-platform tests show
as pass (zero assertions, green checkmark) instead of skip — CI's test
count looked the same regardless of what actually ran. New
test/helpers/platform.ts exports isLinux/isMacOS/isSupportedPlatform.

Delete ~310 lines of unreachable tests from seccomp-filter.test.ts:
- skipIfNotAnt() gate checked USER_TYPE env var that nothing sets
- Two tests called wrapCommandWithSandboxLinux() with no restrictions,
  which returns the command unwrapped at the early-return check —
  expect("echo test").not.toContain("apply-seccomp") was vacuously true

Pin allow-read root-deny tests to /bin/bash — EXEC_DEPS doesn't list
/opt/homebrew, so execvp failed on Macs with homebrew bash as SHELL.

Add docker-tests CI job: unprivileged container on both arches,
exercises enableWeakerNestedSandbox end-to-end.

Drop push trigger from '**' to 'main' — PRs were running the full
matrix twice (once for branch push, once for the PR event).

* Replace mock.module with spyOn in linux-dependency-error tests

mock.module patches bun's module cache globally and never unmocks.
With npm test running all files in one process (instead of the old
test:unit + test:integration split), the mock leaked: every file that
imported getApplySeccompBinaryPath after this one got () => null, so
pid-namespace-isolation.test.ts and integration.test.ts failed in
beforeAll.

spyOn swaps one export binding; mockRestore in afterEach puts it back.
The callee's own import binding routes through the same slot in bun, so
checkLinuxDependencies sees the spy without any module-level surgery.

Also spies on whichSync directly rather than overwriting Bun.which on
globalThis — same fix, closer to what's actually being tested.

Drop stale README reference to the deleted test:integration script.

* Replace docker test-suite job with srt end-to-end test

The full suite assumes bwrap --proc /proc works; an unprivileged
container doesn't have CAP_SYS_ADMIN for that. Only tests that set
enableWeakerNestedSandbox can pass there.

Instead of filtering which unit tests to run, test the thing the job
is for: build srt, run it with enableWeakerNestedSandbox, check that
allowed writes land, denied writes don't, and the seccomp filter blocks
AF_UNIX. Gated on SRT_E2E_DOCKER so host jobs skip it.

* Rename docker job to match other Tests jobs

* Add required network key to docker test config

SandboxRuntimeConfigSchema requires network (no .optional()). Without it
loadConfig returns null, srt falls through to getDefaultConfig, and the
sandbox enforces a different allowWrite than the test expects.

* Add explicit timeouts to update-config sandboxed-curl tests

The three it.if(isLinux) tests each run two spawnSync calls with curl
--max-time 3 then --max-time 5. When example.com responds slowly both
curls run to their limits and the body takes ~8s, but bun's default
test timeout is 5000ms. bun aborts mid-body; afterEach runs reset()
against an in-flight spawn and the next test sees stale state.

These were never in test:integration so they never ran on CI before
this branch. On fast responses they complete in under 200ms.
2026-03-31 15:36:39 -07:00
Dylan Conway
ed5a909983 Fix enableWeakerNestedSandbox after apply-seccomp namespace changes (#196)
* Fix enableWeakerNestedSandbox after apply-seccomp namespace changes

apply-seccomp now creates a nested userns and writes /proc/self/setgroups
and uid_map before applying the seccomp filter. That broke
enableWeakerNestedSandbox in two ways:

  1. Without --proc, bwrap's --ro-bind / / leaves /proc read-only.
     apply-seccomp's setgroups write dies with EROFS.

  2. In unprivileged Docker (the flag's target), apply-seccomp's proc
     remount fails the kernel domination check — Docker's /proc masks
     are MNT_LOCKED in the less-privileged nested userns.

And the reason bwrap never got that far in Docker: bwrap only auto-adds
--unshare-user when EUID != 0. Docker's default is EUID=0 without
CAP_SYS_ADMIN; bwrap assumes it has caps, tries direct clone(NEWPID),
and EPERMs before apply-seccomp runs.

Changes:

  - bwrap args for weak mode: --unshare-user (force userns even as
    EUID=0) and --bind /proc /proc (restore rw /proc for setgroups)
  - apply-seccomp: tolerate mount(/proc) EPERM. The nested userns is
    the isolation boundary; the proc remount only hides outer PIDs
    from `ls /proc`.

Fixes the two failing mandatory-deny-paths tests that exercise
enableWeakerNestedSandbox. No test changes required.

Bump version to 0.0.46.

* Run mandatory-deny-paths tests in CI

These exercise enableWeakerNestedSandbox — the two tests that broke
when apply-seccomp started nesting namespaces. Add explicitly until
the full-suite CI change lands.

* Remove CI step comment
2026-03-31 12:56:06 -07:00
David Dworken
7ee4ac602d Isolate seccomp workload in nested PID ns and block io_uring (#183)
* Isolate seccomp workload in nested PID namespace and block io_uring

apply-seccomp now creates a nested user+PID+mount namespace before applying
the seccomp filter. The user command runs as PID 2 under a non-dumpable PID 1
reaper, with /proc remounted so only the inner process tree is visible. This
prevents the sandboxed command from ptracing or patching the unfiltered bwrap
init, bash wrapper, or socat helpers via /proc/N/mem, regardless of the host's
kernel.yama.ptrace_scope setting. Namespace setup failure aborts rather than
silently degrading.

The BPF filter now also blocks io_uring_setup/enter/register. IORING_OP_SOCKET
(Linux 5.19+) creates sockets without going through socket(), and seccomp
cannot inspect SQEs in the shared ring, so denying ring creation entirely is
the only safe option.

The filter generator now accepts an optional target-arch argument so a single
builder can emit both x64 and arm64 filters. Prebuilt binaries and filters are
regenerated for both architectures.

* Pass CAP_SYS_ADMIN to apply-seccomp and clear ambient caps before exec

apply-seccomp needs CAP_SYS_ADMIN to unshare PID+mount namespaces. The
original approach obtained it via unshare(CLONE_NEWUSER), but on hosts
where an LSM restricts unprivileged user namespaces (Ubuntu 24.04 with
AppArmor defaults), the nested userns is created without capabilities
and the setgroups write fails.

bwrap now passes --cap-add CAP_SYS_ADMIN (scoped to its user namespace)
so apply-seccomp can unshare directly. The nested-userns path remains as
a fallback for standalone invocation.

apply-seccomp clears the ambient capability set after remounting /proc,
so the sandboxed command's execve drops to zero capabilities and cannot
umount /proc to reveal the outer mount underneath. Two new tests cover
CapEff=0 and umount denial.

* chore: bump version to 0.0.44

* Add --unshare-user so --cap-add works with setuid bwrap

Setuid bwrap rejects --cap-add from non-root because it would grant
real host capabilities. --unshare-user forces user-namespace mode so
the capability is scoped to that namespace and the flag is accepted.

* Disable AppArmor userns restriction in CI instead of using setuid bwrap

Setuid bwrap rejects --cap-add from non-root, so that path is a dead end.
Instead, disable kernel.apparmor_restrict_unprivileged_userns in CI so
apply-seccomp's nested-userns path works without any bwrap cooperation.
This matches what production Ubuntu 24.04 users need to do anyway, now
documented in the README.

* Exit inner init as soon as the worker exits

reap_until was waiting for all children including orphaned background
processes reparented to PID 1, which hung the sandbox when the user
command backgrounded something long-running and then exited. Return
immediately when the worker terminates; PID 1 exiting tears down the
namespace and SIGKILLs any stragglers.
2026-03-30 17:07:40 -07:00
Dylan Conway
ef4afdef4d ci: add npm release workflow (#143) 2026-02-19 14:48:18 -08:00
Sosuke Suzuki
7c9dbfa8dc ci: add Node.js fallback test for whichSync 2026-02-04 07:58:55 +00:00
David Dworken
04fc873246 Update macOS CI runner from retired macos-13 to macos-15-large
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 18:16:39 +00:00
ollie-anthropic
380da4a976 fix integration tets 2025-11-13 02:10:31 -08:00
David Dworken
e88bbb7fd7 Add tests for binShell parameter with zsh and install zsh in CI
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 17:34:32 -07:00
David Dworken
bfab892a2e Rename workflow from "Integration Tests" to "Tests"
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 16:04:00 -07:00
David Dworken
a918f1dd6d Add unit tests to CI workflow and fix bridge process cleanup
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 16:02:32 -07:00
David Dworken
abd65b17f8 Remove Artifactory npm configuration from integration tests 2025-10-24 15:34:15 -07:00
David Dworken
4eb7b42b10 Enable ARM64 Linux runners in integration tests 2025-10-24 15:32:43 -07:00
David Dworken
23e9e22622 Add BPF/seccomp integration for Linux unix socket blocking and comprehensive testing infrastructure
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 13:55:33 -07:00