Skip to content

🔉 fix: Normalize audio MIME types in STT format validation - #12674

Merged
danny-avila merged 2 commits into
devfrom
fix/stt-audio-mime-normalization
Apr 15, 2026
Merged

danny-avila merged 2 commits into
devfrom
fix/stt-audio-mime-normalization

Conversation

@danny-avila

Copy link
Copy Markdown
Collaborator

Summary

Browsers commonly report audio files with non-standard MIME types (e.g. audio/x-m4a for .m4a files, audio/x-wav, audio/x-flac). The STT azureOpenAIProvider rejects these because the format validation only checks the raw MIME subtype against the accepted formats list.

This is the same class of bug as #12608 (text/x-markdown rejected in file uploads). The fix reuses the existing MIME_TO_EXTENSION_MAP — which already has the correct MIME-to-extension mapping — to normalize the format before validation. Unknown MIME types are correctly rejected instead of silently falling through to a webm default. Raw subtype fallback is gated on audio/video prefix to prevent non-audio types from bypassing validation.

Fixes #12632
Continues #12633

Credit to @jona7o for the original PR.

Changes

  • Use MIME_TO_EXTENSION_MAP directly for normalization instead of getFileExtensionFromMime() (which has a webm default fallback that would accept unknown audio subtypes)
  • Gate raw subtype matching on audio/video prefix to reject types like text/webm
  • Export MIME_TO_EXTENSION_MAP for test use
  • Add negative tests for unknown audio subtypes and non-audio prefix bypass

Test plan

  • 16 unit tests pass covering MIME normalization and format validation
  • Known non-standard MIME types (audio/x-m4a, audio/x-wav, audio/x-flac) accepted
  • Standard formats (audio/mpeg, audio/wav, etc.) accepted
  • Unknown audio subtypes (audio/aac, audio/somethingelse) rejected
  • Non-audio types with audio subtypes (text/webm) rejected
  • application/ogg (valid Ogg container in the MIME map) accepted

jona7o and others added 2 commits April 12, 2026 23:37
Use getFileExtensionFromMime() to normalize non-standard MIME types
(e.g. audio/x-m4a, audio/x-wav, audio/x-flac) before checking against
the accepted formats list in azureOpenAIProvider. This is the same class
of bug as #12608 (text/x-markdown), but for STT audio validation.

Only audio/ and video/ MIME prefixes are normalized to prevent
non-audio types from matching via the webm default fallback.

Export getFileExtensionFromMime for testability.

Fixes #12632
Use MIME_TO_EXTENSION_MAP for normalization instead of
getFileExtensionFromMime() which falls back to 'webm' for unrecognized
types. Gate raw subtype matching on audio/video prefix to prevent
non-audio types (e.g. text/webm) from passing validation.

Resolves Codex review comment about unknown subtypes silently passing.
Copilot AI review requested due to automatic review settings April 15, 2026 13:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Normalizes audio MIME types during Azure OpenAI STT format validation so common browser-reported vendor MIME types (e.g. audio/x-m4a) are accepted when they map to an allowed audio format, while unknown/unsafe MIME types remain rejected.

Changes:

  • Update Azure OpenAI STT provider validation to normalize via MIME_TO_EXTENSION_MAP and restrict raw-subtype fallback to audio/ and video/ MIME prefixes.
  • Export MIME_TO_EXTENSION_MAP (and getFileExtensionFromMime) for unit testing.
  • Add Jest tests covering MIME normalization and negative cases (unknown audio subtypes, non-audio prefix bypass).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
api/server/services/Files/Audio/STTService.js Normalize MIME types before validating accepted audio formats; export MIME map/util for tests.
api/server/services/Files/Audio/STTService.spec.js New unit tests for MIME normalization and format acceptance/rejection scenarios.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +64 to +73
function isFormatAccepted(mimetype) {
const [mimePrefix, rawFormat = ''] = mimetype.split('/');
const isAudioMime = mimePrefix === 'audio' || mimePrefix === 'video';
const isKnownMime = mimetype in MIME_TO_EXTENSION_MAP;
const normalizedFormat = isKnownMime ? MIME_TO_EXTENSION_MAP[mimetype] : null;
return (
acceptedFormats.includes(normalizedFormat) ||
(isAudioMime && acceptedFormats.includes(rawFormat))
);
}

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new tests validate a local isFormatAccepted() helper that re-implements the provider’s MIME/format check, but they never call STTService.azureOpenAIProvider() (the code changed in this PR). This can let the test suite pass even if the real provider logic diverges (e.g., acceptedFormats list or normalization rules change). Consider exercising azureOpenAIProvider() directly with mocked sttSchema/genAzureEndpoint and asserting it throws/doesn’t throw for the same mimetypes instead of duplicating the logic in the test.

Copilot uses AI. Check for mistakes.
}

module.exports = { STTService, speechToText };
module.exports = { STTService, speechToText, getFileExtensionFromMime, MIME_TO_EXTENSION_MAP };

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MIME_TO_EXTENSION_MAP is now exported, which makes it part of the module’s public surface and allows external code/tests to mutate it at runtime. To prevent hard-to-debug side effects, consider freezing the map (e.g., Object.freeze) or exporting a defensive copy so consumers can’t modify the internal lookup table.

