Skip to content

Commit

Permalink
Merge pull request #1892 from onionshare/security-updates
Browse files Browse the repository at this point in the history
Release 2.6.2 (security updates)
  • Loading branch information
SaptakS committed Mar 21, 2024
2 parents 3083382 + 23d409d commit 6665274
Show file tree
Hide file tree
Showing 46 changed files with 3,905 additions and 1,916 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# OnionShare Changelog

## 2.6.2

* Security fix: Removes newlines from History item path
* Security fix: Set a maximum length of 524288 characters for text messages in Receive mode
* Security fix: Allows only specific ASCII characters for usernames and removes control characters
* Security fix: Forcefully disconnect user from chat on `disconnect` event
* Security fix: Handle username validation excpeptions to prevent silent joining

## 2.6.1

* Release updates: Automate builds with CI, make just 64-bit Windows release, make a single universal2 release for both Intel and Apple Silicon macOS
Expand Down
7 changes: 2 additions & 5 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ Create a Windows 11 VM, and set it up like this:
- Download and install [gpg4win](https://gpg4win.org/). Add `C:\Program Files (x86)\GnuPG\bin` to your path.
- Install the Windows SDK from here: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/.
- Go to https://dotnet.microsoft.com/download/dotnet-framework and download and install .NET Framework 3.5 SP1 Runtime. I downloaded `dotnetfx35.exe`.
- Go to https://wixtoolset.org/docs/wix3/ and download and install WiX toolset. I downloaded `wix311.exe`. Add `C:\Program Files (x86)\WiX Toolset v3.11\bin` to the path.
- Go to https://wixtoolset.org/docs/wix3/ and download and install WiX toolset. I downloaded `wix314.exe`. Add `C:\Program Files (x86)\WiX Toolset v3.14\bin` to the path.

Clone the OnionShare git repo and checkout the release tag.

Expand Down Expand Up @@ -267,9 +267,7 @@ export APPLE_PASSWORD="changeme" # app-specific Apple ID password
export VERSION=$(cat ../cli/onionshare_cli/resources/version.txt)

# Notarize it
xcrun altool --notarize-app --primary-bundle-id "com.micahflee.onionshare" -u "micah@micahflee.com" -p "$APPLE_PASSWORD" --file dist/OnionShare-$VERSION.dmg
# Wait for it to get approved, check status with
xcrun altool --notarization-history 0 -u "micah@micahflee.com" -p "$APPLE_PASSWORD"
xcrun notarytool submit --apple-id "micah@micahflee.com" --team-id N9B95FDWH4 --password "$APPLE_PASSWORD" --progress --wait dist/OnionShare-$VERSION.dmg
# After it's approved, staple the ticket
xcrun stapler staple dist/OnionShare-$VERSION.dmg
```
Expand All @@ -290,7 +288,6 @@ After following all of the previous steps, gather these files:

- `onionshare_${VERSION}_amd64.snap`
- `OnionShare.flatpak` (rename to `OnionShare-$VERSION.flatpak`)
- `OnionShare-win32-$VERSION.msi`
- `OnionShare-win64-$VERSION.msi`
- `OnionShare-$VERSION.dmg`
- `onionshare-$VERSION.tar.gz`
Expand Down
2 changes: 1 addition & 1 deletion cli/onionshare_cli/resources/templates/receive.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ <h1>{% if title %}{{ title }}{% else %}OnionShare Dropbox{% endif %}</h1>
<p><input type="file" id="file-select" name="file[]" multiple /></p>
{% endif %}
{% if not disable_text %}
<p><textarea id="text" name="text" placeholder="Write a message"></textarea></p>
<p><textarea id="text" name="text" placeholder="Write a message (max length 524288 characters)" maxlength="524288"></textarea></p>
{% endif %}
<p><button type="submit" id="send-button" class="button">Submit</button></p>
</form>
Expand Down
2 changes: 1 addition & 1 deletion cli/onionshare_cli/resources/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.6.1
2.6.2
2 changes: 1 addition & 1 deletion cli/onionshare_cli/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(self, common, config=False):
"zh_Hans": "中文 (简体)", # Simplified Chinese
"hr": "Hrvatski", # Croatian
"cs": "čeština", # Czech
# "da": "Dansk", # Danish
"da": "Dansk", # Danish
# "nl": "Nederlands", # Dutch
"en": "English", # English
"fi": "Suomi", # Finnish
Expand Down
93 changes: 70 additions & 23 deletions cli/onionshare_cli/web/chat_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import unicodedata

from flask import request, render_template, make_response, jsonify, session
from flask_socketio import emit, ConnectionRefusedError
Expand Down Expand Up @@ -47,15 +48,45 @@ def __init__(self, common, web):

self.define_routes()

def validate_username(self, username):
username = username.strip()
return (
username
and username.isascii()
and username not in self.connected_users
and len(username) < 128
def remove_unallowed_characters(self, text):
"""
Sanitize username to remove unwanted characters.
Allowed characters right now are:
- all ASCII numbers
- all ASCII letters
- dash, underscore and single space
"""

def allowed_character(ch):
allowed_unicode_categories = [
'L', # All letters
'N', # All numbers
]
allowed_special_characters = [
'-', # dash
'_', # underscore
' ', # single space
]
return (
unicodedata.category(ch)[0] in allowed_unicode_categories and ord(ch) < 128
) or ch in allowed_special_characters

return "".join(
ch for ch in text if allowed_character(ch)
)

def validate_username(self, username):
try:
username = self.remove_unallowed_characters(username.strip())
return (
username
and username not in self.connected_users
and len(username) < 128
)
except Exception as e:
self.common.log("ChatModeWeb", "validate_username", e)
return False

def define_routes(self):
"""
The web app routes for chatting
Expand All @@ -77,13 +108,17 @@ def index():

self.web.add_request(self.web.REQUEST_LOAD, request.path)
return render_template(
"chat.html",
static_url_path=self.web.static_url_path,
username=session.get("name"),
title=self.web.settings.get("general", "title"),
"chat.html",
static_url_path=self.web.static_url_path,
username=session.get("name"),
title=self.web.settings.get("general", "title"),
)

@self.web.app.route("/update-session-username", methods=["POST"], provide_automatic_options=False)
@self.web.app.route(
"/update-session-username",
methods=["POST"],
provide_automatic_options=False,
)
def update_session_username():
history_id = self.cur_history_id
data = request.get_json()
Expand Down Expand Up @@ -122,6 +157,8 @@ def server_connect():
A status message is broadcast to all people in the room."""
if self.validate_username(session.get("name")):
self.connected_users.append(session.get("name"))
# Store the session id for the user
session["socketio_session_id"] = request.sid
emit(
"status",
{
Expand All @@ -133,7 +170,7 @@ def server_connect():
broadcast=True,
)
else:
raise ConnectionRefusedError('You are active from another session!')
raise ConnectionRefusedError('Invalid session')

@self.web.socketio.on("text", namespace="/chat")
def text(message):
Expand All @@ -153,9 +190,9 @@ def update_username(message):
new_name = message.get("username", "").strip()
if self.validate_username(new_name):
session["name"] = new_name
self.connected_users[
self.connected_users.index(current_name)
] = session.get("name")
self.connected_users[self.connected_users.index(current_name)] = (
session.get("name")
)
emit(
"status",
{
Expand All @@ -178,13 +215,23 @@ def update_username(message):
def disconnect():
"""Sent by clients when they disconnect.
A status message is broadcast to all people in the server."""
user_already_disconnected = False
if session.get("name") in self.connected_users:
self.connected_users.remove(session.get("name"))
emit(
"status",
{
"msg": "{} has left the room.".format(session.get("name")),
"connected_users": self.connected_users,
},
broadcast=True,
else:
user_already_disconnected = True

# Forcefully disconnect the user
self.web.socketio.server.disconnect(
sid=session.get("socketio_session_id"), namespace="/chat"
)

if not user_already_disconnected:
emit(
"status",
{
"msg": "{} has left the room.".format(session.get("name")),
"connected_users": self.connected_users,
},
broadcast=True,
)
7 changes: 5 additions & 2 deletions cli/onionshare_cli/web/receive_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ def upload(ajax=False):
if files_received > 0:
msg = f"Uploaded {files_msg}"
else:
msg = "Nothing submitted"
if not self.web.settings.get("receive", "disable_text"):
msg = "Nothing submitted or message was too long (> 524288 characters)"
else:
msg = "Nothing submitted"

if ajax:
info_flashes.append(msg)
Expand Down Expand Up @@ -462,7 +465,7 @@ def __init__(self, environ, populate_request=True, shallow=False):
self.includes_message = False
if not self.web.settings.get("receive", "disable_text"):
text_message = self.form.get("text")
if text_message:
if text_message and len(text_message) <= 524288:
if text_message.strip() != "":
self.includes_message = True

Expand Down
2 changes: 1 addition & 1 deletion cli/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "onionshare_cli"
version = "2.6.1"
version = "2.6.2"
description = "OnionShare lets you securely and anonymously send and receive files. It works by starting a web server, making it accessible as a Tor onion service, and generating an unguessable web address so others can download files from you, or upload files to you. It does _not_ require setting up a separate server or using a third party file-sharing service."
authors = ["Micah Lee <micah@micahflee.com>"]
license = "GPLv3+"
Expand Down
1 change: 1 addition & 0 deletions desktop/onionshare/resources/countries/da.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"AF": "Afghanistan", "AL": "Albanien", "DZ": "Algeriet", "AS": "Amerikansk Samoa", "AD": "Andorra", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarktis", "AG": "Antigua og Barbuda", "AR": "Argentina", "AM": "Armenien", "AW": "Aruba", "AZ": "Aserbajdsjan", "AU": "Australien", "BS": "Bahamas", "BH": "Bahrain", "BD": "Bangladesh", "BB": "Barbados", "BE": "Belgien", "BZ": "Belize", "BJ": "Benin", "BM": "Bermuda", "BT": "Bhutan", "BO": "Bolivia", "BA": "Bosnien-Hercegovina", "BW": "Botswana", "BV": "Bouvet\u00f8en", "BR": "Brasilien", "BN": "Brunei", "BG": "Bulgarien", "BF": "Burkina Faso", "BI": "Burundi", "KH": "Cambodja", "CM": "Cameroun", "CA": "Canada", "KY": "Cayman\u00f8erne", "CL": "Chile", "CC": "Cocos\u00f8erne", "CO": "Colombia", "KM": "Comorerne", "CG": "Congo-Brazzaville", "CD": "Congo-Kinshasa", "CK": "Cook\u00f8erne", "CR": "Costa Rica", "CU": "Cuba", "CW": "Cura\u00e7ao", "CY": "Cypern", "DK": "Danmark", "VI": "De Amerikanske Jomfru\u00f8er", "VG": "De Britiske Jomfru\u00f8er", "AE": "De Forenede Arabiske Emirater", "TF": "De Franske Besiddelser i Det Sydlige Indiske Ocean og Antarktis", "BQ": "De tidligere Nederlandske Antiller", "CF": "Den Centralafrikanske Republik", "DO": "Den Dominikanske Republik", "IO": "Det Britiske Territorium i Det Indiske Ocean", "DJ": "Djibouti", "DM": "Dominica", "EC": "Ecuador", "EG": "Egypten", "SV": "El Salvador", "CI": "Elfenbenskysten", "ER": "Eritrea", "EE": "Estland", "SZ": "Eswatini", "ET": "Etiopien", "FK": "Falklands\u00f8erne", "FJ": "Fiji", "PH": "Filippinerne", "FI": "Finland", "FR": "Frankrig", "GF": "Fransk Guyana", "PF": "Fransk Polynesien", "FO": "F\u00e6r\u00f8erne", "GA": "Gabon", "GM": "Gambia", "GE": "Georgien", "GH": "Ghana", "GI": "Gibraltar", "GD": "Grenada", "GR": "Gr\u00e6kenland", "GL": "Gr\u00f8nland", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GN": "Guinea", "GW": "Guinea-Bissau", "GY": "Guyana", "HT": "Haiti", "HM": "Heard Island og McDonald Islands", "NL": "Holland", "HN": "Honduras", "BY": "Hviderusland", "IN": "Indien", "ID": "Indonesien", "IQ": "Irak", "IR": "Iran", "IE": "Irland", "IS": "Island", "IM": "Isle of Man", "IL": "Israel", "IT": "Italien", "JM": "Jamaica", "JP": "Japan", "JO": "Jordan", "CX": "Jule\u00f8en", "CV": "Kap Verde", "KZ": "Kasakhstan", "KE": "Kenya", "CN": "Kina", "KG": "Kirgisistan", "KI": "Kiribati", "HR": "Kroatien", "KW": "Kuwait", "LA": "Laos", "LS": "Lesotho", "LV": "Letland", "LB": "Libanon", "LR": "Liberia", "LY": "Libyen", "LI": "Liechtenstein", "LT": "Litauen", "LU": "Luxembourg", "MG": "Madagaskar", "MW": "Malawi", "MY": "Malaysia", "MV": "Maldiverne", "ML": "Mali", "MT": "Malta", "MA": "Marokko", "MQ": "Martinique", "MR": "Mauretanien", "MU": "Mauritius", "YT": "Mayotte", "MX": "Mexico", "MD": "Moldova", "MC": "Monaco", "MN": "Mongoliet", "ME": "Montenegro", "MS": "Montserrat", "MZ": "Mozambique", "MM": "Myanmar (Burma)", "NA": "Namibia", "NR": "Nauru", "NP": "Nepal", "NZ": "New Zealand", "NI": "Nicaragua", "NE": "Niger", "NG": "Nigeria", "NU": "Niue", "KP": "Nordkorea", "MK": "Nordmakedonien", "NF": "Norfolk Island", "NO": "Norge", "NC": "Ny Kaledonien", "OM": "Oman", "PK": "Pakistan", "PW": "Palau", "PA": "Panama", "PG": "Papua Ny Guinea", "PY": "Paraguay", "PE": "Peru", "PN": "Pitcairn", "PL": "Polen", "PT": "Portugal", "PR": "Puerto Rico", "QA": "Qatar", "RE": "R\u00e9union", "RO": "Rum\u00e6nien", "RU": "Rusland", "RW": "Rwanda", "BL": "Saint Barth\u00e9lemy", "KN": "Saint Kitts og Nevis", "LC": "Saint Lucia", "MF": "Saint Martin", "PM": "Saint Pierre og Miquelon", "VC": "Saint Vincent og Grenadinerne", "SB": "Salomon\u00f8erne", "WS": "Samoa", "SM": "San Marino", "ST": "S\u00e3o Tom\u00e9 og Pr\u00edncipe", "HK": "SAR Hongkong", "MO": "SAR Macao", "SA": "Saudi-Arabien", "CH": "Schweiz", "SN": "Senegal", "RS": "Serbien", "SC": "Seychellerne", "SL": "Sierra Leone", "SG": "Singapore", "SX": "Sint Maarten", "SK": "Slovakiet", "SI": "Slovenien", "SO": "Somalia", "GS": "South Georgia og De Sydlige Sandwich\u00f8er", "ES": "Spanien", "LK": "Sri Lanka", "SH": "St. Helena", "GB": "Storbritannien", "SD": "Sudan", "SR": "Surinam", "SJ": "Svalbard og Jan Mayen", "SE": "Sverige", "ZA": "Sydafrika", "KR": "Sydkorea", "SS": "Sydsudan", "SY": "Syrien", "TJ": "Tadsjikistan", "TW": "Taiwan", "TZ": "Tanzania", "TD": "Tchad", "TH": "Thailand", "TL": "Timor-Leste", "CZ": "Tjekkiet", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad og Tobago", "TN": "Tunesien", "TM": "Turkmenistan", "TC": "Turks- og Caicos\u00f8erne", "TR": "Tyrkiet", "DE": "Tyskland", "UG": "Uganda", "UA": "Ukraine", "HU": "Ungarn", "UY": "Uruguay", "US": "USA", "UZ": "Usbekistan", "VU": "Vanuatu", "VA": "Vatikanstaten", "VE": "Venezuela", "EH": "Vestsahara", "VN": "Vietnam", "WF": "Wallis og Futuna", "YE": "Yemen", "ZM": "Zambia", "ZW": "Zimbabwe", "GQ": "\u00c6kvatorialguinea", "AT": "\u00d8strig", "AX": "\u00c5land"}
5 changes: 4 additions & 1 deletion desktop/onionshare/tab/mode/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import os
from datetime import datetime
from PySide6 import QtCore, QtWidgets, QtGui
from urllib.parse import unquote

from ... import strings
from ...widgets import Alert
Expand Down Expand Up @@ -464,7 +465,9 @@ def __init__(self, common, data, path):
self.common = common

self.id = id
self.path = path
# Decode and sanitize the path to remove newlines
decoded_path = unquote(path)
self.path = decoded_path.replace("\r", "").replace("\n", "")
self.total_bytes = 0
self.downloaded_bytes = 0
self.started = time.time()
Expand Down
2 changes: 1 addition & 1 deletion desktop/org.onionshare.OnionShare.appdata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
<update_contact>micah@micahflee.com</update_contact>
<content_rating type="oars-1.1" />
<releases>
<release type="development" date="2024-02-20" version="2.6.1" />
<release type="development" date="2024-03-18" version="2.6.2" />
</releases>
</component>
2 changes: 1 addition & 1 deletion desktop/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion desktop/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "onionshare"
version = "2.6.1"
version = "2.6.2"
description = "OnionShare lets you securely and anonymously send and receive files. It works by starting a web server, making it accessible as a Tor onion service, and generating an unguessable web address so others can download files from you, or upload files to you. It does _not_ require setting up a separate server or using a third party file-sharing service."
authors = ["Micah Lee <micah@micahflee.com>"]
license = "GPLv3+"
Expand Down
2 changes: 1 addition & 1 deletion desktop/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import setuptools

# The version must be hard-coded because Snapcraft won't have access to ../cli
version = "2.6.1"
version = "2.6.2"

setuptools.setup(
name="onionshare",
Expand Down
2 changes: 1 addition & 1 deletion docs/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
VERSION=$(cat ../cli/onionshare_cli/resources/version.txt)

# Supported locales
LOCALES="en fr de el pl ru es tr uk vi"
LOCALES="en fr de el ja pl ru es tr uk vi"

# Generate English .po files
make gettext
Expand Down
Binary file modified docs/gettext/.doctrees/advanced.doctree
Binary file not shown.
Binary file modified docs/gettext/.doctrees/develop.doctree
Binary file not shown.
Binary file modified docs/gettext/.doctrees/environment.pickle
Binary file not shown.
Binary file modified docs/gettext/.doctrees/features.doctree
Binary file not shown.
Binary file modified docs/gettext/.doctrees/help.doctree
Binary file not shown.
Binary file modified docs/gettext/.doctrees/index.doctree
Binary file not shown.
Binary file modified docs/gettext/.doctrees/install.doctree
Binary file not shown.
Binary file modified docs/gettext/.doctrees/security.doctree
Binary file not shown.
Binary file modified docs/gettext/.doctrees/tor.doctree
Binary file not shown.
4 changes: 2 additions & 2 deletions docs/gettext/advanced.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: OnionShare 2.6.1\n"
"Project-Id-Version: OnionShare 2.6.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-05 11:30-0700\n"
"POT-Creation-Date: 2024-03-15 13:52+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down
4 changes: 2 additions & 2 deletions docs/gettext/develop.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: OnionShare 2.6.1\n"
"Project-Id-Version: OnionShare 2.6.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-05 11:30-0700\n"
"POT-Creation-Date: 2024-03-15 13:52+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down
4 changes: 2 additions & 2 deletions docs/gettext/features.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: OnionShare 2.6.1\n"
"Project-Id-Version: OnionShare 2.6.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-05 11:30-0700\n"
"POT-Creation-Date: 2024-03-15 13:52+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down
4 changes: 2 additions & 2 deletions docs/gettext/help.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: OnionShare 2.6.1\n"
"Project-Id-Version: OnionShare 2.6.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-05 11:30-0700\n"
"POT-Creation-Date: 2024-03-15 13:52+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down
4 changes: 2 additions & 2 deletions docs/gettext/index.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: OnionShare 2.6.1\n"
"Project-Id-Version: OnionShare 2.6.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-05 11:30-0700\n"
"POT-Creation-Date: 2024-03-15 13:52+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down

0 comments on commit 6665274

Please sign in to comment.