# OpenUSD 26.11 Disables Support for Binary USD Files Older Than Version 0.4.0

**URL:** <https://forum.aousd.org/t/openusd-26-11-disables-support-for-binary-usd-files-older-than-version-0-4-0/3057>\
**Category:** Announcements\
**Created:** [October 8, 2026, 6:15pm UTC](https://forum.aousd.org/t/openusd-26-11-disables-support-for-binary-usd-files-older-than-version-0-4-0/3057 "2026-10-08T18:15:49Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![amohr](https://avatars.discourse-cdn.com/v4/letter/a/f475e1/32.png) [@amohr](https://forum.aousd.org/u/amohr)\
**Post date:** [October 8, 2026, 6:15pm UTC](https://forum.aousd.org/t/openusd-26-11-disables-support-for-binary-usd-files-older-than-version-0-4-0/3057/1 "2026-10-08T18:15:49Z")

</div>

To address a security issue related to reading maliciously crafted files, OpenUSD release 26.11 disables support for reading binary USD (`.usd`/`.usdc`, “crate”) files older than version 0.4.0. The risk lies in the code that reads these older versions.

Crate file version 0.4.0 became the default for newly-created files in USD release 0.8.2, December 2017. Files created with that release or newer are unaffected and continue to work. Older files must be updated to keep working. OpenUSD 26.11 refuses to open them, reporting:

```auto
Cannot read asset @Prop.geom.usd@ with obsolete version 0.0.1. The oldest
version this software supports is 0.4.0. See the OpenUSD FAQ for information
about handling obsolete assets. https://openusd.org/release/usdfaq.html

```

Files with versions from 0.4.0 up to but not including 0.8.0 remain deprecated. OpenUSD 26.11 still opens them but emits a warning:

```auto
Asset @Prop.geom.usd@ has deprecated version 0.7.0. Future versions of USD will
not be able to read it. See the OpenUSD FAQ for information about handling
deprecated assets. https://openusd.org/release/usdfaq.html Disable this warning
by setting PXR_USDC_EMIT_DEPRECATION_WARNINGS=0 in the environment.

```

The [OpenUSD FAQ](https://openusd.org/release/usdfaq.html) link in the above messages contains information on handling old files, but be sure to select “Dev (26.11)” from the drop-down at the top of the page to get the most up-to-date information before 26.11 releases.

We recommend updating both obsolete and deprecated files at the same time.

## Identifying Old Files

The `usdupdatecrate` tool, new in OpenUSD 26.08, scans directories, including the contents of `.usdz` packages, and reports old files. By default it reports files older than 0.8.0, covering both obsolete and deprecated versions. Pass `--olderThan 0.4.0` to report only the files that OpenUSD 26.11 cannot read:

```auto
> usdupdatecrate --root /path/to/assets
> usdupdatecrate --root /path/to/assets --olderThan 0.4.0

```

To identify file versions without an OpenUSD build, there are two options.

### Unix `file`

Some versions of the `file` utility (5.39, for example) recognize crate files:

```auto
> file Prop.geom.usd
Prop.geom.usd: USD crate, version 0.0.1

```

If yours does not, add these entries to `~/.magic` or `/etc/magic`:

```auto
# Pixar USD Crate File Format
0 string PXR-USDC Pixar USD crate file (usdc), version
>8 byte x %d.
>9 byte x \b%d.
>10 byte x \b%d

# Pixar USD Text File Format
0 string #usda Pixar USD text file (usda), version
>6 string >\0 %s

```

Note that `file` does not look inside `.usdz` packages.

### Python script

The Python script appearing at the end of this post needs only Python 3 and should work on any platform, including Windows, where `file` is not normally available. It reports the format and version of each USD file given, including files inside `.usdz` packages, and ignores non-USD files. Directory traversal is left to `usdupdatecrate`.

```auto
> python3 usdFileVersion.py Prop.geom.usd Set.usdz notes.txt
Prop.geom.usd: usdc 0.0.1
Set.usdz[Set.usdc]: usdc 0.8.0

```

With `--olderThan`, it reports only crate files older than the given version, and exits with status 1 if it finds any:

```auto
> python3 usdFileVersion.py --olderThan 0.4.0 Prop.geom.usd Set.usdz
Prop.geom.usd: usdc 0.0.1

```

## Updating Old Files

OpenUSD 26.08 can read and update old files. Rewriting a file writes it at the current crate version. Note that opening an old file, editing it, and saving it preserves its old version; the file must be fully rewritten to update it.

For a handful of files, `usdcat` updates them in place:

```auto
> file Prop.geom.usd
Prop.geom.usd: USD crate, version 0.0.1
> usdcat -o Prop.geom.usd Prop.geom.usd
> file Prop.geom.usd
Prop.geom.usd: USD crate, version 0.8.0

```

For bulk updates, run `usdupdatecrate --update` in OpenUSD 26.08 to do the job robustly. It writes each file to a temporary sibling, verifies the new version, and only then replaces the original. See `usdupdatecrate --help` for details.

```auto
> usdupdatecrate --root /path/to/assets --update

```

## Continuing to Read Old Files

Users who must continue reading versions older than 0.4.0 in OpenUSD 26.11 can patch `PXR_USDC_OLDEST_SUPPORTED_VERSION` in `pxr/usd/sdf/crateFile.cpp`, but doing so carries security risk when reading untrusted files. We intend to delete the code for reading versions older than 0.4.0, making this option impractical in OpenUSD release 27.05. Deprecated versions from 0.4.0 up to but not including 0.8.0 will remain readable in 27.05.

## Appendix: `usdFileVersion.py`

```python
#!/usr/bin/env python3
"""Report the format and version of USD files, including the contents of .usdz
packages. Package members are reported as package.usdz[member.usd]. Non-USD
files are ignored.

With --olderThan, report only binary USD (crate) files older than the given
version, and exit with status 1 if any are found.
"""
import argparse, glob, os, sys, zipfile

def parseVersion(s):
    try:
        version = tuple(int(x) for x in s.split('.'))
    except ValueError:
        version = ()
    if len(version) != 3:
        raise argparse.ArgumentTypeError(
            "expected major.minor.patch, got '%s'" % s)
    return version

def check(name, f, olderThan):
    """Report on the open file f. Return the number of crate files found
    older than olderThan."""
    header = f.read(16)
    if header.startswith(b'PXR-USDC'):
        version = tuple(header[8:11])
        isOld = olderThan is not None and version < olderThan
        if olderThan is None or isOld:
            print('%s: usdc %d.%d.%d' % ((name,) + version))
        return int(isOld)
    elif header.startswith(b'#usda'):
        if olderThan is None:
            fields = header[5:].split()
            print('%s: usda %s' %
                  (name, fields[0].decode('ascii', 'replace')
                   if fields else '(no version)'))
    elif header.startswith(b'PK\x03\x04'):
        # A .usdz package is an uncompressed zip archive.
        f.seek(0)
        numOld = 0
        with zipfile.ZipFile(f) as z:
            for info in z.infolist():
                if not info.is_dir():
                    with z.open(info) as member:
                        numOld += check('%s[%s]' % (name, info.filename),
                                        member, olderThan)
        return numOld
    return 0

def main():
    parser = argparse.ArgumentParser(description= __doc__ )
    parser.add_argument('files', nargs='+', metavar='FILE')
    parser.add_argument('--olderThan', type=parseVersion, metavar='VERSION',
                        help='report only crate files older than VERSION '
                        '(major.minor.patch), for example 0.4.0')
    args = parser.parse_args()

    paths = args.files
    if os.name == 'nt':
        # The Windows command shell does not expand wildcards.
        paths = [p for arg in paths for p in (glob.glob(arg) or [arg])]

    numOld = 0
    hadError = False
    for path in paths:
        try:
            with open(path, 'rb') as f:
                numOld += check(path, f, args.olderThan)
        except (OSError, zipfile.BadZipFile) as e:
            print('%s: error: %s' % (path, e), file=sys.stderr)
            hadError = True
    if hadError:
        return 2
    return 1 if numOld else 0

if __name__ == ' __main__':
    sys.exit(main())

```
