Skip to content

CWE-400: Uncontrolled Resource Consumption for sftp#1017

Open
loganaden wants to merge 1 commit into
wolfSSL:masterfrom
cyberstormdotmu:wolfssh_dos
Open

CWE-400: Uncontrolled Resource Consumption for sftp#1017
loganaden wants to merge 1 commit into
wolfSSL:masterfrom
cyberstormdotmu:wolfssh_dos

Conversation

@loganaden

Copy link
Copy Markdown

Enforce a per-session cap on open SFTP file handles before accepting additional retained handles. When the cap is reached, the server must reject the new handle and must not retain the newly opened file descriptor.

Signed-off-by: Loganaden Velvindron <logan@cyberstorm.mu>
@wolfSSL-Bot

Copy link
Copy Markdown

Can one of the admins verify this patch?

@ejohnstown

ejohnstown commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Can we treat this as a bug report and fix it another way? Or would you fill out a contributor agreement? The issue is I'm removing the functions this modifies. I have another spot something like this can be added.

@loganaden

Copy link
Copy Markdown
Author

@ejohnstown sure. I can fill in the CLA.

@ejohnstown

Copy link
Copy Markdown
Contributor

I'll need you to send an email to support@wolfssl.com. Please include this PR number and your github username. Say that you need a contributor agreement. They will set you up.

Note, this code won't apply any more after one of my PRs is merged. Would you mind porting this over when mine is merged?

@loganaden

Copy link
Copy Markdown
Author

Sure. I've sent the request for CLA.

@loganaden

Copy link
Copy Markdown
Author

CLA signed.

@loganaden

Copy link
Copy Markdown
Author

@ejohnstown can I push now ?

@dgarske

dgarske commented Jun 17, 2026

Copy link
Copy Markdown
Member

@ejohnstown can I push now ?

Hi @loganaden you are welcome to push code all you want. The CLA will be reviewed internally and once approved we will let you know. But don't let it stop you for pushing changes to your PR's or opening new ones. Thank you

@ejohnstown

Copy link
Copy Markdown
Contributor

@loganaden, the other PR has been merged. Your PR needs some conflict resolution. Your CLA needs to move through our system. Once both are complete, I can merge this. Thank you for the fix!

@loganaden

Copy link
Copy Markdown
Author

@ejohnstown CLA signed. Working on updating the PR.

@aidangarske aidangarske self-requested a review July 9, 2026 01:18
@aidangarske aidangarske self-assigned this Jul 9, 2026

@aidangarske aidangarske left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Skoll Multi-Scan Review

Modes: review + review-security + bugsOverall recommendation: REQUEST_CHANGES
Findings: 5 total — 5 posted, 0 skipped
5 finding(s) posted as inline comments (see file-level comments below)

Posted findings

  • [High] [review] Handle cap is enforced only after opening the filesystem objectsrc/wolfsftp.c:4681-4684
  • [Medium] [review+review-security] New SFTP handle cap has no test coveragesrc/wolfsftp.c:4661-4685
  • [Medium] [review+review-security] Handle cap covers file handles only; directory OPENDIR path remains unboundedsrc/wolfsftp.c:4661-4685
  • [Low] [review] Cap constant defined mid-source instead of with other SFTP limits in the headersrc/wolfsftp.c:4661-4663
  • [Low] [review] WS_MEMORY_E reused for resource-limit-reached casesrc/wolfsftp.c:4682-4684

Review generated by Skoll

Comment thread src/wolfsftp.c
return WS_BUFFER_E;
}

for (cur = ssh->handleList; cur != NULL; cur = cur->next) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🔴 [High] Handle cap is enforced only after opening the filesystem object · bug

The new cap rejection happens inside SFTP_AddHandleNode, but both wolfSSH_SFTP_RecvOpen paths call the platform open routine first: POSIX WOPEN at src/wolfsftp.c:2402 and Windows WS_CreateFileA at src/wolfsftp.c:2578, with SFTP_AddHandleNode only invoked afterward at src/wolfsftp.c:2420. Once the session is at WOLFSSH_MAX_SFTP_HANDLES, a client can send an OPEN with create/truncate flags; the server opens, creates, or truncates the file, then this new check rejects the handle and cleanup closes it. The descriptor is not retained, but the rejected open still has filesystem side effects. This PR turns what used to be a rare post-open allocation-failure path into the normal deterministic behavior at the configured cap. Verified against source: WOPEN at line 2402 precedes the SFTP_AddHandleNode cap check reached at line 2420. Note: the review-security scan reviewed this same reject path and concluded the descriptor is not leaked (cleanup closes fd and skips SFTP_RemoveHandleNode); the concern here is the pre-open filesystem side effect, not a leak.

Fix: Add a preflight capacity check before WOPEN / WS_CreateFileA in wolfSSH_SFTP_RecvOpen, and keep the SFTP_AddHandleNode check as a backstop. If the cap is already reached, build the SFTP failure response without calling the filesystem open routine so rejected opens do not create, truncate, or otherwise modify files.

