Mask special bits from peer-supplied SCP receive mode#1032
Open
yosuke-wolfssl wants to merge 1 commit into
Open
Mask special bits from peer-supplied SCP receive mode#1032yosuke-wolfssl wants to merge 1 commit into
yosuke-wolfssl wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the SCP receive path by ensuring peer-supplied file modes cannot propagate setuid/setgid/sticky bits into directory creation or custom receive callbacks, matching the existing behavior on the SCP send path.
Changes:
- Mask peer-supplied SCP mode (
C/Drecords) withWOLFSSH_MODE_MASKwhen storing it inssh->scpFileMode. - Add a
WOLFSSH_TEST_INTERNALwrapper to directly exercise the SCP mode parser in unit tests. - Add a unit test that validates masking behavior, index advancement, and rejection of invalid inputs.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/wolfscp.c |
Masks peer-supplied mode on receive and adds an internal test wrapper for the parser. |
wolfssh/internal.h |
Declares the new internal test wrapper behind WOLFSSH_TEST_INTERNAL and WOLFSSH_SCP. |
tests/unit.c |
Adds and registers a unit test covering mode masking and error paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #1032
Scan targets checked: wolfssh-bugs, wolfssh-src
No new issues found in the changed files. ✅
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The SCP receive path did not mask setuid/setgid/sticky bits out of the
peer-supplied file mode before using it.
GetScpFileMode()parsed the octalmode from a peer-sent
C/Drecord (e.g.D4755 0 dirname) and stored theraw value into
ssh->scpFileModewithout masking. That unmasked value thenpropagated to:
wsScpRecvCallback, which passes it straight toWMKDIR()fordirectory creation, and
scpRecvCbcallback (the documented API contract handed thecallback an unmasked mode).
The send path already masks with
WOLFSSH_MODE_MASK(0777) atsrc/wolfscp.c:318and:355; the receive path had no equivalent. As aresult an authenticated peer could force creation of sticky/setgid
directories inside the SCP base path (the kernel strips setuid/setgid from
mkdir()on Linux but preserves sticky; setgid also survives on BSD/macOS),and a custom callback that applied the mode via
chmod()while running asroot could end up creating setuid files.
Fix
Mask the peer-supplied mode at the single point where it is stored, mirroring
the send path:
Masking at the storage point protects every downstream consumer (
scpRecvCb,the default callback, and
WMKDIR) at once. This strips setuid (04000),setgid (02000), and sticky (01000) while leaving ordinary permission bits
untouched.
Tests
Added
test_ScpGetFileModetotests/unit.c. End-to-end coverage is notpossible because both peers mask the mode on send, so the test drives the
parser directly via a new
WOLFSSH_TEST_INTERNALwrapper(
wolfSSH_TestScpGetFileMode). It covers:C4755->0755,D2755->0755,D1755->0755,D7777->0777, and an ordinary-mode controlC0644->0644.idxis moved past the prefix, four modeoctets, and trailing space.
C8755), bad prefix (X4755),and a buffer shorter than the mode field (
C75) all returnWS_BAD_ARGUMENT.Verification
scripts/scp.testpasses (regular-file transfersunaffected).
tests/unit.testpasses (exit 0, zero failures), including the new test.mutating the
idx/rejection expectations makes those assertions fail —confirming each assertion is real.
AddressSanitizer or UBSan reports, including the short-buffer case.
Files changed
src/wolfscp.c— mask the mode inGetScpFileMode; addwolfSSH_TestScpGetFileModetest wrapper.wolfssh/internal.h— declare the test wrapper (guarded byWOLFSSH_TEST_INTERNAL+WOLFSSH_SCP).tests/unit.c— add and registertest_ScpGetFileMode.