ppy/osu · error · InvalidOperationException

Filename ""{filename}"" is not allowed.

Error message

Filename ""{filename}"" is not allowed.

What it means

Thrown by ModelManager<TModel>.AddFile after ToStandardisedPath() if FilesystemSanityCheckHelpers.IncursPathTraversalRisk(filename) is true. It is a hard security guard rejecting filenames that could escape the model's file directory via '..' segments, absolute paths, or other traversal patterns. Runs inside an ongoing realm transaction.

Source

Thrown at osu.Game/Database/ModelManager.cs:93

        }

        /// <summary>
        /// Replace a file from within an ongoing realm transaction.
        /// </summary>
        public void ReplaceFile(RealmNamedFileUsage file, Stream contents, Realm realm)
        {
            file.File = realmFileStore.Add(contents, realm);
        }

        /// <summary>
        /// Add a file from within an ongoing realm transaction. If the file already exists, it is overwritten.
        /// </summary>
        public void AddFile(TModel item, Stream contents, string filename, Realm realm)
        {
            filename = filename.ToStandardisedPath();

            if (FilesystemSanityCheckHelpers.IncursPathTraversalRisk(filename))
                throw new InvalidOperationException($@"Filename ""{filename}"" is not allowed.");

            var existing = item.GetFile(filename);

            if (existing != null)
            {
                ReplaceFile(existing, contents, realm);
                return;
            }

            var file = realmFileStore.Add(contents, realm);
            var namedUsage = new RealmNamedFileUsage(file, filename);

            item.Files.Add(namedUsage);
        }

        /// <summary>
        /// Delete multiple items.
        /// This will post notifications tracking progress.

View on GitHub (pinned to d9c73e12ad)

Solutions

  1. Sanitise the filename before calling AddFile: strip directory components with Path.GetFileName(filename) and reject/replace any path separators or '..'.
  2. Validate with the same helper the manager uses: guard with if (FilesystemSanityCheckHelpers.IncursPathTraversalRisk(filename)) return early or normalise.
  3. Ensure user-facing filename fields are passed through ToStandardisedPath() and a GetValidFilename()-style normaliser upstream so only a relative leaf name reaches AddFile.

Example fix

// before
modelManager.AddFile(item, stream, @"../../etc/evil.osu", realm);

// after
string safeName = Path.GetFileName(filename).GetValidFilename();
if (FilesystemSanityCheckHelpers.IncursPathTraversalRisk(safeName))
    throw new ArgumentException($"Refusing unsafe filename: {filename}");
modelManager.AddFile(item, stream, safeName, realm);
Defensive patterns

Strategy: validation

Validate before calling

string safe = Path.GetFileName(filename).ToStandardisedPath();
if (FilesystemSanityCheckHelpers.IncursPathTraversalRisk(safe))
    throw new ArgumentException($"Unsafe filename: {filename}");
modelManager.AddFile(item, stream, safe, realm);

Type guard

static bool IsSafeFilename(string filename)
    => !string.IsNullOrWhiteSpace(filename)
       && !Path.IsPathRooted(filename)
       && !filename.Contains("..")
       && !FilesystemSanityCheckHelpers.IncursPathTraversalRisk(filename);

Try / catch

try { modelManager.AddFile(item, stream, filename, realm); }
catch (InvalidOperationException ex) when (ex.Message.Contains("is not allowed"))
{ /* log offending filename, reject user input */ }

Prevention

When it happens

Trigger: Calling modelManager.AddFile(item, stream, filename, realm) with a filename containing '../', leading drive/root separators, backslash-based traversal, or any pattern FilesystemSanityCheckHelpers flags. Happens during editor save, import merge, or programmatic file addition.

Common situations: Filenames sourced from untrusted input (downloaded archives, external editor imports, user-typed paths). A ruleset/beatmap editor that constructs filenames by joining user strings without sanitising. Cross-platform path normalisation surprises (backslashes on Windows interpreted as traversal).

Related errors


AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13). Data as JSON: /api/errors/e83e4e89ea08be2d. Report an issue: GitHub.