Copilot uses AI. Check for mistakes.
!acceptedFormats.includes(normalizedFormat) &&
!(isAudioMime && acceptedFormats.includes(rawFormat))
) {
throw new Error(`The audio file format ${rawFormat} is not accepted`);

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thrown error now always interpolates rawFormat. For some invalid inputs rawFormat can be empty or misleading (e.g., malformed MIME strings without a subtype), which makes debugging harder. Consider including the full audioFile.mimetype and/or the computed normalizedFormat in the error message so logs clearly show what was rejected.

Suggested change
throw new Error(`The audio file format ${rawFormat} is not accepted`);
throw new Error(
`The audio file format is not accepted (mimetype: "${audioFile.mimetype}", raw format: "${rawFormat}", normalized format: "${normalizedFormat}")`,
);

Copilot uses AI. Check for mistakes.
@github-actions

Copy link
Copy Markdown
Contributor

GitNexus: ❌ deploy failed

The deploy failed — the previous index (if any) continues to be served.
Deploy run

@danny-avila
danny-avila changed the base branch from main to dev April 15, 2026 13:45
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila danny-avila changed the title fix: Normalize audio MIME types in STT format validation 🔉 fix: Normalize audio MIME types in STT format validation Apr 15, 2026
@danny-avila
danny-avila merged commit 6183303 into dev Apr 15, 2026
15 checks passed
@danny-avila
danny-avila deleted the fix/stt-audio-mime-normalization branch April 15, 2026 13:58
krgokul pushed a commit to syedhabib39/LibreChat that referenced this pull request Apr 20, 2026
…-AI#12674)

* fix: normalize audio MIME types in STT format validation

Use getFileExtensionFromMime() to normalize non-standard MIME types
(e.g. audio/x-m4a, audio/x-wav, audio/x-flac) before checking against
the accepted formats list in azureOpenAIProvider. This is the same class
of bug as LibreChat-AI#12608 (text/x-markdown), but for STT audio validation.

Only audio/ and video/ MIME prefixes are normalized to prevent
non-audio types from matching via the webm default fallback.

Export getFileExtensionFromMime for testability.

Fixes LibreChat-AI#12632

* fix: reject unknown audio subtypes in STT format validation

Use MIME_TO_EXTENSION_MAP for normalization instead of
getFileExtensionFromMime() which falls back to 'webm' for unrecognized
types. Gate raw subtype matching on audio/video prefix to prevent
non-audio types (e.g. text/webm) from passing validation.

Resolves Codex review comment about unknown subtypes silently passing.

---------

Co-authored-by: Tobias Jonas <t.jonas@innfactory.de>
krgokul pushed a commit to syedhabib39/LibreChat that referenced this pull request Apr 21, 2026
…-AI#12674)

* fix: normalize audio MIME types in STT format validation

Use getFileExtensionFromMime() to normalize non-standard MIME types
(e.g. audio/x-m4a, audio/x-wav, audio/x-flac) before checking against
the accepted formats list in azureOpenAIProvider. This is the same class
of bug as LibreChat-AI#12608 (text/x-markdown), but for STT audio validation.

Only audio/ and video/ MIME prefixes are normalized to prevent
non-audio types from matching via the webm default fallback.

Export getFileExtensionFromMime for testability.

Fixes LibreChat-AI#12632

* fix: reject unknown audio subtypes in STT format validation

Use MIME_TO_EXTENSION_MAP for normalization instead of
getFileExtensionFromMime() which falls back to 'webm' for unrecognized
types. Gate raw subtype matching on audio/video prefix to prevent
non-audio types (e.g. text/webm) from passing validation.

Resolves Codex review comment about unknown subtypes silently passing.

---------

Co-authored-by: Tobias Jonas <t.jonas@innfactory.de>
jcbartle pushed a commit to jcbartle/LibreChat that referenced this pull request May 11, 2026
…-AI#12674)

* fix: normalize audio MIME types in STT format validation

Use getFileExtensionFromMime() to normalize non-standard MIME types
(e.g. audio/x-m4a, audio/x-wav, audio/x-flac) before checking against
the accepted formats list in azureOpenAIProvider. This is the same class
of bug as LibreChat-AI#12608 (text/x-markdown), but for STT audio validation.

Only audio/ and video/ MIME prefixes are normalized to prevent
non-audio types from matching via the webm default fallback.

Export getFileExtensionFromMime for testability.

Fixes LibreChat-AI#12632

* fix: reject unknown audio subtypes in STT format validation

Use MIME_TO_EXTENSION_MAP for normalization instead of
getFileExtensionFromMime() which falls back to 'webm' for unrecognized
types. Gate raw subtype matching on audio/video prefix to prevent
non-audio types (e.g. text/webm) from passing validation.

Resolves Codex review comment about unknown subtypes silently passing.

---------

Co-authored-by: Tobias Jonas <t.jonas@innfactory.de>
ThomasVuNguyen pushed a commit to ThomasVuNguyen/LibreChat that referenced this pull request Jul 15, 2026
…-AI#12674)

* fix: normalize audio MIME types in STT format validation

Use getFileExtensionFromMime() to normalize non-standard MIME types
(e.g. audio/x-m4a, audio/x-wav, audio/x-flac) before checking against
the accepted formats list in azureOpenAIProvider. This is the same class
of bug as LibreChat-AI#12608 (text/x-markdown), but for STT audio validation.

Only audio/ and video/ MIME prefixes are normalized to prevent
non-audio types from matching via the webm default fallback.

Export getFileExtensionFromMime for testability.

Fixes LibreChat-AI#12632

* fix: reject unknown audio subtypes in STT format validation

Use MIME_TO_EXTENSION_MAP for normalization instead of
getFileExtensionFromMime() which falls back to 'webm' for unrecognized
types. Gate raw subtype matching on audio/video prefix to prevent
non-audio types (e.g. text/webm) from passing validation.

Resolves Codex review comment about unknown subtypes silently passing.

---------

Co-authored-by: Tobias Jonas <t.jonas@innfactory.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: STT rejects valid audio files with non-standard MIME types (e.g. audio/x-m4a)

3 participants