Comment thread src/wolfsftp.c
}


#ifndef WOLFSSH_MAX_SFTP_HANDLES

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🟠 [Medium] New SFTP handle cap has no test coverage · Missing Tests

Consensus across the review and review-security scans (review rated Medium/SUGGEST; review-security rated Info; stricter Medium kept). The new cap branch (if (++count >= WOLFSSH_MAX_SFTP_HANDLES) return WS_MEMORY_E;) is not exercised by any test. The cap resolves to exactly 64 concurrent handles (<=63 existing -> add succeeds, >=64 -> reject). Existing regression coverage in tests/regress.c only adds one or two handles and already unit-tests SFTP_AddHandleNode directly (TestSftpRemoveHandleHeadUpdate, TestSftpValidateFileHandle), so a targeted boundary test is low-cost. No test fills the list to WOLFSSH_MAX_SFTP_HANDLES, verifies the max boundary, or checks that the rejected handle is not retained. This is exactly the off-by-one and cleanup-sensitive path that should have direct coverage; without it a future regression that off-by-ones the limit or drops the check would pass CI silently.

Fix: Add a regress.c test that inserts WOLFSSH_MAX_SFTP_HANDLES unique handles (asserting WS_SUCCESS each time), asserts the next SFTP_AddHandleNode returns WS_MEMORY_E, verifies the rejected handle is absent and the list count stays capped, then removes one and confirms a subsequent add succeeds again. An OPEN-level test with a small configured cap driving wolfSSH_SFTP_RecvOpen would also confirm the newly opened descriptor is closed on the cap-failure path and catch the pre-open side-effect bug.

Comment thread src/wolfsftp.c
}


#ifndef WOLFSSH_MAX_SFTP_HANDLES

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🟠 [Medium] Handle cap covers file handles only; directory OPENDIR path remains unbounded · Security

Consensus across the review and review-security scans (review rated Medium/SUGGEST; review-security rated Info; stricter Medium kept). The cap only bounds file handles in ssh->handleList. Directory handles opened via wolfSSH_SFTP_RecvOpenDir are tracked in the separate, uncapped ssh->dirList (WS_DIR_LIST): verified at src/wolfsftp.c:2731-2758 (and inserts at 2757-2758 / 2917-2918), that function WMALLOCs a new node and prepends it with no count check and never routes through SFTP_AddHandleNode. An attacker can therefore still drive unbounded memory/descriptor consumption by repeatedly sending WOLFSSH_FTP_OPENDIR without a matching CLOSE — the same CWE-400 resource-exhaustion class this PR targets. This is a pre-existing gap (not introduced by this PR); may be intentionally out of scope per the PR description ("open SFTP file handles"), so raised as a question.

Fix: Confirm whether directory handles are in scope; if so, apply an analogous per-session count/limit to ssh->dirList inside wolfSSH_SFTP_RecvOpenDir (or a combined open-handle budget) before retaining a new WS_DIR_LIST node, so the DoS mitigation is complete.

Comment thread src/wolfsftp.c
}


#ifndef WOLFSSH_MAX_SFTP_HANDLES

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🔵 [Low] Cap constant defined mid-source instead of with other SFTP limits in the header · convention

WOLFSSH_MAX_SFTP_HANDLES is defined mid-.c-file, immediately above the function (verified at src/wolfsftp.c:4661-4663). The codebase convention places related SFTP limits in the public header — WOLFSSH_MAX_HANDLE lives in wolfssh/wolfsftp.h and WOLFSSH_MAX_FILENAME in wolfssh/ssh.h/port.h. Defining the tunable in wolfssh/wolfsftp.h (near WOLFSSH_MAX_HANDLE) makes it discoverable and configurable through the normal header/user_settings path. The #ifndef guard does still allow -DWOLFSSH_MAX_SFTP_HANDLES=... overrides, so this is placement/discoverability only.

Fix: Relocate the #ifndef WOLFSSH_MAX_SFTP_HANDLES / #define ... 64 / #endif block into wolfssh/wolfsftp.h alongside WOLFSSH_MAX_HANDLE for consistency and discoverability.

Comment thread src/wolfsftp.c
}

for (cur = ssh->handleList; cur != NULL; cur = cur->next) {
if (++count >= WOLFSSH_MAX_SFTP_HANDLES) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🔵 [Low] WS_MEMORY_E reused for resource-limit-reached case · style

Returning WS_MEMORY_E when the handle cap is hit conflates a policy/limit rejection with an allocation failure. Callers treat any non-success generically ("Unable to store handle" -> FXP FAILURE), so behavior is correct, but the error semantics are slightly misleading for anyone debugging or reading logs. There is no obvious dedicated error code today, so this is a note rather than a defect.

Fix: Consider a distinct code (e.g. a WS_RESOURCE/limit error) if one exists or is worth adding; otherwise leave WS_MEMORY_E and note the intent.

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.

5 participants