From 5daed9774cc81a3b0c253020caaa454a17d69c1e Mon Sep 17 00:00:00 2001 From: "Richie Gomez (he/him)" Date: Fri, 7 Aug 2026 09:39:03 -0700 Subject: [PATCH 1/3] Harden Linux SDK dependency setup Refresh apt metadata before the cached installation, verify Bubblewrap and LXC afterward, and retry a direct install when the cache action leaves dependencies incomplete. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 52e48fee-23e1-4b05-803c-522812fcdda2 --- .../workflows/SDK.Integration.Test.Job.yml | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/.github/workflows/SDK.Integration.Test.Job.yml b/.github/workflows/SDK.Integration.Test.Job.yml index aad3532a8..551df4ce7 100644 --- a/.github/workflows/SDK.Integration.Test.Job.yml +++ b/.github/workflows/SDK.Integration.Test.Job.yml @@ -58,6 +58,11 @@ jobs: - name: npm run build run: npm run build + - name: Refresh Linux package indexes + if: matrix.os_label == 'linux' + shell: bash + run: sudo apt-get -o Acquire::Retries=3 update + - name: Install bubblewrap + LXC stack (Linux only, cached) if: matrix.os_label == 'linux' uses: awalsh128/cache-apt-pkgs-action@v1 @@ -80,19 +85,74 @@ jobs: # env var for the same reason (compounded by 1ES Hosted Pool # egress filtering). packages: bubblewrap lxc lxc-utils dnsmasq-base iptables bridge-utils - version: 1.3 + version: 1.4 + + - name: Verify or repair Linux containment dependencies + if: matrix.os_label == 'linux' + shell: bash + run: | + set -euo pipefail + + packages=( + bubblewrap + lxc + lxc-utils + dnsmasq-base + iptables + bridge-utils + ) + + missing=() + for package in "${packages[@]}"; do + if [ "$(dpkg-query --show --showformat='${db:Status-Abbrev}' "$package" 2>/dev/null || true)" != "ii " ]; then + missing+=("$package") + fi + done + + if [ "${#missing[@]}" -ne 0 ]; then + echo "::warning::Cached dependency installation was incomplete; repairing: ${missing[*]}" + + # Runner images can have package indexes that reference versions + # already removed from the Ubuntu mirrors. Refresh and retry the + # complete install so a transient 404 cannot leave a green setup + # step with no containment packages installed. + for attempt in 1 2 3; do + sudo apt-get -o Acquire::Retries=3 update + if sudo env DEBIAN_FRONTEND=noninteractive \ + apt-get -o Acquire::Retries=3 install -y "${packages[@]}"; then + break + fi + + if [ "$attempt" -eq 3 ]; then + echo "::error::Failed to install Linux containment dependencies after $attempt attempts" + exit 1 + fi + + echo "::warning::Dependency installation failed; refreshing package indexes and retrying" + sleep $((attempt * 5)) + done + else + echo "Linux containment dependencies restored successfully from cache" + fi + + command -v bwrap + command -v lxc-start + dpkg-query --show --showformat='${binary:Package}=${Version}\n' "${packages[@]}" - name: Start LXC services (cache restore skips postinst hooks) if: matrix.os_label == 'linux' shell: bash run: | + set -euo pipefail + # cache-apt-pkgs-action restores package files but does not # re-run postinst hooks on cache hit, so AppArmor profiles # (lxc-container-default) and the lxc-net bridge service may # not be active. Load/start them explicitly so lxc-start # doesn't abort with an AppArmor denial. - sudo apparmor_parser -rT /etc/apparmor.d/lxc* 2>/dev/null || true - sudo systemctl start lxc-net 2>/dev/null || true + sudo apparmor_parser -rT /etc/apparmor.d/lxc* + sudo systemctl start lxc-net + sudo systemctl is-active --quiet lxc-net - name: Restore execute permission on mxc-exec-mac if: matrix.os_label == 'macos' From 9420cef86e9daab58f3a98e42c60caace0398f72 Mon Sep 17 00:00:00 2001 From: "Richie Gomez (he/him)" Date: Fri, 7 Aug 2026 09:47:44 -0700 Subject: [PATCH 2/3] Preserve apt cache fast path Validate the commands restored by cache-apt-pkgs-action instead of querying dpkg state, which the action intentionally does not restore. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 52e48fee-23e1-4b05-803c-522812fcdda2 --- .../workflows/SDK.Integration.Test.Job.yml | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/SDK.Integration.Test.Job.yml b/.github/workflows/SDK.Integration.Test.Job.yml index 551df4ce7..b6f0f2144 100644 --- a/.github/workflows/SDK.Integration.Test.Job.yml +++ b/.github/workflows/SDK.Integration.Test.Job.yml @@ -102,15 +102,24 @@ jobs: bridge-utils ) - missing=() - for package in "${packages[@]}"; do - if [ "$(dpkg-query --show --showformat='${db:Status-Abbrev}' "$package" 2>/dev/null || true)" != "ii " ]; then - missing+=("$package") + required_commands=( + bwrap + lxc-start + lxc-create + dnsmasq + iptables + brctl + ) + + missing_commands=() + for command in "${required_commands[@]}"; do + if ! command -v "$command" >/dev/null 2>&1; then + missing_commands+=("$command") fi done - if [ "${#missing[@]}" -ne 0 ]; then - echo "::warning::Cached dependency installation was incomplete; repairing: ${missing[*]}" + if [ "${#missing_commands[@]}" -ne 0 ]; then + echo "::warning::Cached dependency installation was incomplete; missing commands: ${missing_commands[*]}" # Runner images can have package indexes that reference versions # already removed from the Ubuntu mirrors. Refresh and retry the @@ -135,9 +144,9 @@ jobs: echo "Linux containment dependencies restored successfully from cache" fi - command -v bwrap - command -v lxc-start - dpkg-query --show --showformat='${binary:Package}=${Version}\n' "${packages[@]}" + for command in "${required_commands[@]}"; do + command -v "$command" + done - name: Start LXC services (cache restore skips postinst hooks) if: matrix.os_label == 'linux' From fc3bf6a69cfc69908d85d2cf9166c32721c38476 Mon Sep 17 00:00:00 2001 From: "Richie Gomez (he/him)" Date: Fri, 7 Aug 2026 10:11:21 -0700 Subject: [PATCH 3/3] Complete Linux setup failure handling Use the top-level LXC AppArmor profile, reload systemd units after cache restoration, retry package index failures, and ensure cache action failures flow into explicit verification and repair. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 52e48fee-23e1-4b05-803c-522812fcdda2 --- .../workflows/SDK.Integration.Test.Job.yml | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/.github/workflows/SDK.Integration.Test.Job.yml b/.github/workflows/SDK.Integration.Test.Job.yml index b6f0f2144..e08dcee69 100644 --- a/.github/workflows/SDK.Integration.Test.Job.yml +++ b/.github/workflows/SDK.Integration.Test.Job.yml @@ -61,10 +61,26 @@ jobs: - name: Refresh Linux package indexes if: matrix.os_label == 'linux' shell: bash - run: sudo apt-get -o Acquire::Retries=3 update + run: | + set -euo pipefail + + for attempt in 1 2 3; do + if sudo apt-get -o Acquire::Retries=3 update; then + exit 0 + fi + + if [ "$attempt" -eq 3 ]; then + echo "::error::Failed to refresh Linux package indexes after $attempt attempts" + exit 1 + fi + + echo "::warning::Package index refresh failed; retrying" + sleep $((attempt * 5)) + done - name: Install bubblewrap + LXC stack (Linux only, cached) if: matrix.os_label == 'linux' + continue-on-error: true uses: awalsh128/cache-apt-pkgs-action@v1 with: # Installs the LXC + Bubblewrap substrate the SDK integration @@ -126,9 +142,9 @@ jobs: # complete install so a transient 404 cannot leave a green setup # step with no containment packages installed. for attempt in 1 2 3; do - sudo apt-get -o Acquire::Retries=3 update - if sudo env DEBIAN_FRONTEND=noninteractive \ - apt-get -o Acquire::Retries=3 install -y "${packages[@]}"; then + if sudo apt-get -o Acquire::Retries=3 update && + sudo env DEBIAN_FRONTEND=noninteractive \ + apt-get -o Acquire::Retries=3 install -y "${packages[@]}"; then break fi @@ -159,7 +175,8 @@ jobs: # (lxc-container-default) and the lxc-net bridge service may # not be active. Load/start them explicitly so lxc-start # doesn't abort with an AppArmor denial. - sudo apparmor_parser -rT /etc/apparmor.d/lxc* + sudo apparmor_parser -rT /etc/apparmor.d/lxc-containers + sudo systemctl daemon-reload sudo systemctl start lxc-net sudo systemctl is-active --quiet lxc-net