Sanitizing User-Uploaded glTF Models for Web Servers
Serving user-uploaded 3D assets like glTF (GL Transmission Format) and GLB files introduces significant security risks, ranging from path traversal and cross-site scripting (XSS) to denial-of-service (DoS) via decompression bombs. To safeguard your infrastructure and client browsers, web servers must systematically validate file structure, strip unapproved URIs, enforce resource limits, and sanitize metadata before distributing models to end users.
Prefer and Enforce Self-Contained GLB
glTF files can be distributed either as standalone JSON
(.gltf) pointing to external bin/texture files, or as
single, self-contained binary files (.glb).
- Restrict uploads to GLB: Whenever possible, mandate
the binary format (
.glb). This avoids complex multi-file upload management, prevents external asset references, and confines all data chunks to a single stream. - Validate the GLB container header: Verify that the
12-byte header begins with the correct magic number
(
0x46546C67forglTF), specifies version2, and that the declared total length matches the exact byte length of the uploaded file.
Schema and Structural Validation
Do not rely solely on MIME types or file extensions, as they are trivially spoofed.
- Khronos Schema Validation: Parse the internal JSON manifest and validate it strictly against the official Khronos glTF 2.0 JSON schema. Reject any files that fail structural compliance.
- Chunk Order and Alignment: In GLB files, verify
that the first chunk is strictly the
JSONchunk (0x4E4F534A) and the optional second chunk is strictly the binary buffer (BIN\x00/0x004E4942). Discard files with unexpected trailing data or unaligned byte padding.
URI and Path Traversal Neutralization
When processing standard .gltf files or GLBs with
image/buffer references:
- Ban Local File Schemes: Explicitly disallow
protocols like
file://,blob:,javascript:, or absolute operating system paths. - Disallow External URIs: Strip or reject references
to remote domains (
http://,https://) to prevent your servers or users' browsers from being used for Server-Side Request Forgery (SSRF) or unauthorized outbound tracking. - Neutralize Path Traversal: If external assets are
supported, normalize all relative paths and explicitly block directory
traversal sequences (such as
../and..\). All referenced assets must resolve strictly within the designated temporary upload sandbox. - Data URI Sanitization: If
data:URIs are permitted for textures, restrict them strictly to safe, non-executable MIME types (image/png,image/jpeg,image/webp).
Extension Whitelisting and Metadata Stripping
glTF supports arbitrary extensions (extensionsUsed,
extensionsRequired) and custom metadata dictionaries
(extras).
- Whitelist Extensions: glTF allows custom extensions
that may trigger unhandled parser behaviors. Compare all declared
extensions against an explicit whitelist of supported Khronos/vendor
extensions (such as
KHR_materials_unlitorKHR_draco_mesh_compression). Reject files declaring unknown entries underextensionsRequired. - Sanitize
extrasObjects: Theextrasproperty can contain arbitrary JSON, which could be reflected into the client DOM and lead to Cross-Site Scripting (XSS). Recursively scrub HTML tags, script constructs, and control characters from string values, or completely dropextrasif application-specific metadata is not required.
Resource Limits and Decompression Bomb Mitigation
Malicious models can easily freeze the user's browser, crash WebGL contexts, or exhaust server RAM.
- Limit Geometry Complexity: Set hard ceilings on total triangle counts, vertex counts, and mesh primitive counts based on your target platform's performance thresholds.
- Prevent Buffer Overlaps: Validate that buffer views
(
bufferViews) and accessors (accessors) reference non-overlapping, in-bounds memory ranges within the binary chunk to avoid out-of-bounds read vulnerabilities. - Inspect Texture Dimensions: Extract and inspect image headers without fully decompressing them into memory. Enforce limits on texture dimensions (e.g., maximum 4096×4096) and total texture count to prevent WebGL memory crashes.
- Guard Against Draco Decompression Bombs: If Draco mesh compression is enabled, enforce an uncompressed size threshold before decoding to prevent zip-bomb-style CPU and memory exhaustion.
Normalization and Pipeline Re-encoding
The most robust sanitization strategy is to re-encode the file using
a headless, isolated processor (such as
@gltf-transform/core).
- Run the file through an automated headless pipeline in an isolated, short-lived container.
- Unpack the model, validate components programmatically, discard unapproved nodes and attributes, and serialize the model into a freshly generated GLB file.
- Discard the original uploaded binary entirely, ensuring that malformed payloads or exploit attempts targeting WebGL parsers are neutralized during the transformation step.
Safe Web Server Delivery
Once the model is cleaned and stored, configure your delivery infrastructure defensively:
- Content-Type Headers: Serve
.glbfiles withmodel/gltf-binaryand.gltffiles withmodel/gltf+json. - Security Headers: Enforce
X-Content-Type-Options: nosniffto stop browsers from interpreting JSON or binary chunks as executable HTML or JavaScript. - Isolated Origins: Host user-generated models on a
separate, dedicated media domain (e.g.,
user-assets.example.com) without session cookies. - Content Security Policy (CSP): Ensure the rendering environment's CSP restricts connect-src and img-src to prevent client-side WebGL loaders from making unapproved outbound network requests.