WIP: security: harden untrusted-input handling (issue #148) #176
Draft
jabber.developer2
wants to merge 1 commits from
fix/untrusted-input-148 into master
pull from: fix/untrusted-input-148
merge into: devs:master
devs:master
devs:fix/e2ee-transport-147
devs:feat/cons-show-warning-87
devs:fix/disco-info-null-from
devs:fix/editor-terminal-size
devs:fix/data-at-rest-hardening
devs:fix/omemo-prosody-bootstrap
devs:feat/ai-api-type
devs:ci/docker-hub-publishing
devs:feat/disco-ac
devs:feat/privacy-enhancements
devs:fix/clientid-regression
devs:fix/ai-chat-completions-followup
devs:feat/ai-custom
devs:fix/unencrypted-send
devs:rollback/pre-upstream-merge
devs:fix/autoping-warning-null-domain
devs:fix/pad-dead-space-reclaim
devs:feat/autoping-warning
devs:chore/untrack-gitversion
devs:fix/multiline-pad-clip
devs:fix/issue-112-followups
devs:fix/issue-128-migrate-v3-dedup
devs:fix/delay-timestamp-validation
devs:ref/light-cleanup
devs:fix/history-scroll-pad-redraw-storm
devs:fix/plugin-post-display-incoming-only
devs:merge/upstream-full
devs:merge-improve
devs:chore/remove-chatlog-stage-1
devs:fix/ai-json-encoding
devs:feat/no-db-backlog-114
devs:fix/scroll-non-chat-windows
devs:fix/paged-non-chat-windows
devs:fix/ai-leaks
devs:feat/ai
devs:fix/ai-followups
devs:test/ai-coverage-unit-only
devs:test/ai-coverage
devs:refactor/scroll-mechanism
devs:fix/verify-per-contact-context
devs:feat/no-db-mode
devs:feat/ai-json
devs:feat/pikaur-parity-arch
devs:fix-pikaur-build
devs:feat/upstream-sync
devs:feat/functest-speedup
devs:fix/cwe-134-format-string-audit
devs:ci/separate-build-step
devs:test/autoping-functional-tests
devs:test/db-functional-tests
devs:fix/arch-build
devs:fix/xep-0030-disco-items-error-handling
devs:fix/xep-0030-empty-disco-items
devs:playground/fix/src_refactoring
devs:tests/disco
devs:fix/test-CI-stability
devs:feat/parallel-tests-clean
devs:feat/parallel-functional-tests
devs:fix/functional_tests_v2
devs:fix/functional_tests
devs:fix/connect_max_args
devs:feat/extended_debug_info
devs:playground/fix/scroll-stuck
devs:build/multicore
devs:build/reenable-fedora
devs:build/autoupdate
No Reviewers
Labels
Clear labels
Compat/Breaking
Breaking change that won't be backward compatible
Kind/Bug
Something is not working
Kind/Documentation
Documentation changes
Kind/Enhancement
Improve existing functionality
Kind/Feature
New functionality
Kind/Security
This is security issue
Kind/Testing
Issue or pull request related to testing
Priority
Critical
1
The priority is critical
Priority
High
2
The priority is high
Priority
Low
4
The priority is low
Priority
Medium
3
The priority is medium
Reviewed
Confirmed
1
Issue has been confirmed
Reviewed
Duplicate
2
This issue or pull request already exists
Reviewed
Invalid
3
Invalid issue
Reviewed
Won't Fix
3
This issue won't be fixed
Status
Abandoned
3
Somebody has started to work on this but abandoned work
Status
Blocked
1
Something is blocking this issue or pull request
Status
Need More Info
2
Feedback is required to reproduce issue or to continue work
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: devs/cproof#176
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
No description provided.
Delete Branch "fix/untrusted-input-148"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Covers the input-validation and memory-safety tasks of issue #148 (T02, T10, T11). Every change is on a path that processes data controlled by a remote peer or by the server: presence and message handlers, the URL commands, the desktop notifier, the OX/OMEMO helpers and the disco cache.
T02 — crashes on malformed
from(REQ-INP-01)Four receive-path handlers dereferenced the result of
jid_create()without a NULL check, so a stanza with a missing or malformedfromterminated the client:_presence_error_handler()— MUC join errors_subscribed_handler()/_unsubscribed_handler()— subscription presence, reachable from any remote JID_should_ignore_based_on_silence()— withsilence.non-rosterenabled this is on the path of every incoming messageTwo MUC handlers (
_muc_user_self_handler,_muc_user_occupant_handler) got the same guard, defensively: the caller validates today, but the handlers are one refactor away from being reachable directly._subscribe_handler()logged the missing attribute and then continued into the NULL dereference anyway — it now returns.T11 — untrusted input reaching the shell, the terminal and the storage layer
/url open,/url save(REQ-INP-06) — the URL comes out of a received message and was passed to the configured opener command with no scheme check. Both commands now accept onlyhttp,httpsandaesgcm; afile:,javascript:ordata:URL is refused with an error line. User-visible behaviour change.system(), so a message body containing`,$(…)or;executed as a command. Replaced withg_spawn_async()and an argv, where the message is a single argument the shell never sees.<stanza-id>elements are already gated on the archive announcing XEP-0359 support; MAM results were not, so any server could inject ids that end up stored as stable identifiers. The same gate now applies, falling back to the account's own bare JID when the archive is implicit.str_neutralize_untrusted()replaces C0/C1 control characters (including ESC) and the bidi embedding/override/isolate ranges with U+FFFD. It runs in_clean_incoming_message(), i.e. after decryption, so OTR, PGP and OX plaintext is covered by the same pass. Tab and newlines are kept, as is LRM/RLM (U+200E/U+200F) — legitimate RTL text needs them.T10 — memory safety
strcpy/strcat/allocain the OX signcrypt helper andsprintfin the OMEMO AESGCM fragment builder, the last-activity handler and the MUC trigger printer replaced withg_strdup_printf,g_strndupandg_snprintf.gcry_malloc_secure()may return NULL under a secure-memory limit; that return is now checked.malloc()and fed the result straight intomemcpy(). They now useg_malloc, which aborts rather than returning NULL, with an explicit zero-length case sinceg_malloc(0)does return NULL. The matchingfree()calls inomemo_bundle_publish()becameg_free().-Werror=vlaenforced in both build systems, so a stack array sized from peer input cannot come back. Two of the removed VLAs were remote-sized: the disco#info feature count incaps_add_by_ver()(nowg_malloc_n) and a word length in the line-wrapping code (which only ever needed room for one UTF-8 character). Enabling the flag also surfaced, in the plugin autocompleter bindings, a one-past-the-end stack write and a leak on the argument-validation early return.Resolve #148
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.