
DEV Community
A space to discuss and keep up software development and manage your software career
dev.to
A space to discuss and keep up software development and manage your software career
dev.toTimed out while enabling automation mode, and the phone's own log says the daemon "requires authentication to enable automation mode". One morning all nine lanes dropped at once and stayed down until someone walked to the rig. Two things helped: - Settings > Developer > Enable UI Automation, switched on by hand once per phone. - A watcher that runs every 30 minutes, stays silent when healthy, and when lanes are down with posts overdue it names the blocker (Mac screen locked, phone with no USB session, passcode) for a human. Our agents never answer a Trust or passcode prompt. That is a person's job on purpose. ## 6. The fix itself was too loose Two of the fixes above went onto the rack, then an independent review found the first versions accepted too much. We reworked both. The lesson we wrote down: review before you install on the machine that is posting, not after. ## The audit that caught all of it One script, run for any date range: - planned posts against done posts, per phone and per account - every miss listed with its cause - "done" YouTube rows checked against the public channel feed - "unknown" TikTok rows checked against the public profile Three days in early October came back 159 of 165 live. After the fixes, the next full day was 61 of 62. The six misses were the interesting part, because each one was a green run. ## If you automate real devices - Verify against the public result, not your own log. - Count per account or per tenant, not per device. - Treat system alerts as a separate layer from the app. - Take proofs before the action that changes the screen. - Decide in advance which prompts only a human may answer. We packaged the poster as Foundry: a Mac app, a CLI and an agent skill, running on your own iPhones and your own accounts. 7 days free: https://runfoundry.app If you run device automation at any scale, what was your worst green run?sbx, Sandboxes, and Kits. AI agents are basically overprivileged potential attackers. As they develop our code, they need access to Docker and other services, and putting them in a Docker container is not enough: privileged Docker in Docker weakens the isolation between the container and the host, and mounting the host's Docker socket is worse. That hands the container direct control over the host's Docker daemon. Security risks around both are covered in Chapter 5, "Docker-in-Docker," of Docker and Kubernetes Security. That's why Docker introduced Sandboxes: a microVM-based isolation environment for running untrusted workloads, and by untrusted workloads, I mean AI agents. But the agents still need to access external services, some directories on the host, and some credentials. How do we define what they can access? Enter Docker Sandbox Kits. On September 24, Docker published the open-source Sandbox Kit Specification v3.1 Here's what a Kit descriptor looks like in practice: part of the gh mixin, which gives an agent the GitHub CLI. # gh.yaml — part of the GitHub CLI mixin's descriptor capabilities: - type: com.docker.sandbox/network-policy@2 config: runtime: allow: - github.com - hosts: [api.github.com] methods: [GET, HEAD, POST, PATCH, PUT, DELETE] deny: - hosts: [api.github.com] methods: [DELETE] paths: [/repos/**] - type: com.docker.sandbox/credential@1 optional: true config: service: github phase: runtime apiKey: name: GH_TOKEN proxyManaged: true inject: - { domain: api.github.com, header: Authorization, format: 'Bearer %s' } It reads like a Dockerfile, except it declares requested authority instead of software: the Kit requests access to GitHub, but asks for DELETE requests under /repos/** to be denied, and asks to never see the real GH_TOKEN. A Kit is an ordinary OCI image: the layers are its content, and the descriptor above becomes a single manifest annotation. That's why you can build, scan, sign, and digest-pin a Kit with tooling you already run. If you want to try this yourself, e.g., running a sandbox, composing a published Kit, then building this exact mixin from source, I wrote a step-by-step tutorial with a companion repository: docker-sandbox-kits-tutorial There are two kinds of Kits: - Workload: The base software that runs inside the sandbox, such as a coding agent. - Mixin: An overlay like the one above — credentials, network rules, or tools layered onto a workload. A runtime can compose one workload with multiple mixins. ### What Does That Mean for Security? The gh Kit above requests access to GitHub only, requests that DELETE requests under /repos/** be denied, and requests that the agent never hold the real GH_TOKEN: the proxy injects it into authorized requests instead. Useful capabilities, without unrestricted access. But those are requests, not guarantees. The Kit does not enforce anything by itself. The OCI annotation is metadata; a conforming runtime must enforce, reject, or skip those requests according to the specification. Docker Sandboxes is the first such runtime, and Docker is taking the specification toward CNCF governance, though it's still experimental.2 My takeaway: Dockerfiles made application packaging reproducible. Kits aim to do the same for the authority an application requests. ## 🧟 Mini Shai-Hulud: The Zombie GitHub Actions Remember Mini Shai-Hulud? mini-shai-hulud-attack In May, the worm compromised several developer tools, including two GitHub Actions: actions-cool/issues-helper and actions-cool/maintain-one-comment. GitHub disabled the compromised repositories on May 19, stopping workflows from downloading their malicious code. Problem solved? Not quite. According to Socket, both repositories became accessible again on September 16, with their malicious release tags still intact.3 Any downstream workflow referencing those tags could execute the payload again. For issues-helper alone, GitHub's dependency graph showed approximately 15,000 dependent repositories. That does not mean all 15,000 were compromised, but it illustrates the potential exposure. The attacker didn't need to compromise anything again. The original payload was still waiting. Fortunately, both repositories were disabled again on September 25. ### What Can We Learn? GitHub Actions referenced through version tags aren't immutable. For example, uses: example/action@v1 can resolve to different code if someone moves the tag. Pinning an Action to a verified, clean, full commit SHA prevents that particular attack path. Of course, pinning a malicious commit doesn't magically make it safe. And remember to audit the permissions and secrets available to your workflows. The SIP example workflow pins every third-party Action to a commit SHA and scopes its permissions: block to exactly what the job needs, for this reason. sip The zombie needed no new attack. It only needed someone to reopen the door. For the full Shai-Hulud family tree and the trust assumption each worm broke, see the taxonomy of modern supply-chain worms. taxonomy-of-modern-supply-chain-worms ## 🛡️ Docker Hardened Images: Bring Your Own Security Policy Docker has also published the security policies used to evaluate Docker Hardened Images. What makes this interesting is that you can evaluate your own container images against the same policy requirements.4 The policies include checks for non-root execution, vulnerability remediation deadlines, malware and secret-scan attestations, and signed SBOM and provenance attestations. You can evaluate an image with Docker Scout. Try it against any image you already have pulled, public or private: docker login docker scout policy my-app:latest --policy-bundle dhi/policies:latest docker scout ships with Docker Desktop, so there's nothing extra to install if you already have that. Standalone Docker Engine users need the Scout CLI plugin separately. The policy bundle itself is pulled and cached by digest on first use, so re-running the command doesn't re-download it. To enforce the same check in CI and fail the build on violations, add exit-code: true to the Scout GitHub Action: - name: Evaluate DHI policies uses: docker/scout-action@2688993af7bafd6ba8c6a74ec652442be91dd82b # v1.23.1 with: command: policy image: my-app:${{ github.sha }} policy-bundle: dhi/policies:latest exit-code: true The policy bundle is distributed as an OCI artifact, with its source available as Rego policies. A failing result doesn't necessarily mean your image contains malware. For example, it might simply be missing a required scan attestation. This distinction matters: evidence of security checks is not the same as proof that software is secure. Nevertheless, having reusable policies that can run locally or in CI is a useful development. ## GitHub Actions Gets More Granular Cache Permissions On September 10, GitHub also introduced cache-mode, a generally available mechanism for controlling GitHub Actions cache access at the workflow or job level.5 It supports read, write, write-only, and none. Set it per job, right next to runs-on: jobs: build: # trusted: needs to save the cache for later jobs runs-on: ubuntu-latest cache-mode: write lint-pr: # untrusted: runs on pull_request, only ever restores runs-on: ubuntu-latest cache-mode: read GitHub already defaults cache access to read-only for low-trust triggers like pull_request_target. The event still runs in the trusted base-repository context and can have access to secrets and a read/write token; only its cache access defaults to read-only. The point of setting cache-mode explicitly is to stop relying on that default: a job that genuinely never needs to save a cache can't poison one, even if someone widens its trigger later without noticing the cache implications. After the supply-chain attacks we have covered in previous issues, this is a welcome addition. ## 🎨 GlassWorm: Even Your VS Code Theme Can Be Malicious An early-October addition to this issue. On October 2, Socket reported a cluster of suspicious VS Code and Open VSX theme extensions connected to previously identified malware. The investigation identified at least two confirmed malicious extensions and linked one to GlassWorm with high confidence.6 The malicious extension used obfuscated JavaScript and a staged loader to retrieve further payloads. The broader cluster also contained apparently harmless extensions sharing development or publishing characteristics with the malicious ones. Not every extension in the cluster was confirmed to be malicious. This illustrates another uncomfortable fact about developer environments: a VS Code theme isn't necessarily just colors. Extensions may execute JavaScript with access to developer resources. Your editor is part of your software supply chain. Review installed extensions, remove those you no longer need, and pay attention to their publishers and updates. Start with a full inventory, which takes one command: code --list-extensions --show-versions For each theme or extension you don't immediately recognize, check its Marketplace listing for a verified-publisher badge and an actual install count, not just a plausible name. A theme published last month with a few hundred installs and no verification badge deserves more scrutiny than one with a decade of history. Apparently, even going dark mode requires a threat model. 🌑 ## 🎙️ Recent Work ### 🐳 Docker Captains Summit 2026 I spent the end of September in Cancún, Mexico, meeting Docker Captains from around the world. You can see them in this photo from the summit: So, as you can see, Docker is going dark mode. But, we don't have cookies. 🍪 To celebrate the dark mode, Docker is also giving away $250 in sbx cloud credit to new sign-ups, through October 31, 2026, credit card required. Claim it here. ### 📚 Black Forest Commandos: Asgard Mission The Commandos finally have their own graphic novel! Black Forest Commandos: Asgard Mission brings the characters from my DevSecOps workshops into a new adventure inspired by Norse mythology. The current version is purely narrative, and feels like Anton Chekhov meets Mortal Kombat with DLCs. Get the PDF here for free. ### 🇨🇭 Coming Up: BaselOne On October 15, I'll be speaking at BaselOne in Switzerland. My talk, Dockerize Java Securely: SBOMs + Attestations + Cosign, covers container supply-chain security for Java applications, including BuildKit-generated SBOMs, provenance, and image signing. If you're attending, come say hello! ## Until Next Time Our software supply chain now includes dependencies, build workflows, IDE extensions, and autonomous agents. Some of these tools can execute arbitrary code. Others hold credentials or decide what to do next. The common challenge is not simply identifying what we trust. It's controlling how much authority that trust grants. Until next time, pin your Actions, review your permissions, and watch out for the zombie worms. And remember: the dark side doesn't always have cookies. 🍪🧟 1. Christian Dupuis. "From Dockerfile to Kit: The Docker Sandboxes Kit Specification." Docker, September 24, 2026. See also the Sandbox Kit Specification repository. ↩ 2. Eli Aleyner and Srini Sekaran. "Docker and CNCF Partner on an Open Spec for Agent Permissions." Docker, September 24, 2026. ↩ 3. Karlo Zanki. "Re-Enabled GitHub Actions Expose Thousands of Repositories to Mini Shai-Hulud." Socket, September 24, 2026; updated September 25. ↩ 4. Docker Docs. "Apply Docker Hardened Image Policies to Your Images." ↩ 5. GitHub. "Control GitHub Actions Cache Access with cache-mode." September 10, 2026. ↩ 6. Kirill Boychenko. "Pretty Themes, Hidden Loaders: GlassWorm-Linked Extensions." Socket, October 2, 2026. ↩gemini-3.8-flash and includes a deterministic fallback when the model is unavailable. The repository's project description mentions Gemma 4, so the exact model used in the final deployed version should be verified before making a specific Gemma 4 implementation claim. ### Render We deployed CampusCare on Render to make the project accessible through a public URL. Deployment made it easier to demonstrate the complete user experience instead of asking everyone to run the project locally. The repository also includes a Render Blueprint configuration to support deployment. ## Hackathon Experience Hackathons encourage us to move quickly from an idea to something people can actually try. But building a working application also means thinking about the less obvious parts: what happens after a report is submitted, how different users access the system, how repairs are verified, and what should happen when an AI result is uncertain. CampusCare gave us a practical way to explore those questions. One lesson I am taking away is that adding AI is not enough by itself. The surrounding workflow matters just as much. A useful system needs clear responsibilities, predictable state transitions, validation, and a way to handle uncertainty instead of pretending every result is correct. I also learned to think beyond the local development environment. Making a project accessible online changes how we can demonstrate it, gather feedback, and identify what still needs improvement. CampusCare is a starting point, not a finished production system. There is still room to improve persistent storage, reliability, and the AI integration. But building it helped turn an everyday campus problem into a concrete engineering project. I hope this project encourages more developers to look at ordinary problems around them and explore how thoughtful software and AI-assisted workflows can help solve them. Thanks to the MLH and DEV communities for giving builders a place to share what they create and learn from one another.