{"id":50840222,"url":"https://github.com/can1357/isobox","last_synced_at":"2026-06-14T06:07:53.198Z","repository":{"id":362786587,"uuid":"1260788688","full_name":"can1357/isobox","owner":"can1357","description":"Run a command in a sandbox with the same flags on every OS — one capability model compiled to Seatbelt (macOS), gVisor (Linux), and AppContainer (Windows).","archived":false,"fork":false,"pushed_at":"2026-06-05T22:44:29.000Z","size":126,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-05T23:14:09.506Z","etag":null,"topics":["appcontainer","capabilities","cli","confinement","cross-platform","go","golang","gvisor","isolation","ld-preload","linux","macos","runsc","sandbox","sandboxing","seatbelt","security","windows"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/can1357/isobox","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/can1357.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-05T21:53:32.000Z","updated_at":"2026-06-05T22:41:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/can1357/isobox","commit_stats":null,"previous_names":["can1357/isobox"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/can1357/isobox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/can1357%2Fisobox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/can1357%2Fisobox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/can1357%2Fisobox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/can1357%2Fisobox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/can1357","download_url":"https://codeload.github.com/can1357/isobox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/can1357%2Fisobox/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34310835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appcontainer","capabilities","cli","confinement","cross-platform","go","golang","gvisor","isolation","ld-preload","linux","macos","runsc","sandbox","sandboxing","seatbelt","security","windows"],"created_at":"2026-06-14T06:07:52.417Z","updated_at":"2026-06-14T06:07:53.187Z","avatar_url":"https://github.com/can1357.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eisobox\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eRun a command in a sandbox, with the same flags on every OS.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/can1357/isobox/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/can1357/isobox/ci.yml?branch=main\u0026style=flat\u0026colorA=222222\u0026colorB=3FB950\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pkg.go.dev/github.com/can1357/isobox\"\u003e\u003cimg src=\"https://img.shields.io/badge/pkg.go.dev-reference-00ADD8?style=flat\u0026colorA=222222\u0026logo=go\u0026logoColor=white\" alt=\"Go Reference\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://goreportcard.com/report/github.com/can1357/isobox\"\u003e\u003cimg src=\"https://img.shields.io/badge/go%20report-A%2B-3FB950?style=flat\u0026colorA=222222\" alt=\"Go Report Card\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/can1357/isobox/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/can1357/isobox?style=flat\u0026colorA=222222\u0026colorB=58A6FF\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://go.dev\"\u003e\u003cimg src=\"https://img.shields.io/badge/Go-1.26-00ADD8?style=flat\u0026colorA=222222\u0026logo=go\u0026logoColor=white\" alt=\"Go\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Simple universal sandboxing with preload capabilities.\u003cbr\u003e\n  One policy compiles to Seatbelt, gVisor, or AppContainer, and your command's exit code passes straight through.\n\u003c/p\u003e\n\n---\n\n```sh\nisobox -- echo hi\n```\n\n| OS      | Backend                  | Mechanism            |\n| ------- | ------------------------ | -------------------- |\n| macOS   | Seatbelt                 | `sandbox-exec`       |\n| Linux   | gVisor                   | `runsc`              |\n| Windows | AppContainer             | in-process Win32     |\n\nBy default the CLI chooses the native backend, then optional Docker backends if\nthey can satisfy requested capabilities the native backend cannot. Override with\n`--backend`.\n\n## The problem it solves\n\nEvery OS sandbox has its own vocabulary and its own gaps. A profile that denies\nnetwork on macOS does not transfer to Linux, and the two do not even agree on what\n\"deny network\" includes. isobox papers over this with an explicit **capability\nmodel** instead of a lowest-common-denominator illusion:\n\n- Each backend declares the set of capabilities it can actually enforce.\n- Build your policy from the **intersection of per-OS backend unions**:\n  `(macOS native+compatible) ∩ (Linux native+compatible) ∩ (Windows native+compatible)`.\n- Reach for one backend's **union** extras and isobox still runs, but attaches a\n  queryable **caveat** wherever enforcement falls short of the stated intent.\n- `--strict` refuses anything outside that portable per-OS intersection, so you\n  fail loudly instead of silently degrading.\n\nBecause the capability tables are plain data, you can inspect or preview any\nbackend's plan from any host. Running it still needs that backend's tool installed.\n\n## Install\n\nInstall Go 1.26+ and `just`, then:\n\n```sh\njust build\njust test\n```\n\nWithout `just`:\n\n```sh\ngo build -o isobox ./cmd/isobox\ngo test ./...\n```\n\nOn Linux, the optional LD_PRELOAD filesystem fallback is C:\n\n```sh\njust isoboxfs-build\njust isoboxfs-test\n```\n\nThis builds `preload/isoboxfs/libisoboxfs.so` from the C sources under\n`preload/isoboxfs`.\n\nGitHub Actions runs `just build` and `just test` on Ubuntu, macOS, and Windows,\nplus the C preload build and test on Ubuntu.\n\n## Quick start\n\n```sh\nisobox -- echo hi                              # agent defaults (see Profiles)\nisobox --profile=tight -- echo hi              # locked down: no net, read-only, no writes\nisobox --net=enable -- curl https://example.com\nisobox --writable ./work -- just build         # persist ./work plus the default cwd\nisobox --write=ephemeral -- ./build.sh         # writes happen, then vanish\nisobox --cpus 1.5 --memory 512m --pids 64 -- ./build.sh  # cap CPU, memory, and processes\nisobox --timeout 30s -- ./build.sh              # bound wall-clock execution\nisobox --readable . --cpus 1 --memory 512m --pids 64 -- ./build.sh  # macOS can auto-pick Docker/runsc if configured\nisobox --print --backend gvisor -- ls /        # preview the Linux plan from any OS\nisobox --caps                                  # print the capability matrix\n```\n\nEverything after `--` is the command and its arguments.\n\n## Profiles\n\nA profile sets the defaults; explicit flags always override it.\n\n- **`agent`** (default): outbound-only network, the command working directory and OS\n  temp writable, broad host reads with common credential paths denied, secret-like\n  environment variables scrubbed (`*_TOKEN`, `*_KEY`, `*_SECRET`, `AWS_*`,\n  `GITHUB_*`, `ANTHROPIC_*`, `OPENAI_*`, `SSH_AUTH_SOCK`), and writes elsewhere\n  kept off the host. On gVisor this is a memory-backed root overlay plus\n  persistent writable binds. Seatbelt and AppContainer cannot redirect outside\n  writes, so they deny them and report the caveat in the plan.\n- **`tight`**: no external network, broad reads, no writes anywhere.\n\n`outbound-only` blocks inbound/listen paths; it is not egress filtering. A\nprogram with `net.outbound` can still connect to arbitrary external addresses\nand exfiltrate data unless the caller or surrounding network separately\nconstrains egress.\n\n## Capabilities\n\n`isobox --caps` prints the live matrix (`yes` = enforced, `-` = unsupported):\n\n```\nCAPABILITY          WINDOWS  DOCKER-EPHEMERAL  DOCKER-RUNSC-EPHEMERAL  GVISOR  SEATBELT  PORTABLE  DESCRIPTION\nenv.scrub           yes      yes               yes                     yes     yes       yes       scrub inherited environment variables by name pattern before launch\nfs.read.deny        -        -                 -                       yes     yes       -         read broadly except denied sensitive paths\nfs.read.host        -        -                 -                       yes     yes       -         read the host filesystem broadly\nfs.read.scope       yes      yes               yes                     yes     yes       yes       restrict host/user filesystem reads to an allowlist plus backend runtime paths\nfs.write.deny       yes      yes               yes                     yes     yes       yes       deny all writes to the host filesystem\nfs.write.ephemeral  yes      yes               yes                     yes     yes       yes       permit backend ephemeral writes; configured host inputs stay untouched\nfs.write.scope      yes      yes               yes                     yes     yes       yes       permit writes under listed paths plus opt-in temp roots; listed-path writes persist\nipc.restrict        yes      yes               yes                     yes     -         yes       no host local IPC endpoint reachable\nkernel.isolation    -        -                 yes                     yes     -         -         serve syscalls from a user-space kernel; shield host kernel\nmach.restrict       -        -                 -                       -       yes       -         restrict Mach service lookups (Seatbelt-only)\nnet.disable         yes      yes               yes                     yes     yes       yes       deny network access; some backends additionally block loopback (see caveats)\nnet.enable          yes      yes               yes                     yes     yes       yes       permit network access\nnet.outbound        yes      yes               yes                     yes     yes       yes       permit outbound connections; block inbound TCP listeners; not a domain/CIDR allowlist\nproc.no_exec        yes      -                 -                       yes     -         -         forbid executing another program image\nres.cpu             yes      yes               yes                     yes     -         yes       limit CPU usage to a fraction of the host's cores\nres.memory          yes      yes               yes                     yes     -         yes       limit the sandbox's memory footprint\nres.pids            yes      yes               yes                     yes     -         yes       limit the sandbox's process/task count\n```\n\n`PORTABLE` marks the intersection of per-OS compatibility unions, not the\nintersection of every named backend. For example, macOS can satisfy resource caps\nthrough Docker/runsc even though Seatbelt itself cannot. `res.disk` is not a\ncapability today. Always inspect plan caveats; backend runtime paths, temp roots,\nloopback behavior, net.outbound exfiltration risk, inherited terminal descriptors,\nand platform ambient grants can still differ.\n\n## Inspecting a plan\n\n`--print` compiles a spec to a backend's plan and shows it without running. It works\nfor any backend on any host, so you can review the exact Linux invocation from a Mac:\n\n```\n$ isobox --print --backend gvisor -- just build\nbackend:  gvisor\nenforces: fs.read.deny, fs.read.host, fs.write.ephemeral, fs.write.scope, kernel.isolation, net.outbound\nfilesystem: linux-namespace-view\ncaveats:\n  - net.outbound is not an egress filter or domain/CIDR allowlist; permitted outbound connections can exfiltrate data unless the caller or surrounding network constrains them\n  - host filesystem scopes can expose host IPC endpoints\n  - gvisor overlay flag syntax varies by runsc version (used --overlay2=root:memory)\n  ...\nargv:\n  runsc --overlay2=root:memory --oci-seccomp run --bundle \u003cbundle\u003e isobox-gvisor-...\n```\n\nFor Seatbelt the plan also includes the generated SBPL profile; for AppContainer it\nincludes the resolved grants.\n\n## CLI reference\n\n| Flag                                      | Default        | Meaning                                                                                                  |\n| ----------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------- |\n| `--profile=agent\\|tight`                  | `agent`        | Apply defaults. `tight` restores the no-network/no-write posture.                                        |\n| `--net=disable\\|enable\\|outbound`         | profile        | Network policy. `outbound` allows clients and blocks listen/inbound; it is not a domain/CIDR allowlist or egress filter. |\n| `--write=none\\|scope\\|ephemeral\\|overlay` | profile        | Deny writes, persist only `--writable`, discard all writes, or persist writable paths with shadow/deny elsewhere. |\n| `--writable PATH`                         | cwd in profile | Repeatable. Writable path; adds to the agent cwd grant, or implies `--write=scope` under `tight`.        |\n| `--readable PATH`                         | –              | Repeatable. Restrict reads to these paths where the backend supports it.                                 |\n| `--read-deny PATH`                        | credentials    | Repeatable. Deny reads to sensitive paths while broad/scoped reads remain.                               |\n| `--env-deny PATTERN`                     | credentials    | Repeatable. Remove environment variables by exact name or glob (`*_TOKEN`, `AWS_*`, `SSH_AUTH_SOCK`).    |\n| `--env-allow PATTERN`                    | –              | Repeatable. If present, keep only matching environment variables before applying `--env-deny`.           |\n| `--no-exec`                               | `false`        | Forbid exec of a new program image after launch (fork/clone still allowed).                              |\n| `--allow-temp`                            | profile        | Also allow writes to the OS temp dir. Requires `--write=scope` or `--write=overlay`.                     |\n| `--cpus N`                                | –              | Limit CPU usage to N logical cores (fractional allowed, e.g. `1.5`). May auto-select Docker/runsc on macOS when the rest of the spec fits. |\n| `--memory SIZE`                           | –              | Limit memory (`512m`, `2g`, or raw bytes). May auto-select Docker/runsc on macOS when the rest of the spec fits.                          |\n| `--pids N`                                | –              | Limit process/task count. May auto-select Docker/runsc on macOS when the rest of the spec fits.                           |\n| `--timeout DURATION`                       | `0`            | Cancel the command after a Go duration (`30s`, `5m`). Zero means no timeout.                             |\n| `--mach-allow NAME`                       | –              | Repeatable. Allow a Mach service global-name (Seatbelt only).                                            |\n| `--strict`                                | `false`        | Reject capabilities outside the per-OS portable intersection.                                             |\n| `--dir PATH`                              | –              | Working directory for the command; also becomes the default agent writable path.                        |\n| `--backend BACKEND`                       | `auto`         | Auto-select or force a backend (`seatbelt`, `gvisor`, `appcontainer`, `docker-ephemeral`, `docker-runsc-ephemeral`).                     |\n| `--print`                                 | `false`        | Compile and print the plan without running.                                                              |\n| `--caps`                                  | `false`        | Print the capability matrix and exit.                                                                    |\n| `--version`                               | `false`        | Print version and build information and exit.                                                            |\n\nBackend tools and Docker workarounds are configurable through\n`ISOBOX_SANDBOX_EXEC`, `ISOBOX_RUNSC`, `ISOBOX_DOCKER`, `ISOBOX_DOCKER_IMAGE`,\n`ISOBOX_DOCKER_RUNTIME`, and `ISOBOX_DOCKER_RUNSC_RUNTIME`.\n\n## Library\n\n```go\nspec := isobox.Spec{\n\tArgs:        []string{\"just\", \"build\"},\n\tNet:         isobox.NetDisable,\n\tWrite:       isobox.WriteScope,\n\tWritable:    []string{\"out\"},\n\tCPUs:        1.5,        // cap at 1.5 cores where the backend supports it\n\tMemoryBytes: 512 \u003c\u003c 20,  // cap at 512 MiB; 0 means unlimited\n\tPIDs:        64,          // cap process/task count; 0 means unlimited\n}\n\nr, err := isobox.NewForSpec(spec) // native first, optional Docker backends if needed\nif err != nil {\n\tpanic(err)\n}\n\nplan, _ := r.Compile(spec) // inspect plan.Caveats without running\ncode, err := r.Run(context.Background(), spec, isobox.Stdio{})\nif err != nil {\n\tpanic(err) // failed to launch the sandbox\n}\nos.Exit(code) // the command's own exit code\n```\n\nThe capability tables are plain data, so any backend is inspectable from any host:\n\n```go\nisobox.Union()                       // every capability any backend supports\nisobox.Intersection()                // capabilities common to all backends\nisobox.CapsOf(isobox.BackendGvisor)  // one backend's set\nisobox.BackendForSpec(spec)          // auto-selection result on this host\nisobox.NewBackend(b)                 // a runner for a named backend, on any OS\n```\n\n## Companion tools\n\n- `cmd/isobox-sshd` starts an SSH server _inside_ an isobox so you can shell in and\n  poke at the confinement interactively, the way a remote user would.\n- `cmd/isobox-testkit-host` and `cmd/isobox-testkit-client` form an end-to-end test\n  harness that launches a probe inside a sandbox and reports, per capability,\n  whether enforcement actually held.\n\nisobox does not currently provide structured denial audit logging or a\n`--log-denials` mode; use `--print`/plan caveats plus backend or OS logs when\ndebugging denied operations.\n\n## Notes and caveats\n\n- `--write=overlay` is exact on gVisor: `--overlay2=root:memory` makes writes\n  outside persisted binds ephemeral while `--writable` paths still hit the host.\n  Seatbelt and AppContainer cannot redirect filesystem writes, so they degrade\n  outside-overlay writes to denial with a plan caveat.\n- gVisor `--read-deny` obscures existing denied paths with empty bind mounts.\n  Docker and AppContainer also apply caveated read-deny masks/temporary DENY\n  ACEs where they can, but they still do not advertise `fs.read.deny` because\n  they lack broad host-read support. Nonexistent denied paths cannot always be\n  pre-mounted or ACL-stamped without touching the host.\n- `--env-deny` and `--env-allow` match environment variable names, not values.\n  Matches use exact names or `path.Match`-style globs. If any allow pattern is\n  set, the inherited/explicit environment becomes an allowlist first; deny\n  patterns are then applied and take precedence. The default `agent` profile uses\n  deny patterns so ordinary variables such as `PATH`, `HOME`, `TERM`, locale, and\n  temp settings still pass unless they look like credentials.\n- macOS `--write=ephemeral` clones the workspace with APFS `clonefile(2)`; it\n  protects that workspace, not all of `/`.\n- Windows `--write=ephemeral` recursively copies the workspace to a temporary\n  AppContainer-writable directory and deletes it on exit; it is workspace-scoped\n  and a full byte copy.\n- Scoped-write rules are path/mount/ACL based. Hardlinks or nested mountpoints\n  under writable paths can still affect the same host objects through aliases\n  outside the lexical scope; plan caveats call this out.\n- isobox does not enforce `res.disk`. Scoped and persistent writes, including\n  `--writable` paths, can fill the backing host filesystem unless the caller,\n  container runtime, VM, or filesystem quota constrains them separately. gVisor's\n  memory overlays keep non-persistent writes off host disk, but behavior can\n  differ by runsc overlay mode/version and writable bind mounts still consume host\n  disk.\n- Zero-value library `Stdio` and the CLI inherit the caller's stdin/stdout/stderr.\n  If stdin is a controlling terminal, an untrusted command receives that terminal\n  file descriptor. Seatbelt/gVisor/Docker/AppContainer do not currently advertise\n  a portable guarantee that terminal ioctls such as TIOCSTI are blocked; pass an\n  explicit non-terminal stdin (pipe, file, or empty reader) for non-interactive\n  untrusted commands.\n- `--cpus`, `--memory`, and `--pids` cap resources on every backend that has a\n  real mechanism: gVisor maps them onto the sandbox's host cgroup via the OCI\n  bundle (`runsc` needs cgroup support to enforce), Docker backends pass `--cpus`,\n  `--memory`, `--memory-swap`, and `--pids-limit` to `docker run`, and\n  AppContainer assigns the process to a Windows job object (whole-job memory cap,\n  CPU hard cap scheduled as a share of all host cores, and active-process cap).\n  Seatbelt has no kernel resource-limit primitive, so isobox applies caveated\n  best-effort process-group CPU/memory watchdogs but does not advertise\n  `res.cpu`, `res.memory`, or `res.pids`.\n- `--timeout` is a CLI wall-clock deadline. It cancels the backend through the\n  same context path used for interrupts; zero leaves command lifetime unchanged.\n- `--net=outbound` is TCP-server oriented. Docker and gVisor deny\n  `listen`/`accept`/`accept4`; UDP bind behavior is backend-specific and called\n  out in plan caveats.\n- On macOS, Seatbelt's `mach.restrict` denies Mach service lookups, but native-TLS\n  clients (anything validating certificates through Security.framework, e.g. Go's\n  platform verifier or Rust's `rustls-platform-verifier`) need `trustd`/`securityd`\n  over Mach or they fail with `errSecNotAvailable` (-25291, \"No keychain is\n  available\") even though raw sockets connect. So whenever the network is enabled\n  (`--net=enable`/`outbound`), isobox automatically re-allows `com.apple.trustd`,\n  `com.apple.trustd.agent`, and `com.apple.SecurityServer`; the rest of the Mach\n  surface stays denied and the plan reports the carve-out as a caveat. Under\n  `--net=disable` (e.g. `--profile=tight`) none of these are granted.\n- On macOS, `docker-ephemeral` is an optional workaround for disposable Linux-image\n  runs. Set `ISOBOX_DOCKER_IMAGE`; it isolates at the VM level unless Docker is\n  configured with a `runsc` runtime. Docker plans pass `--cap-drop ALL` and\n  `--security-opt no-new-privileges`, but intentionally do not set `--user`:\n  `Spec` has no user field, and a fixed non-root uid would fail on common\n  writable host bind mounts owned by the invoking user/root-mapped Docker VM.\n- Use `--backend docker-runsc-ephemeral` to require Docker's `runsc` runtime and\n  get `kernel.isolation`; plain `docker-ephemeral` never advertises it even if\n  `ISOBOX_DOCKER_RUNTIME=runsc` is set.\n  Docker image tags are inspected and then rewritten to immutable image IDs before\n  launch, so VOLUME policy checks and execution target the same image object.\n- Seatbelt is covered end-to-end by the test suite where `sandbox-exec` exists.\n  gVisor, AppContainer, and Docker are covered by compiler unit tests; verify\n  runtime enforcement on a real Linux/Windows host before relying on them.\n\n## License\n\nMIT. See [LICENSE](LICENSE). Copyright (c) 2026 Can Bölük.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcan1357%2Fisobox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcan1357%2Fisobox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcan1357%2Fisobox/lists"}