Skip to content

fix: validate recording output paths - #1755

Merged
summeroff merged 2 commits into
stagingfrom
fix/h1-3335237-safe-recording
Aug 9, 2026
Merged

fix: validate recording output paths#1755
summeroff merged 2 commits into
stagingfrom
fix/h1-3335237-safe-recording

Conversation

@summeroff

@summeroff summeroff commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary

companion to obs-studio): reject unsafe recording/replay directories at start via os_is_path_safe.

Covers simple/advanced recording and both replay buffers.

Test plan

  • Start recording/replay with normal path
  • Start with symlink/junction directory path → rejected

@summeroff summeroff changed the title fix: H1-3335237 validate recording output paths fix: validate recording output paths Aug 6, 2026
@summeroff
summeroff requested a lite review from Copilot August 6, 2026 01:28

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

This PR tightens recording/replay-buffer startup validation by rejecting unsafe output directories (e.g., symlink/junction paths) using os_is_path_safe, aligning behavior with upstream OBS safety expectations.

Changes:

  • Add os_is_path_safe validation for simple recording output directory before starting recording.
  • Add os_is_path_safe validation for simple and advanced replay buffer output directory before starting replay buffer.
  • Add os_is_path_safe validation for advanced recording output directory before building the final output file path.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
obs-studio-server/source/osn-simple-replay-buffer.cpp Rejects unsafe/empty replay buffer directory before output update/start.
obs-studio-server/source/osn-simple-recording.cpp Rejects unsafe/empty recording directory before constructing the final recording file path.
obs-studio-server/source/osn-advanced-replay-buffer.cpp Rejects unsafe/empty replay buffer directory before output update/start.
obs-studio-server/source/osn-advanced-recording.cpp Rejects unsafe/empty recording directory before constructing the final recording file path.

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

Comment thread obs-studio-server/source/osn-advanced-recording.cpp Outdated

if (!recording->path.size()) {
if (!recording->path.size() || !os_is_path_safe(recording->path.c_str())) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Rather than reword the shared message, the check is now split so each branch says what actually tripped:

if (!recording->path.size()) {
    PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");
}

if (!os_is_path_safe(recording->path.c_str())) {
    PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");
}

PRETTY_ERROR_RETURN puts the string in both the IPC return value and the log, so this reaches the desktop error and the support log. Applied consistently across all four files.


obs_output_set_video_encoder(recording->GetOutput(), recording->videoEncoder);
if (!recording->path.size() || !os_is_path_safe(recording->path.c_str())) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Rather than reword the shared message, the check is now split so each branch says what actually tripped:

if (!recording->path.size()) {
    PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");
}

if (!os_is_path_safe(recording->path.c_str())) {
    PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");
}

PRETTY_ERROR_RETURN puts the string in both the IPC return value and the log, so this reaches the desktop error and the support log. Applied consistently across all four files.


if (!replayBuffer->path.size()) {
if (!replayBuffer->path.size() || !os_is_path_safe(replayBuffer->path.c_str())) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Rather than reword the shared message, the check is now split so each branch says what actually tripped:

if (!recording->path.size()) {
    PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");
}

if (!os_is_path_safe(recording->path.c_str())) {
    PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");
}

PRETTY_ERROR_RETURN puts the string in both the IPC return value and the log, so this reaches the desktop error and the support log. Applied consistently across all four files.


if (!replayBuffer->path.size()) {
if (!replayBuffer->path.size() || !os_is_path_safe(replayBuffer->path.c_str())) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Rather than reword the shared message, the check is now split so each branch says what actually tripped:

if (!recording->path.size()) {
    PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");
}

if (!os_is_path_safe(recording->path.c_str())) {
    PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");
}

PRETTY_ERROR_RETURN puts the string in both the IPC return value and the log, so this reaches the desktop error and the support log. Applied consistently across all four files.

summeroff and others added 2 commits August 9, 2026 23:50
Splitting the empty-path and os_is_path_safe() checks lets the IPC error
and the log line say which one tripped, so a rejected symlink/junction
directory is diagnosable instead of just "Invalid recording path."

Also switch osn-encoders.hpp to a quoted include, matching every other
consumer of that header.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@summeroff
summeroff force-pushed the fix/h1-3335237-safe-recording branch from 014dd0f to 0387e73 Compare August 9, 2026 21:55
@summeroff
summeroff requested a balanced review from Copilot August 9, 2026 22:36

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

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (8)

obs-studio-server/source/osn-simple-recording.cpp:406

  • os_is_path_safe also returns false when a path component is missing, inaccessible, malformed, or not a directory, so this message can incorrectly blame a symbolic link/junction for ordinary path failures. Make the message cover those failure modes as well.
		PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");

obs-studio-server/source/osn-advanced-recording.cpp:291

  • os_is_path_safe also returns false when a path component is missing, inaccessible, malformed, or not a directory, so this message can incorrectly blame a symbolic link/junction for ordinary path failures. Make the message cover those failure modes as well.
		PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");

obs-studio-server/source/osn-simple-replay-buffer.cpp:152

  • os_is_path_safe also returns false when a path component is missing, inaccessible, malformed, or not a directory, so this message can incorrectly blame a symbolic link/junction for ordinary path failures. Make the message cover those failure modes as well.
		PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");

obs-studio-server/source/osn-advanced-replay-buffer.cpp:210

  • os_is_path_safe also returns false when a path component is missing, inaccessible, malformed, or not a directory, so this message can incorrectly blame a symbolic link/junction for ordinary path failures. Make the message cover those failure modes as well.
		PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");

obs-studio-server/source/osn-simple-recording.cpp:406

  • The simple-recording integration suite exercises start() with normal paths, but no automated case verifies that this new branch rejects a Windows symlink/junction path and propagates the intended error. Add a regression case so this security boundary cannot silently disappear.

This issue also appears on line 406 of the same file.

	if (!os_is_path_safe(recording->path.c_str())) {
		PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");

obs-studio-server/source/osn-advanced-recording.cpp:291

  • The advanced-recording integration suite exercises start() with normal paths, but no automated case verifies that this new branch rejects a Windows symlink/junction path and propagates the intended error. Add a regression case so this security boundary cannot silently disappear.

This issue also appears on line 291 of the same file.

	if (!os_is_path_safe(recording->path.c_str())) {
		PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");

obs-studio-server/source/osn-simple-replay-buffer.cpp:152

  • The simple replay-buffer integration suite exercises start() with normal paths, but no automated case verifies that this new branch rejects a Windows symlink/junction path and propagates the intended error. Add a regression case so this security boundary cannot silently disappear.

This issue also appears on line 152 of the same file.

	if (!os_is_path_safe(replayBuffer->path.c_str())) {
		PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");

obs-studio-server/source/osn-advanced-replay-buffer.cpp:210

  • The advanced replay-buffer integration suite exercises start() with normal paths, but no automated case verifies that this new branch rejects a Windows symlink/junction path and propagates the intended error. Add a regression case so this security boundary cannot silently disappear.

This issue also appears on line 210 of the same file.

	if (!os_is_path_safe(replayBuffer->path.c_str())) {
		PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Unsafe recording path: symbolic links and junctions are not allowed.");

@summeroff
summeroff merged commit 19278f8 into staging Aug 9, 2026
21 checks passed
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.

2 participants