You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Security advisories not yet reported upstream (OBS Studio)
#1629
This thread tracks published obs-rust security advisories for bugs that also exist in upstream OBS Studio, until someone reports each one upstream.
Upstream takes security reports only at security@obsproject.com or on their Discord. GitHub private reporting is turned off on obsproject/obs-studio. Upstream also asks reporters to keep a bug confidential for 120 days.
Rules for this thread
Only add an advisory after it has been published. Advisories still in triage stay private, so don't mention them here.
Once you've reported an advisory upstream, reply with the date and the channel, and tick its box.
Subject: Heap use-after-free in libobs/callback/signal.c (signal_handler_remove_current)
If a signal callback calls signal_handler_connect on the signal that is currently running, da_push_back can reallocate sig->callbacks.array. The thread-local current_signal_cb then points into the freed block. If that callback then calls signal_handler_remove_current(), it writes 1 byte into freed memory. AddressSanitizer reports this as a heap-use-after-free. The global-callback path (current_global_cb / signal_handler_connect_global) has the same problem.
Backlog: earlier public fixes that upstream still lacks
Each fix below landed publicly in obs-rust. On 2026-10-21 the same file on obsproject/obs-studio master still had the bug. Each line can be sent as it stands, with the PR link as the patch.
librtmp: Reject invalid Set Chunk Size values #115librtmpHandleChangeChunkSize() accepts a chunk size with bit 31 set from the server. The resulting negative m_inChunkSize corrupts the chunk read and allocation arithmetic. Fix: reject values below 1. (network, medium-high)
librtmp: Reject secureToken lengths that are not whole TEA blocks #232librtmpDecodeTEA() takes a secureToken of any length from the server. A length of 0 reads v[-1] and divides by zero, and a length that isn't a multiple of 8 reads past the end of the token. Fix: reject both. (network, medium-high)
librtmp: Bound AMF/AMF3 decode recursion depth #116librtmpAMF_Decode and AMF3_Decode recurse once per nesting level with no limit, so a server's deeply nested objects overflow the stack. Fix: cap the depth. (network, DoS)
librtmp: Bound AMF3 name logging and free class member names #230librtmpAMF3_Decode logs the class and member names with %s although they aren't NUL-terminated, which reads out of bounds. It also leaks cd_props on every class decode. Fix: use %.*s and free cd_props. (network, medium)
libobs: Keep AV1 OBU parsing inside the buffer #103libobs/obs-av1.cparse_obu_header() sets obu_size = size - 1 without accounting for the extension byte or the buffer end, so a crafted OBU reads out of bounds. leb128() also overflows an int from the 5th byte. (media, medium)
libobs: Snapshot contexts during enumeration #730libobs/obs.cobs_enum() reads context->next after the callback may have released the last reference, a use-after-free in obs_enum_outputs, obs_enum_encoders and obs_enum_services. It can also hand out encoders that are already being destroyed. Fix: enumerate a snapshot that holds references. (local, medium)
mac-avcapture: Clamp audio buffer list to MAX_AV_PLANES #124mac-avcapture copies mNumberBuffers plane pointers into an array of MAX_AV_PLANES entries without checking the count, so a device reporting more than 8 buffers writes out of bounds. Fix: clamp the count. (device, low-medium)
libobs: Reject recursive transition destinations #737libobs transitionsobs_transition_start() deadlocks on the transition's own mutex when the destination already contains that transition, directly or nested. Fix: reject recursive destinations. (local, DoS, borderline)
libobs: Reject an image too large for a texture before decoding it #1474image source decodes an image of any size in full before texture creation fails, for example about 2.5 GB for a 20480x11520 image. Fix: check against the device's maximum texture size in get_buffer2. (file, DoS, borderline)
Checked and left out: #200, #228 and #305 (functional bugs, not security), #582 (unreachable), #685 (the code exists only in obs-rust), and #1426 (a performance change on the Rust side only).
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This thread tracks published obs-rust security advisories for bugs that also exist in upstream OBS Studio, until someone reports each one upstream.
Upstream takes security reports only at security@obsproject.com or on their Discord. GitHub private reporting is turned off on obsproject/obs-studio. Upstream also asks reporters to keep a bug confidential for 120 days.
Rules for this thread
Not yet reported upstream
signal_handler_remove_current(libobs/callback/signal.c). Found by @vpacher. Fixed here in callback: Fix signal callback removal across nesting, recursion and registration (split from #1464) #1556 (signal callbacks) and callback: Track the running global signal callback by index #1639 (global callbacks); the reporter confirmed both. Upstream has both paths, unchanged. Ready to send.Ready-to-send report
Backlog: earlier public fixes that upstream still lacks
Each fix below landed publicly in obs-rust. On 2026-10-21 the same file on obsproject/obs-studio master still had the bug. Each line can be sent as it stands, with the PR link as the patch.
HandleChangeChunkSize()accepts a chunk size with bit 31 set from the server. The resulting negativem_inChunkSizecorrupts the chunk read and allocation arithmetic. Fix: reject values below 1. (network, medium-high)DecodeTEA()takes a secureToken of any length from the server. A length of 0 readsv[-1]and divides by zero, and a length that isn't a multiple of 8 reads past the end of the token. Fix: reject both. (network, medium-high)AMF_DecodeandAMF3_Decoderecurse once per nesting level with no limit, so a server's deeply nested objects overflow the stack. Fix: cap the depth. (network, DoS)AMF3_Decodelogs the class and member names with%salthough they aren't NUL-terminated, which reads out of bounds. It also leakscd_propson every class decode. Fix: use%.*sand freecd_props. (network, medium)byte << 24shifts on bytes from the server, which is undefined behaviour. Fix: cast to unsigned before shifting. (network, low)parse_obu_header()setsobu_size = size - 1without accounting for the extension byte or the buffer end, so a crafted OBU reads out of bounds.leb128()also overflows an int from the 5th byte. (media, medium)get_ue_golomb()runs1 << 32on a truncated SPS, which is undefined behaviour. Fix: capiat 31 and shift an unsigned value. (media, low)obs_enum()readscontext->nextafter the callback may have released the last reference, a use-after-free inobs_enum_outputs,obs_enum_encodersandobs_enum_services. It can also hand out encoders that are already being destroyed. Fix: enumerate a snapshot that holds references. (local, medium)on_registry_global_remove_cb()logsdevice_idafterg_hash_table_iter_remove()has freed it, a use-after-free on every camera unplug. Fix: swap the two lines. Upstream PR linux-pipewire: Fix use-after-free in log message obsproject/obs-studio#13698 is open but not merged. (local, low-medium)mNumberBuffersplane pointers into an array ofMAX_AV_PLANESentries without checking the count, so a device reporting more than 8 buffers writes out of bounds. Fix: clamp the count. (device, low-medium)obs_transition_start()deadlocks on the transition's own mutex when the destination already contains that transition, directly or nested. Fix: reject recursive destinations. (local, DoS, borderline)get_buffer2. (file, DoS, borderline)Checked and left out: #200, #228 and #305 (functional bugs, not security), #582 (unreachable), #685 (the code exists only in obs-rust), and #1426 (a performance change on the Rust side only).
All reactions