esbuild, mise, Tomcat, Radius, and late TYPO3 boundary checks¶
Source: hourly offensive-security scan, 2026-06-12, updated 2026-06-22 for the .tool-versions mise follow-up, 2026-06-29 for the Tomcat HTTP/0.9 constraint-bypass follow-up, and 2026-07-01 for the Tomcat RewriteValve session-fixation follow-up. Primary entries: GitHub advisories GHSA-gv7w-rqvm-qjhr, GHSA-g7r4-m6w7-qqqr, GHSA-fjj5-v948-whjj / CVE-2026-33646, GHSA-436v-8fw5-4mj8 / CVE-2026-35533, GHSA-fpj8-gq4v-p354 / CVE-2025-66614, GHSA-fp5j-4fj2-4jvq / CVE-2026-53999, Tomcat advisories GHSA-qq5r-98hh-rxc9 / CVE-2026-24733 and GHSA-23hv-mwm6-g8jf / CVE-2025-55668, and late TYPO3 advisories GHSA-pjpj-v387-x4vq / CVE-2026-11607, GHSA-jh32-v29g-68pq / CVE-2026-49741, GHSA-hwvq-2w67-rvxp / CVE-2026-47346, GHSA-3v8v-4wg6-r7qh / CVE-2026-47343, GHSA-f34x-rx2w-7pm3 / CVE-2026-47349, GHSA-qcmw-6rm2-5x78 / CVE-2026-47350, and GHSA-3p42-w5ch-gg42 / CVE-2026-47347.
This batch is durable because each item exposes a reusable operator boundary: build tooling that converts registry environment variables into executable native binaries, developer servers that normalize paths differently from their host OS, repository-local tool config that can approve its own trust state, TLS SNI/HTTP Host split-brain authentication, HTTP-version/method parsing that crosses servlet security constraints, Kubernetes controller confused-deputy deletes across tenants, and TYPO3 backend permissions crossing into SQL-capable form definitions or unauthorized record/file operations.
What changed¶
- esbuild Deno binary integrity boundary — the Deno module fetched native binaries from
NPM_CONFIG_REGISTRYand wrote executable files without the SHA-256 integrity checks used by the Node installer path. This is a CI, shared dev-host, and private-registry trust boundary, not a generic browser issue. - esbuild Windows dev-server file boundary — the development server used POSIX-style
path.Clean()on request paths while Windows treats backslashes as path separators, enabling traversal out ofservediron affected Windows hosts. - mise project-local trust boundary — local
.mise.tomlsettings could be loaded before trust checks, allowing repository-controlled settings such astrusted_config_paths = ["/"]to make that same untrusted project config appear trusted and reach hooks, tasks, templates, or[env] _.source. A June 22 follow-up adds a separate.tool-versionsparser boundary where Tera template rendering, includingexec(), ran without a trust prompt in non-paranoid mode. - Tomcat connector mTLS virtual-host boundary — when client certificate authentication was enforced only at the connector, Tomcat virtual hosts with different TLS requirements could be confused by sending one host in TLS SNI and another in the HTTP
Hostheader. - Tomcat HTTP/0.9 security-constraint boundary — Tomcat accepted non-
GETHTTP/0.9 request lines. In applications where a servlet security constraint allowedHEADbut deniedGETfor the same URI, a specification-invalid HTTP/0.9-styleHEAD /pathrequest could reach theGET-protected resource boundary. - Tomcat RewriteValve session identifier boundary — RewriteValve redirects and cross-context rewrites did not consistently run through the same session URL-encoding and session-info recycling path that normal redirects use. In cookie-less or URL-rewritten session deployments, this can let an attacker-controlled session identifier survive a rewrite/redirect boundary instead of being regenerated or bound to the expected context.
- Radius controller confused-deputy boundary — in multi-tenant installs, a tampered
radapp.io/statusDeployment annotation could cause the controller to delete a container resource referenced under another tenant/resource group using controller privileges. - TYPO3 form, file-mount, and record-control follow-up wave — late TYPO3 advisories add Form Framework extension/case bypasses that can reach SQL-capable form definitions, direct
DataHandlerwrites toform_definition, unauthorized record moves/restores, destructive operations on file-mount roots, and a core utility open-redirect boundary.
Operator triage¶
- Lead with preconditions. esbuild requires Deno module execution plus registry/environment influence; the file-read variant is Windows dev-server only; mise requires a repo or working tree the tester can place files in and a shell/editor/CI path that invokes mise hooks or parsing; Tomcat mTLS testing requires connector-level client cert auth and multiple virtual hosts with different requirements; Tomcat HTTP/0.9 testing requires a security constraint that allows
HEADbut deniesGETon the same URI; Tomcat session-fixation testing requires RewriteValve plus URL-based session tracking, cookie-less clients, or an application flow wherejsessionidURL rewriting is intentionally supported; Radius is strongest in multi-tenant controller topologies; TYPO3 requires backend roles, file-write, module, or table-write access. - Separate proof of boundary from destructive impact. A downloaded inert binary canary, file-read marker, hook marker, mTLS route differential, HTTP/0.9 method/constraint decision table, synthetic URL-session marker, synthetic Radius container ID, or disposable TYPO3 form definition is enough. Do not execute production payloads, read secrets, hijack live user sessions, delete real tenant resources, or create real admin accounts.
- Favor environment and parser-differential evidence. Capture the exact environment variable, path separator, trust setting, SNI/Host pair, raw request line, RewriteValve rule/redirect pair, Kubernetes annotation field, or TYPO3 module/table/extension check that made the boundary fail.
Replayable validation boundaries¶
esbuild registry-to-executable validation¶
- Scope only CI runners, build images, or developer hosts where running the esbuild Deno module is authorized.
- Set
NPM_CONFIG_REGISTRYto a tester-controlled local registry or HTTP callback that serves an inert tarball matching the expected package path and platform name. - Positive proof is that the Deno installer downloads from the canary registry and writes/attempts to execute a tester-owned marker binary without an integrity mismatch.
- Keep the binary inert: print a marker, write a disposable file under a temp directory, or exit with a unique code. Do not run shell download cradles or credential access commands.
- Evidence: esbuild version, Deno invocation, redacted environment, requested registry URL, marker result, and patched
v0.28.1+negative control.
esbuild Windows servedir traversal validation¶
- Validate only against a local or lab Windows dev-server instance; do not expose production dev servers to the internet for testing.
- Create a harmless marker file outside
servedir, then request a URL path containing Windows backslash traversal segments toward that marker. - Positive proof is retrieval of the marker file and a negative control showing normal forward-slash normalization stays confined.
- Evidence should include OS, esbuild version,
servedir, sanitized request path, marker file contents, and patched negative behavior.
mise repository-config trust validation¶
- Use a disposable repository and a canary
.mise.toml; avoid testing against developer home directories or repositories with real hooks/secrets. - Place a local config that sets a trust-expanding setting such as
trusted_config_pathsand an inert[env] _.source, hook, task, or template marker. - Trigger only a safe command path such as
mise hook-envin a sandboxed shell and confirm whether the marker executes before explicit user trust is granted. - Evidence: mise version, repository path,
.mise.tomltrust stanza, command used, canary marker, and patched-version behavior.
mise .tool-versions Tera execution validation¶
- Validate only in a disposable repository and sandbox shell. Do not run this in a real developer checkout, home directory, or environment carrying live cloud, package-registry, SSH-agent, or API credentials.
- Create a
.tool-versionsfile with the smallest inert Tera marker that proves template evaluation. Prefer a temp-file marker over network callbacks:
- Trigger a safe mise parse path such as
mise hook-envor the same shell activation path the target workflow uses. Avoid package installs, build scripts, or commands that execute project code for unrelated reasons. - Positive proof is the marker appearing before any explicit trust approval for the repository and without a
.mise.tomltrust prompt. Pair it with a patched-version negative control where possible. - Evidence: mise version, shell integration path,
.tool-versionscontents, command used, marker file metadata, and confirmation that the repo was untrusted/non-paranoid. Redact environment output; do not demonstrate token access even if the advisory notes inherited environment exposure.
Tomcat SNI/Host mTLS bypass validation¶
- Confirm a lab or customer-approved Tomcat deployment has at least two virtual hosts on the same connector: one requiring client certificates and one not, with client certificate auth enforced at the connector rather than inside the web application.
- Send one TLS SNI value for the non-client-cert host and an HTTP
Hostheader for the client-cert-protected host. Use an owned route that returns a marker page, not a sensitive application endpoint. - Positive proof is access to the protected virtual host without presenting a client certificate, paired with controls where matching SNI/Host values behave as expected.
- Evidence: Tomcat version, connector/vhost layout, SNI,
Host, client-cert presence/absence, marker route status, and patched version negative behavior.
Tomcat HTTP/0.9 method constraint validation¶
- Validate only on a lab or explicitly authorized Tomcat application where you can create or identify a harmless URI with split method constraints:
GETdenied andHEADallowed. Do not use real admin, export, backup, or user-data routes as proof targets. - First prove the intended controls with normal HTTP/1.1 requests:
GET /canary HTTP/1.1should be rejected andHEAD /canary HTTP/1.1should follow the configuredHEADpolicy. - Send a raw HTTP/0.9-style request line for the same marker URI using
HEAD /canarywith no HTTP version token. Positive proof is a response/body/status behavior that reaches the resource path despite theGETdenial, paired with a patched Tomcat negative control. - Capture raw bytes and parser outcomes rather than sensitive content. A synthetic route that returns a marker header/body is enough.
- Evidence: Tomcat version, connector, security-constraint snippet, URI, raw HTTP/1.1 and HTTP/0.9 request lines, response decision table, and fixed-version behavior for 9.0.113+, 10.1.50+, or 11.0.15+.
Tomcat RewriteValve session-fixation validation¶
- Validate only on a lab or explicitly approved Tomcat application where you control the test account, can enable URL-based session tracking, and can place a harmless RewriteValve rule that redirects or internally rewrites between synthetic routes. Do not test against real login, admin, payment, or customer-account flows.
- Create two canary routes: one route that establishes a test session and one route behind the rewrite or redirect boundary that reports only a synthetic session marker such as
skillz-session-canary, never usernames, cookies, roles, or application data. - With cookies disabled, send a URL containing a tester-chosen
;jsessionid=<canary>or follow the application-generated URL rewriting path through the RewriteValve rule. Positive proof is that the pre-fix RewriteValve path preserves or accepts the session identifier across the redirect/rewrite where the patched path either re-encodes the redirect with the expected session id, recycles cross-context session state, or rejects the attacker-supplied session boundary. - Pair every positive result with controls: normal non-RewriteValve redirects, cookie-enabled requests, a fresh session after authentication, and a patched 9.0.106+, 10.1.42+, or 11.0.8+ build when available.
- Evidence: Tomcat version, session tracking mode, RewriteValve rule, sanitized request URL,
Locationheader or internal-rewrite target, canary session-id decision table, and fixed-version behavior. Do not publish reusable victim-session fixation links.
Radius controller annotation confused-deputy validation¶
- Validate only in a lab or explicitly approved multi-tenant Radius/Kubernetes environment with disposable tenants, resource groups, Deployments, and container resources.
- Create two synthetic tenants/resources and tamper only the attacker-controlled Deployment's
radapp.io/statusannotation to reference a victim canary container resource. - Trigger the reconcile/delete flow and verify whether the controller attempts to delete the referenced canary resource.
- Stop at canary deletion/attempt evidence. Do not target production containers, shared namespaces, service accounts, or non-test resource groups.
- Evidence: Radius version, controller scope/RBAC, tenant/resource IDs, sanitized annotation JSON, controller log/API delete attempt, and recovery/cleanup.
TYPO3 late-wave validation¶
- For Form Framework extension and
DataHandlerissues, use a disposable backend user and a synthetic form definition that executes only a harmless SQL canary such as creating or updating a marker row in a lab table. Do not create administrative users on production systems. - For file-mount root operations, prove attempted rename/move/delete only against a disposable mount root in a lab; prefer observing authorization acceptance/rejection rather than performing destructive operations.
- For Recycler and record-move checks, use synthetic pages/tables and marker records where source/target permissions are intentionally split.
- For
sanitizeLocalUrl, demonstrate only a redirect to a tester-owned URL and never use phishing pages or user-targeted links. - Evidence should include TYPO3 version, backend role, module/table/file permission, canary object, route/API used, and patched-version negative behavior.
Reporting heuristics¶
- Name the crossed trust boundary in the title:
NPM_CONFIG_REGISTRY to native binary execution,Windows dev-server backslash traversal,repo config self-trust,.tool-versions Tera template to shell execution,SNI/Host mTLS mismatch,HTTP/0.9 HEAD to GET-denied route,RewriteValve redirect to URL-session fixation,Deployment annotation to cross-tenant delete, orbackend form/file permission to SQL/admin-capable action. - Keep impact scoped to the proven precondition. These are strong findings when the report preserves topology and role requirements instead of claiming blanket RCE, auth bypass, or tenant takeover.
- Redact environment values, client cert material, Kubernetes tokens, registry credentials, and application secrets. Canary evidence should be enough.
Notes on skipped adjacent items¶
The same scan rechecked Disclosed, PortSwigger, Trail of Bits, ProjectDiscovery, GitHub advisory published/updated feeds, GitHub Security Blog, and CISA KEV. PyO3 memory-safety advisories, pypdf resource-consumption items, Tomcat cleanup/input-validation or resource-exhaustion updates unrelated to security-constraint, RewriteValve URL-session, or SNI/Host client-certificate boundaries, and duplicate/adjacent TYPO3 sanitizer XSS entries were tracked but not promoted because they do not add a higher-signal replayable operator workflow than the trust, parser, session, controller, and backend authorization boundaries above. The July 1 GitHub Security Blog maintainer-settings post was tracked but not promoted because it is primarily defensive configuration guidance. No new PortSwigger, Trail of Bits, ProjectDiscovery, Disclosed, or CISA KEV item in this hour added additional durable guidance.
June 23 mise HTTP-backend symlink update¶
GitHub Advisory Database added GHSA-f94h-j2qg-fxw3 / CVE-2026-54557 for a separate mise package-install boundary: the HTTP backend used the raw requested version path when creating the install symlink destination. That makes repository, task, or operator-supplied version strings filesystem material rather than inert package selectors.
Operator value: treat package-manager version fields as write-path inputs. This is adjacent to the existing mise repo-trust and .tool-versions guidance because the useful proof is not generic command execution; it is whether an untrusted project can steer mise's install/cache layout outside the expected tool directory.
Safe validation boundaries:
- Use only a disposable repository, temporary
MISE_DATA_DIR, and a fake HTTP backend/tool definition under tester control. - Request one baseline version and one traversal-looking version string that should be rejected before symlink creation. Evidence should be a before/after tree rooted under the temp mise data directory and the resolved symlink target.
- Do not point the symlink at shell startup files, SSH material, package-manager config, real tool shims, or developer home directories.
- Negative controls: version identifiers canonicalized before path join, final symlink destination confined under the tool install root, and patched mise refusing absolute paths,
.., slash, or platform-specific separator variants.
Reporting heuristic: title this as HTTP backend version string to install symlink path, include the backend type, mise version, temp data root, resolved path table, and patched rejection behavior.
June 23 mise local credential and task-include updates¶
GitHub Advisory Database added two more mise repository-trust boundaries: GHSA-29hf-rm4x-xxph / CVE-2026-55448 for local [settings.github] credential_command execution before a trust decision, and GHSA-77g9-363w-rccq / CVE-2026-55441 for task-include files that render Tera exec() fields in an untrusted, config-less repository.
Operator value: mise testing should now cover three independent local-repo paths, not just .mise.toml self-trust or .tool-versions: local GitHub credential helper to shell, task metadata/template fields to shell, and HTTP backend version string to symlink path. All three are high-signal in developer workstation, CI, and agent-runner assessments where opening or listing an untrusted repository can invoke tooling.
Safe validation boundaries:
- Use a disposable repository, temporary
MISE_DATA_DIR, clean shell profile, and fake GitHub token flow. Do not run in a checkout that has real cloud, package-registry, SSH-agent, or API credentials. - For
credential_command, set only an inert command that writes a marker under a temp directory, then trigger a GitHub-token resolution path where higher-priority token environment variables are intentionally absent. Evidence is command invocation and marker creation, not environment dumping. - For task includes, create a config-less repository with a single task file under
mise-tasks/or.mise/tasks/containing a harmless Tera marker in a rendered field. Trigger only read-only listing/completion paths such asmise tasksormise task ls. - Negative controls: local settings ignored until trust is granted, task include files gated by the same trust checks as config files, Tera
exec()unavailable in untrusted task metadata, and token helpers restricted to user/global config.
Reporting heuristic: title findings by the exact trigger, for example local credential_command to shell before trust or untrusted task include Tera field to shell on task listing. Include mise version, repository layout, command used, temp marker path, and patched rejection behavior.
September 17 flatpak-builder Git-hook build-host update¶
GitHub Advisory Database added GHSA-rvpr-5p35-6vf8 / CVE-2026-86320: when flatpak-builder applies patch sources with use-git-am: true, it runs Git without disabling hooks, so a malicious source containing a Git post-applypatch hook executes on the host as the user running flatpak-builder during the build.
Operator value: this is the repository-trust family again, reached through a build wrapper rather than a dotfile parser. The generalizable audit rule: any tool that shells out to Git over attacker-supplied content — git am, git apply, git checkout, git merge, archive-to-repo materializers, CI checkout actions, package patchers — executes repository-internal .git/hooks/* unless the caller passes -c core.hooksPath=/dev/null, --no-verify, or an equivalent. Repository content that is nominally "data" (a patch source in a manifest) becomes host code execution because the hook lives inside the delivered object, not in a config file the tool parses.
Safe validation boundaries:
- Disposable checkout only: a tester-controlled source repo or module directory containing a
post-applypatch(andpre-applypatch/post-checkoutvariants) hook that writes a marker under a temp directory. Run flatpak-builder withuse-git-am: trueagainst a minimal manifest in a throwaway build directory. - Evidence is hook invocation and marker creation outside the sandbox; do not run network or persistence payloads.
- Negative controls: fixed flatpak-builder refusing to trigger the marker, plus confirming hooks do not fire when
core.hooksPathis redirected — this distinguishes "hooks disabled by the wrapper" from "hook never reached". - Sweep adjacent tooling with the same harness mindset (authorized CI runners, devcontainers): grep the tool source for
git am/git checkoutinvocations lacking hook suppression flags before probing.
Reporting heuristic: title as flatpak-builder use-git-am patch source post-applypatch hook to host execution; include flatpak-builder version, manifest fragment, hook name, marker path, and patched behavior. Related waves with the same shape: mise .mise.toml/credential_command self-trust above, and repository-controlled .pdm-plugins pre-parse execution.
September 17 follow-up: Snowflake CLI repo-config values interpolated into multi-statement SQL¶
GitHub Advisory Database added GHSA-p2xq-qfx5-xp6q / CVE-2026-92903 (high): in Snowflake CLI prior to 3.27.0, unsanitized user-controlled values are interpolated into SQL strings that execute as multi-statement queries. An attacker with write or pull-request access to a project repository whose CI/CD pipeline runs Snowflake CLI under an elevated service-account role — or who can supply input to CLI-wrapping automation — gets attacker-controlled SQL executed in the victim's Snowflake session and active role. Impact is bounded only by the configured role's privileges; the fix landed in 3.27.0 and requires a manual user upgrade, so pinned CI images lag the advisory.
Operator value: this is the repository-trust family crossing from shell into query structure. The generalizable audit rule: for every CLI that reads project-local configuration (.snowflake/ config, connection/project files, CLI args from repo scripts), check whether config-derived values are bound as parameters or concatenated into SQL, and whether the executor enables multi-statement mode — multi-statement execution turns one injected fragment from a subverted statement into arbitrary follow-on statements (GRANT, data exfil, object drop) under the CI role. On bug-bounty/authorized-CI engagements: a PR you can author is the write-access precondition the advisory itself names; treat any repo that runs a DB CLI in CI as a SQL-structure injection surface and diff "value bound" vs "value interpolated" in the generated query log before executing anything.
Safe validation boundaries:
- Disposable project repo + throwaway Snowflake account or a mocked/recorded request sink: plant a config value containing a statement separator and a second inert marker statement; trigger the CLI path in a temp directory. Evidence is the generated/recorded query text containing both statements, not execution against real data.
- CI-context proof uses a dedicated low-impact test role; record role name and whether the injected follow-on statement was accepted (multi-statement mode on/off is the decision to capture).
- Negative controls: fixed CLI 3.27.0 rejecting or parameterizing the same value, and confirming the vulnerable path is the repo-supplied config (not your own command line) by removing the file and re-running.
Reporting heuristic: title as Snowflake CLI repo-controlled config value to multi-statement SQL under CI role; include CLI version, config key, generated query fragment (redacted), execution role, and patched parameterization behavior. Same shape as the mise credential_command and flatpak-builder hook items above — repository content executing in whoever's context runs the tool.
September 17 follow-up: Redocly CLI split traversal and cyclonedx-npm Windows --workspace shell injection (2 GHSAs)¶
GHSA-657c-g7qc-r9j2 / CVE-2026-63225 (fixed @redocly/cli 2.33.2): an OpenAPI/AsyncAPI description can make redocly split write files outside the chosen output directory — component names and x-codeSamples lang values become path segments. The write is constrained (YAML/JSON component content, code-sample files named after the HTTP method), so it is place/overwrite at an unintended path rather than a free file-write primitive.
GHSA-q69g-4hcv-6jg4 / CVE-2026-71538 (fixed @cyclonedx/cyclonedx-npm 6.0.0): on the Windows fallback execution path, the --workspace value is interpolated into a shell command without neutralization — >, &, | metacharacters execute with the invoking user's privileges whenever automation or a repo script passes an attacker-influenced workspace name.
Operator value: both are the developer-control family reached through tooling that consumes untrusted spec/repo metadata on a workstation or CI runner — the analyst who runs redocly split on a supplied API description is the victim, exactly like the flatpak-builder hook and mise task items above. Audit rules: (1) any CLI that turns document-internal names (component names, sample lang values, artifact ids) into output paths needs a literal ../ sweep in the description before execution — Redocly's own detection advice (component names and lang values legitimately never contain path segments) generalizes to SBOM generators, scaffolders, and doc tooling; (2) any CLI flag consumed on a Windows shell-fallback path is a command-injection candidate even when the POSIX path is safe — test the same metacharacter canary on both platforms and record the divergence. Validation stays inert: a disposable spec with a ../marker component name writing into a temp tree, and a workspace value containing a marker-writing command against a throwaway directory only; never write outside the disposable root or run persistence payloads.
September 20 follow-up: Mistral Vibe executes repository post-checkout hooks before trust validation¶
GHSA-92v2-hh9v-6vj5 / CVE-2026-93993 (8.8, Mistral Vibe before 2.25.5): the worktree creation process runs Git hooks before the trust validation step. A supplied repository containing a crafted post-checkout hook executes arbitrary shell with the privileges of the user running Vibe — the "open an untrusted repo in an AI coding tool" attack becomes host code execution without any trust prompt being answered.
Operator value: this closes another leg of the flatpak-builder audit rule above — "any tool that shells out to Git over attacker-supplied content executes repository-internal .git/hooks/*" now includes git worktree add. Worktree creation fires post-checkout, and tools that clone-then-worktree (AI coding assistants, IDE workspace managers, CI checkout helpers, review bots) often invoke Git before their own repo-trust gate, so the trust UI is bypassed by ordering, not by a flaw in the gate itself. Audit rule for developer-workstation and agent-runner assessments: enumerate every Git subcommand the tool invokes during repository acquisition (clone, checkout, worktree add, submodule update, stash apply), and check whether each passes -c core.hooksPath=/dev/null / --no-verify and whether it runs before or after the trust decision. Validation: disposable repo with a post-checkout hook writing a marker under a temp directory, opened against a throwaway Vibe install; evidence is marker creation timestamped before any trust prompt interaction. Related: the agent repository-trust pages — MCP/agent tools that materialize PR-controlled repos hit the same ordering bug.
October 1 follow-up: virtualenv activation scripts execute metacharacters from paths and prompts¶
GHSA-x78j-v8h9-3j2q / CVE-2026-102937 (fixed virtualenv 21.7.12): BatchActivator.quote() returned its input unchanged — the only activator with no escaping — so --prompt, VIRTUALENV_PROMPT, or a config-file prompt is written raw into @set "VAR=value" in activate.bat. A prompt containing " closes the string early and the remainder runs as live cmd.exe syntax (virtualenv --prompt 'x" & calc & "' venv fires on activation). Anyone templating a prompt from untrusted input — a CI job using a branch name, a wrapper deriving the env name from user input — hands code execution to whoever activates the venv on Windows.
GHSA-p58f-9548-mpm2 / CVE-2026-102925 (fixed virtualenv 21.7.13): same defect class in the POSIX activators. Generated activate (bash/zsh) and activate.fish interpolate an already-shlex.quote-ed value into a template position that quotes it a second time; the doubled quoting terminates the quoted run early and leaves $(...), backticks, or ; parsed as shell code. The bash path fires through the venv's own relocated-path branch — the normal case for any venv copied or distributed to another machine — so a destination named x'$(id)'y executes on source. The fish path fires through TCL_LIBRARY/TK_LIBRARY template lines.
Operator value: two durable patterns for developer-workstation and CI supply-chain work. (1) Pre-generated shell artifacts are delivery vehicles for path/name-derived payloads. A venv directory, prompt string, or project name created by tooling becomes shell code when a human or CI script activates it — audit any template that wraps an already-escaped value in its own quotes (''-doubling inside '...', "..." around shlex.quote output), and treat shared/distributed venvs, CI matrix names, and branch-derived labels as untrusted input to the activator. (2) Quote-once-then-quote-again is the signature bug — grep generator templates for placeholder lines where the substitution site adds quotes around a value the generator already escaped. Validation: create a disposable venv with a marker-bearing directory/prompt name in an isolated container, source/activate it in a throwaway shell, and check for the marker side effect; never distribute or activate such artifacts outside the lab, and never use persistence or credential-reading payloads.
October 2 follow-up: Sapling SCM control characters in Git subtree URLs turn read-only commands into code execution¶
GHSA-g4x4-gm4c-5r8h / CVE-2026-104026 (Sapling SCM < v0.2.20260929-102736): control characters were permitted inside Git subtree URLs in a repository's stored metadata, so a maliciously constructed repository cloned by a target executes code when the target runs otherwise-read-only commands — sl log, sl blame, sl annotate. This is the repository-as-input attack in its purest form: nothing the victim does is write-capable; the repository itself carries the payload, and the trigger is ordinary history browsing.
- Durable rule for source-hosting and supply-chain assessments: repo-controlled metadata strings (remote/subtree/submodule URLs, hooks,
.gitattributesfilters/LFS commands, branch and path names with control bytes) are executed by the VCS client's own plumbing during routine operations. When authorized to assess a code-hosting platform or an internal forge, the client-side trust question — does the client sanitize stored URLs/attributes before spawning subprocesses — is in scope for review. Attack-surface enumeration for your own org: sweep shared repos for subtree/submodule URL fields and control characters (\n,\r,\b, ANSI/terminal control bytes) that downstream tools (IDEs, blame viewers, CI checkout steps, log renderers) re-parse differently. - Control-character classes to test in any VCS-tooling audit (labs with disposable repos only): newline/CR injection into argv-built command lines, terminal-control sequences aimed at log-viewer terminals (terminal escape injection — the escape-sequence twin of the ANSI page family), and encoding tricks that survive
git config-style round-trips. Proof standard: inert marker file or owned callback at the subprocess boundary; never payloads against shared clones or developer workstations. - Same trust-zone family as mise
.tool-versionsTera execution and Mistral Vibepost-checkouthooks already on this page: clone == code execution whenever a repo-controlled string reaches a parser with expression or shell semantics. The Sapling twist is that it reaches the log/blame path, not a checkout hook — auditing must cover the read paths, not just lifecycle hooks.
October 9 00:3xZ follow-up: Go toolchain trust roots were project-controlled — bogus golang.org/fips140 / golang.org/toolchain entries + a hostile GOMODPROXY swap the compiler itself (CVE-2026-94444 + CVE-2026-94447)¶
Two Go toolchain advisories (imported 2026-10-09T00:31Z) extend this page's "repository-local config is a trust decision" family to the most privileged dependency there is: the compiler you are running.
- Bogus
golang.org/fips140+ malicious GOMODPROXY GHSA-2f4j-3hgj-v9j7 / CVE-2026-94444: a project defining a fakegolang.org/fips140module, combined with a module proxy the user chose to use, could have an arbitrary module served in place of the bundled FIPS module. The fix unpacks the trusted ziphash of the bundled module to reconstruct its GOMODCACHE entry so the toolchain can verify it — i.e., before the fix the bundled module's cache entry was reconstructible from project-influenced state. - Bogus
golang.org/toolchaingo.sumentry GHSA-cgx4-3g64-rvr7 / CVE-2026-94447: a malicious project'sgo.sumentry forgolang.org/toolchainplus a malicious GOMODPROXY bypassed the checksum gate for the toolchain download. The fix forcesgolang.org/toolchainto always fetch its canonical checksum from the network — a direct admission that the checksum-of-trust was previously satisfiable from the repository itself.
Operator rules for build-infra and supply-chain assessments:
- Check the bootstrap, not just the manifest. Every toolchain selector (
go.modtoolchainlines,.tool-versions,.nvmrc,packageManagerfields, wrapper configs — this page's mise leg) answers "which binary runs my build." If the integrity reference for that binary can also come from the repo, repo-controlled input selects both the identity and the trust proof of the compiler. Audit question for any version-selector tool: where does the checksum of the downloaded toolchain come from — the repo, a lockfile with the same trust level as the repo, or an out-of-band source? - Two-condition exploits still ship for developers. Both legs need the developer to open a malicious project and use an attacker-chosen GOMODPROXY — "you must have chosen a hostile proxy" is exactly the phrasing vendors use when a proxy env var is set in shared CI images or company laptop baselines. On CI assessments, sweep build environments for
GOPROXY/GOMODCACHE-style overrides pointing at internal mirrors and test whether the mirror can swap pinned high-privilege modules; proof = marker module served from your own fake proxy on a disposable builder, never a real credential or dependency poisoning. - The
fips140sibling matters beyond compliance: the crypto-fips module gates FIPS-mode builds; swapping it is a silent downgrade oracle on compliance-critical pipelines. Inventory which of your org's builds run withGOEXPERIMENT=boringcrypto/fips tags and whether the proxy in that pipeline is third-party.
October 15 follow-up: Renovate four-leg wave — shared presets are attacker-controlled config in a privileged bot (CVE-2026-110865..110868)¶
Renovate (the dependency-update bot that runs repository-controlled config in CI/self-hosted daemons) published four advisories at 00:31Z (fixed 44.60.1 / 44.61.3 / 44.79.0). Same root family as this page's mise/esbuild legs — config assembled from externally-sourced fragments executes with the tool's privileges — but the privileged context here is a bot holding package-registry and source-host credentials:
- CVE-2026-110867 / GHSA-6mj2-rf27-53xc (critical) —
envinside a shared preset bypasses the environment-variable allowlist: repositories thatextendan attacker-controlled preset can setPATH,LD_PRELOAD,NODE_OPTIONS,GIT_SSL_CAINFOin the bot's child processes on self-hosted instances. Preset authorship ≠ config trust: every key the top-level config allowlists must be allowlisted after preset merge, not per-fragment. - CVE-2026-110865 / GHSA-6f4x-rc8m-8j8g (high) —
hostRules[].headersinside shared presets evade theallowedHeadersrestriction, injecting custom headers into requests Renovate sends to other hosts — cross-host credential-header smuggling through the bot's own requests. - CVE-2026-110868 / GHSA-h7j4-4vjp-jmxf (high) — SSRF via
extendspresets /customDatasourcespointing the shared HTTP client at internal URLs — instance metadata reachable, AWS creds obtainable, secrets echoed through Renovate logs. The config field is the fetch primitive. - CVE-2026-110866 / GHSA-8qr3-fm9c-cqg3 (medium) —
minimumReleaseAgeprotection skipped when a PR rebase is requested via the rebase/retry checkbox: a malicious just-published dependency version gets pushed into the PR and run in CI before the cooling-off period elapses. Supply-chain cooldown gates must re-evaluate on every state transition, not only at initial branch update — user-triggered replays (rebase, retry, rerun) are gate-bypass entry points.
Operator sweep for any config-from-fragments automation bot (Renovate, Dependabot, release-please, CI template systems): (1) enumerate which config keys become env vars, HTTP headers, or fetch targets; (2) publish a hostile preset in a repo you own and extend it from a lab instance, checking whether allowlist enforcement runs pre- or post-merge; (3) diff the bot's outbound requests (headers, destinations) with preset-injected vs plain config; (4) test every "re-run/rebase/retry" affordance for protection-gate skips. Lab instances only; never point a shared/public bot at your hostile preset.