#!/usr/bin/env bash set -euo pipefail for command in devcontainer docker node; do command -v "$command" >/dev/null || { echo "Required command missing: $command" >&2; exit 1; } done workspace=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P) tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT devcontainer up --workspace-folder "$workspace" > "$tmp/up.json" container=$(node -e ' const result = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); if (result.outcome !== "success" || !result.containerId) throw Error("CLI startup failed"); process.stdout.write(result.containerId); ' "$tmp/up.json") docker inspect "$container" > "$tmp/inspect.json" node - "$tmp/inspect.json" "$workspace" <<'NODE' const fs = require('fs'); const assert = require('assert/strict'); const [container] = JSON.parse(fs.readFileSync(process.argv[2], 'utf8')); const host = container.HostConfig; const expected = []; const products = new Set(['c222', 'c225', 'c227', 'c22b', 'c22d', 'c22e']); for (const entry of fs.readdirSync('/sys/bus/usb/devices')) { const base = `/sys/bus/usb/devices/${entry}`; const read = name => fs.readFileSync(`${base}/${name}`, 'utf8').trim(); try { if (read('idVendor') !== '046d' || !products.has(read('idProduct'))) continue; const bus = read('busnum'), number = read('devnum'); assert.match(bus, /^\d{1,3}$/); assert.match(number, /^\d{1,3}$/); const node = `/dev/bus/usb/${String(Number(bus)).padStart(3, '0')}/${String(Number(number)).padStart(3, '0')}`; if (fs.statSync(node).isCharacterDevice()) expected.push(node); } catch (error) { if (error.code !== 'ENOENT') throw error; } } assert.equal(container.State.Running, true, 'container must be running'); assert.equal(host.Privileged, false, 'privileged mode forbidden'); assert.notEqual(host.NetworkMode, 'host', 'host networking forbidden'); assert.deepEqual(host.DeviceCgroupRules || [], [], 'device cgroup overrides forbidden'); assert.deepEqual(host.DeviceRequests || [], [], 'additional device requests forbidden'); const devices = host.Devices || []; assert.deepEqual(devices.map(device => device.PathOnHost).sort(), expected.sort(), 'USB mappings must match current host allowlist; reconnects may require container recreation'); for (const device of devices) { assert.equal(device.PathInContainer, device.PathOnHost, 'device remapping forbidden'); assert.equal(device.CgroupPermissions, 'rw', 'only rw device access allowed'); } // Only the checkout bind and the CLI's optional editor volume are permitted. assert(container.Mounts.some(mount => mount.Type === 'bind' && mount.Source === process.argv[3] && mount.Destination === '/work'), 'workspace bind missing'); for (const mount of container.Mounts) { assert((mount.Type === 'bind' && mount.Source === process.argv[3] && mount.Destination === '/work') || (mount.Type === 'volume' && mount.Name === 'vscode' && mount.Destination === '/vscode'), `unexpected mount: ${mount.Source} -> ${mount.Destination}`); } console.log(`PASS: real Docker configuration; ${devices.length} exact allowed USB mapping(s)`); NODE # Expand PWD inside the container, not on the host. # shellcheck disable=SC2016 devcontainer exec --workspace-folder "$workspace" bash -c \ 'set -euo pipefail; test "$PWD" = /work; test -f .devcontainer/devcontainer.json; test ! -e /dev/uinput; printf "PASS: CLI exec and no /dev/uinput; no keyboard I/O performed\n"'