Upload validation and bare-metal image boundary checks from July 9 GHSA updates¶
This update promotes GHSA records into reusable operator checks for authorized assessments. The common pattern is a caller-controlled artifact that crosses a boundary after the platform has already decided it is safe: an upload Content-Type compared through an unsafe denylist regex, an allowed SVG stored on a browser-executable public disk without content sanitization, a tenant-controlled bare-metal console path reaching host-side tooling, or a deployment image influencing commands executed during image preparation.
Sources:
- GHSA-7g26-2qgj-chfg: CarrierWave
content_type_denylistbypass via unescaped regex metacharacters - GHSA-xfvg-8v67-j7wp / CVE-2026-27621: TypiCMS SVG upload stored XSS when public storage serves unsanitized SVG content
- GHSA-wqpv-c3pp-3m58: OpenStack Ironic functionality from an untrusted control sphere
- GHSA-rmxr-45gj-889w: OpenStack Ironic Python Agent chroot
grub-installexecution from deployed image content
Authorized validation only
Keep proofs in disposable upload apps, lab OpenStack/Ironic environments, and scratch bare-metal nodes or VMs. Use benign marker files, fake content types, harmless SVG markers, inert wrapper commands, and lab images. Do not upload web shells, credential-harvesting SVGs, alter production bare-metal provisioning flows, run payloads on conductor hosts, or target customer images.
Operator use¶
Use these checks when a scope includes:
- Ruby/Rails apps using CarrierWave or equivalent upload libraries with MIME denylist controls;
- upload paths that allow SVG, XML, HTML, archive, office, or polyglot-looking content but claim a denylist or MIME check makes the stored artifact safe;
- CMS media libraries that store SVGs on a public disk, render previews inline, or let uploaded files inherit the application origin;
- OpenStack Ironic or bare-metal-as-a-service platforms where tenants can influence image contents, console settings, deployment metadata, or bootloader setup;
- provisioning agents that mount or chroot into tenant-provided images and then run host tooling from inside that environment.
Recon checklist¶
| Boundary | What to look for | Safe canary |
|---|---|---|
| MIME denylist regexes | String denylist entries interpolated into regexes without escaping metacharacters such as +, ., (, ), [, ], or anchors | Benign file with a controlled Content-Type, such as image/svg+xml, and non-executing marker content |
| Upload storage binding | MIME decision separated from extension, final storage path, public serving origin, or downstream processors | Matrix of claimed MIME, detected MIME, extension, storage path, and render/download behavior |
| SVG content trust | SVG is allowlisted as an image but saved without stripping scriptable elements, event handlers, external references, or dangerous animation/link constructs | Harmless SVG with viewBox and a visible text/DOM marker in a lab browser |
| Bare-metal console helpers | Non-default console interfaces or driver options that cause host-side tools such as ipmitool to run using tenant-influenced fields | Lab node with wrapper/logging binary or fake BMC endpoint; no production BMC commands |
| Image preparation chroots | Deployment agents that chroot into an image and run bootloader, package, hook, or helper commands resolved from the image filesystem | Disposable image containing inert marker wrappers and pre/post deployment logs |
Validation patterns¶
CarrierWave MIME denylist bypass¶
The operator question is whether the application treats a denylist as a reliable block for a dangerous class of uploads while the regex form misses the real MIME value.
- Identify uploaders using
content_type_denylistor local wrappers around it. Record the exact configured entries. - Build a decision table for MIME values containing regex metacharacters, especially
image/svg+xml. Compare: - the literal denylist value;
- the real request
Content-Typeheader; - any server-side detected MIME value;
- whether the upload is accepted.
- Use a harmless marker file. If SVG is in scope, use inert SVG/XML with a text marker only; do not include script, external references, or browser-executing payloads.
- Capture final storage and serving behavior. A strong report shows that the same policy blocks a control MIME but accepts the metacharacter-bearing MIME it intended to deny.
Useful evidence is a compact table: configured denylist entry, regex-equivalent behavior if visible, submitted MIME, expected decision, actual decision, stored filename/path, and fixed-version result.
CMS SVG upload and public-origin execution boundary¶
The TypiCMS advisory adds a separate upload lesson: even when the MIME decision is literal and intentional, SVG is active browser content. If the CMS stores the file on a public disk and serves it from the application origin, an attacker with upload rights may be able to turn media-library access into stored client-side execution against editors or administrators.
- In a disposable CMS lab, identify file-upload validators that allow
svg,image/svg+xml, or extension-based SVG uploads. - Confirm where the uploaded file is stored and how it is served: same application origin, media subdomain, forced download, sanitized preview, or inline render.
- Use a harmless SVG canary with a valid
viewBoxand visible marker text. If script execution is explicitly approved for the lab, keep the script to a local marker such as settingdocument.body.dataset.svgCanary = "1"; never collect cookies, tokens, local storage, or page contents. - Compare direct-file access, CMS thumbnail/preview views, admin media-picker views, and any rich-text embed path. Record which contexts execute, download, or sanitize the SVG.
- Pair the proof with a patched or hardened negative control: sanitized SVG output, forced attachment download, origin isolation, or rejection/conversion of active SVG content.
Report this as allowed SVG upload -> unsanitized active content -> same-origin editor/admin render. Do not overstate it as server-side code execution; the durable operator value is the upload-to-browser trust boundary and the contexts where privileged users view the stored artifact.
OpenStack Ironic console/tool execution boundary¶
This check is for approved OpenStack/Ironic labs or customer-approved private-cloud tests. It is not a broad internet scan.
- Confirm the deployment uses OpenStack Ironic and whether non-default console interfaces are enabled for the tested node type.
- Map tenant-controlled inputs that influence console or BMC helper invocations: node driver info, console settings, management addresses, usernames, and deployment metadata.
- In a lab, route helper calls to a fake BMC endpoint or replace the helper with a wrapper that logs argv and environment, then exits safely.
- Evidence should show the boundary crossing: tenant-controlled field -> Ironic/conductor helper invocation -> inert logged argument or callback.
Do not issue real power, boot, SOL, or management commands against production BMCs. The finding is about control-plane trust, not destructive device control.
Ironic Python Agent chroot image execution¶
The risky pattern is host/provisioning code entering an image supplied or influenced by the tenant, then executing a helper resolved from that image's filesystem.
- Build a disposable image in a lab project. Add only an inert marker wrapper for the expected helper path, such as a
grub-installwrapper that writes a timestamped marker to a lab log and exits with a controlled status. - Provision a disposable node/VM through the same Ironic Python Agent path used by the target environment.
- Capture whether the agent executes the wrapper from inside the image chroot during bootloader setup.
- Pair the positive proof with a fixed-version or hardened-path negative control where the host uses trusted tooling or refuses the image-controlled helper.
Do not place shell payloads, credential readers, network callbacks to internal services, or persistence hooks in images. Keep the proof to a single inert marker showing image content influenced provisioning-time execution.
Reporting notes¶
Lead with the artifact-to-runtime boundary:
- configured MIME denylist -> regex parser -> accepted upload;
- allowlisted SVG -> unsanitized active content -> same-origin CMS render;
- tenant console metadata -> conductor-side helper invocation;
- tenant image filesystem -> provisioning agent command resolution.
Include version, configuration preconditions, role/tenant privileges, exact input class, synthetic canary evidence, and a negative control. Avoid claiming generic RCE unless your approved lab proof shows command execution in the specific service context and you can name that context precisely.