diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 00000000..3186f3f0 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/docs/chat/add-contact.md b/docs/chat/add-contact.md index 38366e86..3377573a 100644 --- a/docs/chat/add-contact.md +++ b/docs/chat/add-contact.md @@ -2,10 +2,17 @@ sidebar_position: 1.5 --- -# Adding a New Contact +# Starting a New Conversation 1. Select a Profile 2. Click on the Add button 3. Chose 'Add Contact' -5. Paste a Cwtch Address -6. The contact will be added to your contacts list \ No newline at end of file +4. Paste a Cwtch Address +5. The contact will be added to your contacts list + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: diff --git a/docs/chat/block-contact.md b/docs/chat/block-contact.md index fbf421bf..45ad42e3 100644 --- a/docs/chat/block-contact.md +++ b/docs/chat/block-contact.md @@ -8,3 +8,10 @@ sidebar_position: 7 2. Go to Settings 3. Scroll down to Block Contact 4. Move the switch to Block Contact + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: \ No newline at end of file diff --git a/docs/chat/delete-contact.md b/docs/chat/delete-contact.md new file mode 100644 index 00000000..bc633fc6 --- /dev/null +++ b/docs/chat/delete-contact.md @@ -0,0 +1,12 @@ +--- +sidebar_position: 10 +--- + +# Removing a Conversation + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: diff --git a/docs/chat/share-address-with-friends.md b/docs/chat/share-address-with-friends.md index ddc2c82b..dd6b0a4f 100644 --- a/docs/chat/share-address-with-friends.md +++ b/docs/chat/share-address-with-friends.md @@ -2,11 +2,27 @@ sidebar_position: 3 --- -# Sharing a Cwtch Address +# Sharing Cwtch Addresses + +There are many ways to share a Cwtch address. + +## Sharing Your Cwtch Address 1. Go to your profile 2. Click the copy address icon You can now share this address. People with this address will be able to add you as a Cwtch contact. -For information on blocking connections from people you don't know please see [Settings: Block Unknown Connections](/docs/settings/behaviour/block-unknown-connections) \ No newline at end of file +For information on blocking connections from people you don't know please see [Settings: Block Unknown Connections](/docs/settings/behaviour/block-unknown-connections) + + +# Sharing A Friends Cwtch Address + +Inside of Cwtch there is another mechanism for exchanging cwtch addresses. + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: \ No newline at end of file diff --git a/docs/chat/unblock-contact.md b/docs/chat/unblock-contact.md index 2ba88d07..6ff4cc10 100644 --- a/docs/chat/unblock-contact.md +++ b/docs/chat/unblock-contact.md @@ -7,4 +7,12 @@ sidebar_position: 8 1. Select the contact in your Conversation list. Blocked contacts are moved to the bottom of the list. 2. Go to Conversation Settings 3. Scroll down to Block Contact -4. Move the switch to Unblock Contact \ No newline at end of file +4. Move the switch to Unblock Contact + + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: \ No newline at end of file diff --git a/docs/contribute/developing.md b/docs/contribute/developing.md new file mode 100644 index 00000000..ff41f0b9 --- /dev/null +++ b/docs/contribute/developing.md @@ -0,0 +1,14 @@ +--- +sidebar_position: 1 +--- + +# Developing Cwtch + +This section documents some ways to get started with Cwtch Development. + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: diff --git a/docs/settings/experiments/file-sharing.md b/docs/settings/experiments/file-sharing.md index a60f229a..a0371d0f 100644 --- a/docs/settings/experiments/file-sharing.md +++ b/docs/settings/experiments/file-sharing.md @@ -2,4 +2,11 @@ sidebar_position: 3 --- -# File Sharing \ No newline at end of file +# File Sharing + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: \ No newline at end of file diff --git a/docs/settings/experiments/group-experiment.md b/docs/settings/experiments/group-experiment.md index 58d569bc..10c98895 100644 --- a/docs/settings/experiments/group-experiment.md +++ b/docs/settings/experiments/group-experiment.md @@ -4,6 +4,15 @@ sidebar_position: 1 # Enable the Groups Experiment +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: + 1. Go to Settings 2. Enable Experiments -3. Enable the Group experiment \ No newline at end of file +3. Enable the Group experiment + + diff --git a/docs/settings/experiments/image-previews-and-profile-pictures.md b/docs/settings/experiments/image-previews-and-profile-pictures.md index 7289a15d..f8af05bd 100644 --- a/docs/settings/experiments/image-previews-and-profile-pictures.md +++ b/docs/settings/experiments/image-previews-and-profile-pictures.md @@ -2,4 +2,11 @@ sidebar_position: 4 --- -# Image Previews and Profile Pictures \ No newline at end of file +# Image Previews and Profile Pictures + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: \ No newline at end of file diff --git a/docs/settings/experiments/message-formatting.md b/docs/settings/experiments/message-formatting.md index 6945116b..c6a92c41 100644 --- a/docs/settings/experiments/message-formatting.md +++ b/docs/settings/experiments/message-formatting.md @@ -3,3 +3,10 @@ sidebar_position: 6 --- # Message Formatting + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: \ No newline at end of file diff --git a/docs/settings/experiments/qrcodes.md b/docs/settings/experiments/qrcodes.md new file mode 100644 index 00000000..19fcde80 --- /dev/null +++ b/docs/settings/experiments/qrcodes.md @@ -0,0 +1,12 @@ +--- +sidebar_position: 9 +--- + +# QR Codes + +:::info + +This documentation page is a stub. You can help +by [expanding it](https://git.openprivacy.ca/cwtch.im/docs.cwtch.im). + +::: \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index cf27acfb..bb338a0a 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -77,6 +77,11 @@ const config = { position: 'left', label: 'Cwtch Intro', }, + { + to: '/security/intro', + position: 'left', + label: 'Security Handbook', + }, { to: 'blog', position: 'left', @@ -156,15 +161,17 @@ const config = { darkTheme: darkCodeTheme, }, }), - /*plugins: [ + plugins: [ [ - require.resolve("@cmfcmf/docusaurus-search-local"), + '@docusaurus/plugin-content-docs', { - // Options here - language: ["en", 'fr', 'da', 'de', 'it', 'no', 'ro', 'ru', 'es'], + id: 'docs-security', + path: 'security', + routeBasePath: 'security', + sidebarPath: require.resolve('./sidebars.js'), }, ], - ],*/ + ], }; diff --git a/package-lock.json b/package-lock.json index 1a7571cf..494a5d1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@cmfcmf/docusaurus-search-local": "^0.10.0", "@crowdin/cli": "^3.7.8", "@docusaurus/core": "2.0.0-beta.20", + "@docusaurus/plugin-content-docs": "^2.0.0-beta.20", "@docusaurus/preset-classic": "2.0.0-beta.20", "@mdx-js/react": "^1.6.22", "clsx": "^1.1.1", @@ -2599,6 +2600,28 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.13", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", @@ -2772,9 +2795,9 @@ } }, "node_modules/@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" }, "node_modules/@sideway/pinpoint": { "version": "2.0.0", @@ -2790,116 +2813,16 @@ } }, "node_modules/@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.4.tgz", - "integrity": "sha512-FvMavoWEIePps6/JwGCOLYKCRhuwIHhMtmbKpBFgzNkxwpa/569LfTkrbRk1m1I3n+ezJK4on9E1A6cjuZmD9g==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", + "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", "dependencies": { - "bluebird": "^3.7.1", - "cheerio": "^0.22.0", "eval": "^0.1.8", - "webpack-sources": "^1.4.3" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" + "p-map": "^4.0.0", + "webpack-sources": "^3.2.2" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", - "engines": { - "node": "*" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dependencies": { - "boolbase": "~1.0.0" + "node": ">=14" } }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { @@ -4011,11 +3934,6 @@ "node": ">=8" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -5476,9 +5394,9 @@ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" }, "node_modules/dns-packet": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz", - "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", + "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -5769,9 +5687,9 @@ } }, "node_modules/eta": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz", - "integrity": "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/eta/-/eta-1.14.2.tgz", + "integrity": "sha512-wZmJAV7EFUG5W8XNXSazIdichnWEhGB1OWg4tnXWPj0CPNUcFdgorGNO6N9p6WBUgoUe4P0OziJYn1+6zxP2aQ==", "engines": { "node": ">=6.0.0" }, @@ -6998,9 +6916,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-deceiver": { "version": "1.2.7", @@ -7635,9 +7553,9 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "bin": { "json5": "lib/cli.js" }, @@ -7729,9 +7647,9 @@ } }, "node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -7757,16 +7675,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" - }, - "node_modules/lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" - }, "node_modules/lodash.curry": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", @@ -7777,71 +7685,16 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - }, - "node_modules/lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" - }, "node_modules/lodash.flow": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" }, - "node_modules/lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" - }, - "node_modules/lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" - }, - "node_modules/lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" - }, - "node_modules/lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" - }, - "node_modules/lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" - }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -9761,9 +9614,9 @@ } }, "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", "engines": { "node": ">= 12.13.0" } @@ -10019,25 +9872,14 @@ } }, "node_modules/recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "dependencies": { - "minimatch": "3.0.4" + "minimatch": "^3.0.5" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/recursive-readdir/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": ">=6.0.0" } }, "node_modules/regenerate": { @@ -10742,31 +10584,20 @@ } }, "node_modules/serve-handler": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", - "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", "mime-types": "2.1.18", - "minimatch": "3.0.4", + "minimatch": "3.1.2", "path-is-inside": "1.0.2", "path-to-regexp": "2.2.1", "range-parser": "1.2.0" } }, - "node_modules/serve-handler/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/serve-handler/node_modules/path-to-regexp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", @@ -11002,11 +10833,6 @@ "node": ">= 6.3.0" } }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -11348,13 +11174,13 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/terser": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", - "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz", + "integrity": "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==", "dependencies": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.8.0-beta.0", "source-map-support": "~0.5.20" }, "bin": { @@ -11419,48 +11245,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, - "node_modules/terser/node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/terser/node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/terser/node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "node_modules/terser/node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -11532,7 +11316,8 @@ "node_modules/trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", + "deprecated": "Use String.prototype.trim() instead" }, "node_modules/trim-trailing-lines": { "version": "1.1.4", @@ -11621,9 +11406,9 @@ } }, "node_modules/ua-parser-js": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", - "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.34.tgz", + "integrity": "sha512-cJMeh/eOILyGu0ejgTKB95yKT3zOenSe9UGE3vj6WfiOwgGYnmATUsnDixMFvdU+rNMvWih83hrUP8VwhF9yXQ==", "funding": [ { "type": "opencollective", @@ -12640,12 +12425,11 @@ } }, "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" } }, "node_modules/webpack/node_modules/mime-db": { @@ -12684,14 +12468,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/webpackbar": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", @@ -14856,6 +14632,27 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==" }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, "@jridgewell/sourcemap-codec": { "version": "1.4.13", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", @@ -14992,9 +14789,9 @@ } }, "@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" }, "@sideway/pinpoint": { "version": "2.0.0", @@ -15007,112 +14804,13 @@ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" }, "@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.4.tgz", - "integrity": "sha512-FvMavoWEIePps6/JwGCOLYKCRhuwIHhMtmbKpBFgzNkxwpa/569LfTkrbRk1m1I3n+ezJK4on9E1A6cjuZmD9g==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", + "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", "requires": { - "bluebird": "^3.7.1", - "cheerio": "^0.22.0", "eval": "^0.1.8", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" - }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" - } - } + "p-map": "^4.0.0", + "webpack-sources": "^3.2.2" } }, "@svgr/babel-plugin-add-jsx-attribute": { @@ -15977,11 +15675,6 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, "body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -17015,9 +16708,9 @@ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" }, "dns-packet": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz", - "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", + "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", "requires": { "@leichtgewicht/ip-codec": "^2.0.1" } @@ -17234,9 +16927,9 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "eta": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz", - "integrity": "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==" + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/eta/-/eta-1.14.2.tgz", + "integrity": "sha512-wZmJAV7EFUG5W8XNXSazIdichnWEhGB1OWg4tnXWPj0CPNUcFdgorGNO6N9p6WBUgoUe4P0OziJYn1+6zxP2aQ==" }, "etag": { "version": "1.8.1", @@ -18149,9 +17842,9 @@ } }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "http-deceiver": { "version": "1.2.7", @@ -18579,9 +18272,9 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonfile": { "version": "6.1.0", @@ -18644,9 +18337,9 @@ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -18666,16 +18359,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" - }, - "lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" - }, "lodash.curry": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", @@ -18686,71 +18369,16 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - }, - "lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" - }, "lodash.flow": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" }, - "lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" - }, - "lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" - }, - "lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" - }, - "lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" - }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" - }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -20078,9 +19706,9 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==" }, "locate-path": { "version": "6.0.0", @@ -20267,21 +19895,11 @@ } }, "recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "requires": { - "minimatch": "3.0.4" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - } + "minimatch": "^3.0.5" } }, "regenerate": { @@ -20827,28 +20445,20 @@ } }, "serve-handler": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", - "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", "requires": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", "mime-types": "2.1.18", - "minimatch": "3.0.4", + "minimatch": "3.1.2", "path-is-inside": "1.0.2", "path-to-regexp": "2.2.1", "range-parser": "1.2.0" }, "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, "path-to-regexp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", @@ -21039,11 +20649,6 @@ "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz", "integrity": "sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw==" }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -21279,13 +20884,13 @@ } }, "terser": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", - "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz", + "integrity": "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==", "requires": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.8.0-beta.0", "source-map-support": "~0.5.20" }, "dependencies": { @@ -21293,42 +20898,6 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "requires": { - "whatwg-url": "^7.0.0" - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "requires": { - "punycode": "^2.1.0" - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } } } }, @@ -21412,7 +20981,7 @@ "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==" }, "trim-trailing-lines": { "version": "1.1.4", @@ -21473,9 +21042,9 @@ "peer": true }, "ua-parser-js": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", - "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==" + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.34.tgz", + "integrity": "sha512-cJMeh/eOILyGu0ejgTKB95yKT3zOenSe9UGE3vj6WfiOwgGYnmATUsnDixMFvdU+rNMvWih83hrUP8VwhF9yXQ==" }, "unherit": { "version": "1.1.3", @@ -21958,11 +21527,6 @@ "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" } } }, @@ -22187,13 +21751,9 @@ } }, "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" }, "webpackbar": { "version": "5.0.2", diff --git a/package.json b/package.json index 34fae712..3d789978 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@cmfcmf/docusaurus-search-local": "^0.10.0", "@crowdin/cli": "^3.7.8", "@docusaurus/core": "2.0.0-beta.20", + "@docusaurus/plugin-content-docs": "^2.0.0-beta.20", "@docusaurus/preset-classic": "2.0.0-beta.20", "@mdx-js/react": "^1.6.22", "clsx": "^1.1.1", diff --git a/security/components/_category_.json b/security/components/_category_.json new file mode 100644 index 00000000..dd8190e0 --- /dev/null +++ b/security/components/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Cwtch Components", + "position": 4, + "link": { + "type": "generated-index" + } +} \ No newline at end of file diff --git a/security/components/connectivity/_category_.json b/security/components/connectivity/_category_.json new file mode 100644 index 00000000..6cbf8563 --- /dev/null +++ b/security/components/connectivity/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Connectivity & Tor", + "position": 4, + "link": { + "type": "generated-index" + } +} \ No newline at end of file diff --git a/security/components/connectivity/intro.md b/security/components/connectivity/intro.md new file mode 100644 index 00000000..1543a90b --- /dev/null +++ b/security/components/connectivity/intro.md @@ -0,0 +1,68 @@ +--- +sidebar_position: 3 +--- + + +# Connectivity + +Cwtch makes use of Tor Onion Services (v3) for all inter-node communication. + +We provide the [openprivacy/connectivity](https://git.openprivacy.ca/openprivacy/connectivity) +package for managing the Tor daemon and setting up and tearing down onion +services through Tor. + +## Known Risks + +### Private Key Exposure to the Tor Process + +**Status: Partially Mitigated** (Requires Physical Access or Privilege Escalation to +exploit) + +We must pass the private key of any onion service we wish to set up to the +connectivity library, through the `Listen` interface (and thus to the Tor +process). This is one of the most critical areas that is outside of our +control. Any binding to a rouge tor process or binary will result in +compromise of the Onion private key. + +### Mitigations + +Connectivity attempt to bind to the system-provided Tor process as the default, +*only* when it has been provided with an authentication token. + +Otherwise connectivity always attempts to deploy its own Tor process +using a known +good binary packaged with the system (outside of the scope of the connectivity +package) + +In the long term we hope an integrated library will become available and allow +direct management through an in-process interface to prevent the private key +from leaving the process boundary (or other alternative paths that allow us +to maintain full control over the private key in-memory.) + +### Tor Process Management + +**Status: Partially Mitigated** (Requires Physical Access or Privilege +Escalation to exploit) + +Many issues can arise from the management of a separate process, including the +need to restart, exit and otherwise ensure appropriate management. + +The [ACN](https://git.openprivacy.ca/openprivacy/connectivity/src/branch/master/acn.go) +interface provides `Restart`, `Close` and `GetBootstrapStatus` interfaces to +allow applications to manage the underlying Tor process. In addition the `SetStatusCallback` +method can be used to allow an application to be notified when the status of +the Tor process changes. + +However, if sufficiently-privileged users wish they can interfere with this +mechanism, and as such the Tor process is a more brittle component +interaction than others. + +## Testing Status + +Current connectivity has limited unit testing capabilities and none of these +are run during pull requests or merges. There is no integration testing. + +It is worth noting that connectivity is used by both Tapir and Cwtch in their +integration tests (and so despite the lack of package level testing, it is +exposed to system-wide test conditions) + diff --git a/security/components/cwtch/_category_.json b/security/components/cwtch/_category_.json new file mode 100644 index 00000000..4c5c5571 --- /dev/null +++ b/security/components/cwtch/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Cwtch", + "position": 5, + "link": { + "type": "generated-index" + } +} \ No newline at end of file diff --git a/security/components/cwtch/groups.md b/security/components/cwtch/groups.md new file mode 100644 index 00000000..e23a407e --- /dev/null +++ b/security/components/cwtch/groups.md @@ -0,0 +1,64 @@ +--- +sidebar_position: 4 +--- + +# Groups + +For the most part the Cwtch risk model for groups is split into two distinct +profiles: + +* Groups made up of mutually trusted participants where peers are assumed + honest. +* Groups consisting of strangers where peers are assumed to be potentially + malicious. + +Most of the mitigations described in this section relate to the latter case, but +naturally also impact the former. Even if assumed honest peers later turn + malicious there are mechanisms that can detect such malice and prevent it from + happening in the future. + +## Risk Overview: Key Derivation + +In the ideal case we would use a protocol like OTR, the limitations preventing +us from doing so right now are: + +* Offline messages are not guaranteed to reach all peers, and as such any +metadata relating to key material might get lost. We need a key derivation + process which is robust to missing messages or incomplete broadcast. + +## Risk: Malicious Peer Leaks Group Key and/or Conversation + +**Status: Partially Mitigated (but impossible to mitigate fully)** + +Whether dealing with trusted smaller groups or partially-public larger groups +there is *always* the possibility that a malicious actor will leak group +messages. + +We plan to make it easy for peers to [fork](#fork) groups to mitigate the + same key being used to encrypt lots of sensitive information and provide + some level of forward secrecy for past group conversations. + +## Risk: Active Attacks by Group Members + +**Status: Partially Mitigated** + +Group members, who have access to the key material of the group, can conspire + with a server or other group members to break transcript consistency. + +While we cannot directly prevent censorship given this kind of active + collusion, we have a number of mechanisms in place that should reveal the + presence of censorship to honest members of the group. + +### Mitigations: + +* Because each message is signed by the peers public key, it should not be +possible (within the cryptographic assumptions of the underlying cryptography) +for one group member to imitate another. +* Each message contains a unique identifier derived from the contents and the +previous message hash - making it impossible for collaborators to include +messages from non-colluding members without revealing an implicit message +chain (which if they were attempting to censor other messages would + reveal such censorship) + +Finally: We are actively working on adding non-repudiation to Cwtch servers such +that they themselves are restricted in what they can censor efficiently. diff --git a/security/components/cwtch/key_bundles.md b/security/components/cwtch/key_bundles.md new file mode 100644 index 00000000..e1fd2ff1 --- /dev/null +++ b/security/components/cwtch/key_bundles.md @@ -0,0 +1,35 @@ +--- +sidebar_position: 3 +--- + +# Key Bundles + +Cwtch servers identify themselves through signed key bundles. These key bundles contain a list of keys necessary +to make cwtch group communication secure and metadata resistant. + +At the time of writing, key bundles are expected to contain 3 keys: + +1. A Tor v3 Onion Service Public Key for the Token Board (ed25519)- used to connect to the service over Tor to post and +receive messages. +2. A Tor v3 Onion Service Public Key for the Token Service (ed25519) - used to acquire tokens to post on the service via +a small proof-of-work exercise. +3. A Privacy Pass Public Key - used in the token acquisition process (a ristretto curve point) . See: [OPTR2019-01](https://openprivacy.ca/research/OPTR2019-01/) + +The key bundle is signed and can be verified via the first v3 onion service key, thus binding it to that particular oninon +address. + +## Verifying Key Bundles + +Profiles who import server key bundles verify them using the following trust-on-first-use (TOFU) algorithm: + +1. Verify the attached signature using the v3 onion address of the server. (If this fails, the import process is halted) +2. Check that every key type exists. (If this fails, the import process is halted) +3. If the profile has imported the server key bundle previously, assert that all the keys are the same. (If this fails, the import process is halted) +4. Save the keys to the servers contact entry. + +In the future this algorithm will likely be altered to allow the addition of new public keys (e.g. to allow +tokens to be acquired via a Zcash address.) + +Technically, at steps (2) and (3() the server can be assumed to be malicious, having signed a valid key bundle that +does not conform to the specifications. When groups are moved from "experimental" to "stable" such an action will +result in a warning being communicated to the profile. \ No newline at end of file diff --git a/security/components/cwtch/message_formats.md b/security/components/cwtch/message_formats.md new file mode 100644 index 00000000..8881f697 --- /dev/null +++ b/security/components/cwtch/message_formats.md @@ -0,0 +1,61 @@ +--- +sidebar_position: 2 +--- + +# Message Formats + +## Peer to Peer Messages + + PeerMessage { + ID string // A unique Message ID (primarily used for acknowledgments) + Context string // A unique context identifier i.e. im.cwtch.chat + Data []byte // The context-dependent serialized data packet. + } + +### Context Identifiers + +* `im.cwtch.raw` - Data contains a plain text chat message (see: [overlays](../ui/overlays.md) for more information) +* `im.cwtch.acknowledgement` - Data is empty and ID references a previously sent message + +* `im.cwtch.getVal` and `im.cwtch.retVal` - Used for requesting / returning specific information about a peer. Data +contains a serialized `peerGetVal` structure and `peerRetVal` respectively. + + peerGetVal struct { + Scope string + Path string + } + + type peerRetVal struct { + Val string // Serialized path-dependent value + Exists bool + } + +## Plaintext / Decrypted Group Messages + + type DecryptedGroupMessage struct { + Text string // plaintext of the message + Onion string // The cwtch address of the sender + Timestamp uint64 // A user specified timestamp + // NOTE: SignedGroupID is now a misnomer, the only way this is signed is indirectly via the signed encrypted group messages + // We now treat GroupID as binding to a server/key rather than an "owner" - additional validation logic (to e.g. + // respect particular group constitutions) can be built on top of group messages, but the underlying groups are + // now agnostic to those models. + SignedGroupID []byte + PreviousMessageSig []byte // A reference to a previous message + Padding []byte // random bytes of length = 1800 - len(Text) + } + +DecryptedGroupMessage contains random padding to a fixed size that is equal to the length of all fixed length fields + 1800. +This ensures that all encrypted group messages are equal length. + +## Encrypted Group Messages + + // EncryptedGroupMessage provides an encapsulation of the encrypted group message stored on the server + type EncryptedGroupMessage struct { + Ciphertext []byte + Signature []byte // Sign(groupID + group.GroupServer + base64(decrypted group message)) using the senders cwtch key + } + +Calculating the signature requires knowing the groupID of the message, the server the group is associated with +and the decrypted group message (and thus, the Group Key). It is (ed25519) signed by the sender of the message, and can be +verified using their public cwtch address key. \ No newline at end of file diff --git a/security/components/cwtch/server.md b/security/components/cwtch/server.md new file mode 100644 index 00000000..35df5a64 --- /dev/null +++ b/security/components/cwtch/server.md @@ -0,0 +1,95 @@ +# Cwtch Server + +The goal of the Cwtch protocol is to enable group communication through +**Untrusted Infrastructure**. + +Unlike in relay-based schemes where the groups assign a leader, set of + leaders, or a trusted third party server to ensure that every member of the + group can send and receive messages in a timely manner (even if members are + offline) - untrusted infrastructure has a goal of realizing those properties + without the assumption of trust. + +The original Cwtch paper defined a set of properties that Cwtch Servers were +expected to provide: + +* Cwtch Server may be used by multiple groups or just one. +* A Cwtch Server, without collaboration of a group member, should + never learn the identity of participants within a group. +* A Cwtch Server should never learn the content of any communication. +* A Cwtch Server should never be able to distinguish messages as belonging + to a particular group. + +We note here that these properties are a superset of the design aims of Private +Information Retrieval structures. + +## Malicious Servers + +We expect the presence of malicious entities within the Cwtch ecosystem. + +We also prioritize decentralization and permissionless entry into the + ecosystem and as such we do not base any security claims on the following: + +* Any non-collusion assumptions between a set of Cwtch servers +* Any third-party defined verification process + +Peers themselves are encouraged to set up and run Cwtch servers where they can +guarantee more efficient properties by relaxing trust and security + assumptions - however, by default, we design the protocol to be secure without + these assumptions - sacrificing efficiency where necessary. + +### Detectable Faults + +* If a Cwtch server fails to relay a specific message to a subset of group +members then there will be a detectable gap in the message tree of certain +peers that can be discovered through peer-to-peer gossip. +* A Cwtch server cannot modify any message without the key material known to +the group (any attempt to do so for a subset of group members will result in +identical behavior to failing to relay a message). +* While a server *can* duplicate messages, these will have no impact on the +group message tree (because of encryption, nonces and message identities) - +the source of the duplication is not knowable to a peer. + +## Efficiency + +As of writing, only 1 protocol is known for achieving the desired properties, +naive PIR or "the server sends everything, and the peers sift through it". + +This has an obvious impact on bandwidth efficiency, especially for peers using +mobile devices, as such we are actively developing new protocols in which the +privacy and efficiency guarantees can be traded-off in different ways. + +As of writing, the servers allow both a complete download of all stored messages, and a +request to download messages from a certain specified message. + +All peers when they first join a group on a new server download all messages from the server, and +from then on download only new messages. + +*Note*: This behaviour does permit a mild form of metadata analysis. The server can new messages for each +suspected unique profile, and then use these unique message signatures to track unique sessions over time ( +via requests for new messages). + +This is mitigated by 2 confounding factors: + +1. Profiles can refresh their connections at any time - resulting in fresh server session. +2. Profiles can "resync" from a server at any time - resulting in a new call to download all messages. The most +common usecase for this behaviour is to fetch older messages from a group. + +In combination, these 2 mitigations place bounds on what the server is able to infer however we still cannot +provide full metadata-resistance. + +For potential future solutions to this problem see [Niwl](https://git.openprivacy.ca/openprivacy/niwl) + +# Protecting the Server from Malicious Peers + +The main risk to servers come in the form of spam generated by peers. In the +prototype of Cwtch a spamguard mechanism was put in place that required +peers to conduct some arbitrary proof of work given a server-specified + parameter. + +This is not a robust solution in the presence of a determined adversary with +a significant amount of resources, and thus one of the main external risks to + the Cwtch system becomes censorship-via-resource exhaustion. + +We have outlined a potential solution to this in +[token based services](https://openprivacy.ca/research/OPTR2019-01/) but note + that this also requires further development. diff --git a/security/components/ecosystem-overview.md b/security/components/ecosystem-overview.md new file mode 100644 index 00000000..f977da7e --- /dev/null +++ b/security/components/ecosystem-overview.md @@ -0,0 +1,79 @@ +--- +sidebar_position: 1.5 +--- + +# Component Ecosystem Overview + +Cwtch is made up of several smaller component libraries. This chapter will provide a brief overview of +each component and how it relates to the wider Cwtch ecosystem. + +## [openprivacy/connectivity](https://git.openprivacy.ca/openprivacy/connectivity) + +Summary: A library providing an ACN (Anonymous Communication Network ) networking abstraction. + +The goal of connectivity is to abstract away the underlying libraries/software needed to communicate with a +specific ACN. Right now we only support Tor and so the job of connectivity is to: + +* Start and Stop the Tor Process +* Provide configuration to the Tor process +* Allow raw connections to endpoints via the Tor process (e.g. connect to onion services) +* Host endpoints via the Tor process (e.g. host onion services) +* Provide status updates about the underlying Tor process + +For more information see [connectivity](/security/components/connectivity/intro) + +## [cwtch.im/tapir](https://git.openprivacy.ca/cwtch.im/tapir) + +Summary: Tapir is a small library for building p2p applications over anonymous communication systems. + +The goal of tapir is to abstract away **applications** over a particular ACN. Tapir supports: + +* Creating a cryptographic identity (including ephemeral identities) +* Maintaining a connection pool of inbound and outbound connections to services +* Handling various application-layers including cryptographic transcripts, [authentication and authorization protocols](/security/components/tapir/authentication_protocol), and + [token-based services via PrivacyPass](https://openprivacy.ca/research/OPTR2019-01/), + +For more information see [tapir](./tapir/) + +## [cwtch.im/cwtch](https://git.openprivacy.ca/cwtch.im/cwtch) + +Summary: Cwtch is the main library for implementing the cwtch protocol / system. + +The goal of cwtch is to provide implementations for cwtch-specific applications e.g. +message sending, groups, and file sharing(implemented as Tapir applications), provide interfaces for managing and storing Cwtch profiles, provide an event bus for subsystem splutting and building plugins with new functionality, in addition to managing other core functionality. + +The cwtch library is also responsible for maintaining canonical model representations for wire formats and overlays. + + +## [cwtch.im/libcwtch-go](https://git.openprivacy.ca/cwtch.im/libcwtch-go) + +Summary: libcwtch-go provides C (including Android) bindings for Cwtch for use in UI implementations. + +The goal of libcwtch-go is to bridge the gap between the backend cwtch library and any front end systems which +may be written in a different language. + +The API provided by libcwtch is much more restricted than the one provided by Cwtch directly, each libcwtch API typically +packages up several calls to Cwtch. + +libcwtch-go is also responsible for managing UI settings and experimental gating. It is also often used as a staging ground +for experimental features and code that may eventually end up in Cwtch. + +## [cwtch-ui](https://git.openprivacy.ca/cwtch.im/cwtch-ui) + +Summary: A flutter based UI for Cwtch. + +Cwtch UI uses libcwtch-go to provide a complete UI for Cwtch, allowing people to create and manage profiles, +add contacts and groups, message people, share files (coming soon) and more. + +The UI is also responsible for managing localization and translations. + +For more information see [Cwtch UI](/security/category/cwtch-ui) + +## Auxiliary Components + +Occasionally, Open Privacy will factor out parts of Cwtch into standalone libraries that are not Cwtch specific. +These are briefly summarized here: + +### [openprivacy/log](https://git.openprivacy.ca/openprivacy/log) + +An Open Privacy specific logging framework that is used throughout Cwtch packages. \ No newline at end of file diff --git a/security/components/intro.md b/security/components/intro.md new file mode 100644 index 00000000..da4d5d1a --- /dev/null +++ b/security/components/intro.md @@ -0,0 +1,65 @@ +--- +sidebar_position: 1 +--- + +# Cwtch Technical Basics + +This page presents a brief technical overview of the Cwtch protocol. + +## A Cwtch Profile + +Users can create one of more Cwtch Profiles. Each profile generates a random ed25519 keypair compatible with +Tor. + +In addition to the cryptographic material, a profile also contains a list of Contacts (other Cwtch profile public keys + +associated data about that profile like nickname and (optionally) historical messages), a list of Groups (containing the group cryptographic material in addition to other associated data like the group nickname and historical messages). + +## 2-party conversions: Peer to Peer + +![](/img/BASE_3.png) + +For 2 parties to engage in a peer-to-peer conversation both must be online, but only one needs to be reachable via +their onion service. For the sake of clarity we often label one party the "inbound peer" (the one who hosts the onion service) and the other party the +"outbound peer" (the one that connects to the onion service). + +After connection both parties engage in an authentication protocol which: + +* Asserts that each party has access to the private key associated with their public identity. +* Generates an ephemeral session key used to encrypt all further communication during the session. + +This exchange (documented in further detail in [authentication protocol](tapir/authentication_protocol.md)) is *offline deniable* +i.e. it is possible for any party to forge transcripts of this protocol exchange after the fact, and as such - after the +fact - it is impossible to definitely prove that the exchange happened at all. + +After, the authentication protocol the two parties may exchange messages with each other freely. + +## Multi-party conversations: Groups and Peer to Server Communication + +**Note: Metadata Resistant Group Communication is still an active research area and what is documented here +will likely change in the future.** + +When a person wants to start a group conversation they first randomly generate a secret `Group Key`. All group communication will be encrypted using this key. + +Along with the `Group Key`, the group creator also decides on a **Cwtch Server** to use as the host of the group. +For more information on how Servers authenticate themselves see [key bundles](cwtch/key_bundles.md). + +A `Group Identifier` is generated using the group key and the group server and these three elements are packaged up +into an invite that can be sent to potential group members (e.g. over existing peer-to-peer connections). + +To send a message to the group, a profile connects to the server hosting the group (see below), and encrypts +their message using the `Group Key` and generates a cryptographic signature over the `Group Id`, `Group Server` +and the decrypted message (see: [wire formats](cwtch/message_formats.md) for more information). + +To receive message from the group, a profile connected to the server hosting the group and downloads *all* messages (since +their previous connection). Profiles then attempt to decrypt each message using the `Group Key` and if successful attempt +to verify the signature (see [Cwtch Servers](cwtch/server.md) [Cwtch Groups](./cwtch/groups.md) for an overview of attacks and mitigations). + +### Servers are Peers + +In many respects communication with a server is identical to communication with a regular Cwtch peer, +all the same steps above are taken however the server always acts as the inbound peer, and the outbound +peer always uses newly generated **ephemeral keypair** as their "longterm identity". + +As such peer-server conversations only differ in the *kinds* of messages that are sent between the two parties, +with the server relaying all messages that it receives and also allowing any client to query for older messages. + diff --git a/security/components/tapir/_category_.json b/security/components/tapir/_category_.json new file mode 100644 index 00000000..15782c14 --- /dev/null +++ b/security/components/tapir/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Tapir", + "position": 4, + "link": { + "type": "generated-index" + } +} \ No newline at end of file diff --git a/security/components/tapir/authentication_protocol.md b/security/components/tapir/authentication_protocol.md new file mode 100644 index 00000000..597e77d4 --- /dev/null +++ b/security/components/tapir/authentication_protocol.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 2 +--- + +# Authentication Protocol + +Each peer, given an open connection \\(C\\): + +\\[ \\ +I = \mathrm{InitializeIdentity()} \\\\ +I_e = \mathrm{InitializeEphemeralIdentity()} \\\\ +\\\\ +I,I_e \rightarrow C \\\\ +P,P_e \leftarrow C \\\\ +\\\\ +k = \mathrm{KDF}({P_e}^{i} + {P}^{i_e} + {P_e}^{i_e}) \\\\ +c = \mathrm{E}(k, transcript.Commit()) \\\\ +c \rightarrow C \\\\ +c_p \leftarrow C \\\\ +\mathrm{D}(k, c_p) \stackrel{?}{=} transcript.LatestCommit() \\\\ +\\] + +The above represents a sketch protocol, in reality there are a few + implementation details worth pointing out: + +Once derived from the key derivation function \\(\mathrm{KDF}\\\) the key + \\(k\\) is set *on* the connection, meaning the authentication app doesn't + do the encryption or decryption explicitly. + +The concatenation of parts of the 3DH exchange is strictly ordered: + +* DH of the Long term identity of the outbound connection by the ephemeral + key of the inbound connection. +* DH of the Long term identity of the inbound connection by the ephemeral +key of the outbound connection. +* DH of the two ephemeral identities of the inbound and outbound connections. + +This strict ordering ensures both sides of the connection derive the *same* +session key. + +### Cryptographic Properties + +During an online-session, all messages encrypted with the session key can be authenticated by the peers as having come +from their peer (or at least, someone with possession of their peers secret key as it related to their onion address). + +Once the session has ended, a transcript containing the long term and ephemeral public keys, a derived session key and +all encrypted messages in the session cannot be proven to be authentic i.e. this protocol provides message & participant +repudiation (offline deniable) in addition to message unlinkability (offline deniable) in the case where someone is satisfied +that a single message in the transcript must have originated from a peer, there is no way of linking any other message to +the session. + +Intuition for the above: the only cryptographic material related to the transcript is the derived session key - if the +session key is made public it can be used to forge new messages in the transcript - and as such, any standalone +transcript is subject to forgery and thus cannot be used to cryptographically tie a peer to a conversation. + diff --git a/security/components/tapir/packet_format.md b/security/components/tapir/packet_format.md new file mode 100644 index 00000000..5fec2444 --- /dev/null +++ b/security/components/tapir/packet_format.md @@ -0,0 +1,17 @@ +--- +sidebar_position: 1 +--- + +# Packet Format + +All tapir packets are fixed length (8192 bytes) with the first 2 bytes indicated the actual length of the message, +`len` bytes of data, and the rest zero padded: + + | len (2 bytes) | data (len bytes) | paddding (8190-len bytes)| + +Once encrypted, the entire 8192 byte data packet is encrypted using [libsodium secretbox](https://libsodium.gitbook.io/doc/secret-key_cryptography/secretbox) using the standard structure ( +note in this case the actual usable size of the data packet is 8190-14 to accommodate the nonce included by secret box) + +For information on how the secret key is derived see the [authentication protocol](authentication_protocol.md) + + \ No newline at end of file diff --git a/security/components/ui/_category_.json b/security/components/ui/_category_.json new file mode 100644 index 00000000..b44d6bcf --- /dev/null +++ b/security/components/ui/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Cwtch UI", + "position": 7, + "link": { + "type": "generated-index" + } +} \ No newline at end of file diff --git a/security/components/ui/android.md b/security/components/ui/android.md new file mode 100644 index 00000000..f3d72479 --- /dev/null +++ b/security/components/ui/android.md @@ -0,0 +1,28 @@ +# Android Service + +[Adapted from: Discreet Log #11: Integrating FFI processes with Android services](https://openprivacy.ca/discreet-log/11-android-ffi-service-integration/) + +In addition to needing to make plain ol’ method calls into the Cwtch library, we also need to be able to communicate with (and receive events from) long-running Cwtch goroutines that keep the Tor process running in the background, manage connection and conversation state for all your contacts, and handle a few other monitoring and upkeep tasks as well. This isn’t really a problem on traditionally multitasking desktop operating systems, but on mobile devices running Android we have to contend with shorter sessions, frequent unloads, and network and power restrictions that can vary over time. As Cwtch is intended to be metadata resistant and privacy-centric, we also want to provide notifications without using the Google push notification service. + +The solution for long-running network apps like Cwtch is to put our FFI code into an Android Foreground Service. (And no, it’s not lost on me that the code for our backend is placed in something called a ForegroundService.) With a big of finagling, the WorkManager API allows us to create and manage various types of services including ForegroundServices. This turned out to be a great choice for us, as our gomobile FFI handler happened to already be written in Kotlin, and WorkManager allows us to specify a Kotlin coroutine to be invoked as the service. + +If you’d like to follow along, our WorkManager specifications are created in the handleCwtch() method of [MainActivity.kt](https://git.openprivacy.ca/cwtch.im/cwtch-ui/src/branch/trunk/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt), and the workers themselves are defined in [FlwtchWorker.kt](https://git.openprivacy.ca/cwtch.im/cwtch-ui/src/branch/trunk/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt). + +Our plain ol’ method calls to FFI routines are also upgraded to be made as WorkManager work requests, which allows us to conveniently pass the return values back via the result callback. + +One initial call (aptly named Start) gets hijacked by FlwtchWorker to become our eventbus loop. Since FlwtchWorker is a coroutine, it’s easy for it to yield and resume as necessary while waiting for events to be generated. Cwtch’s goroutines can then emit events, which will be picked up by FlwtchWorker and dispatched appropriately. + +FlwtchWorker’s eventbus loop is not just a boring forwarder. It needs to check for certain message types that affect the Android state; for example, new message events should typically display notifications that the user can click to go to the appropriate conversation window, even when the app isn’t running in the foreground. When the time does come to forward the event to the app, we use LocalBroadcastManager to get the notification to MainActivity.onIntent. From there, we in turn use Flutter MethodChannels to forward the event data from Kotlin into the frontend’s Flutter engine, where the event finally gets parsed by Dart code that updates the UI as necessary. + +Messages and other permanent state are stored on disk by the service, so the frontend doesn’t need to be updated if the app isnt open. However, some things (like dates and unread messages) can then lead to desyncs between the front and back ends, so we check for this at app launch/resume to see if we need to reinitialize Cwtch and/or resync the UI state. + +Finally, while implementing these services on Android we observed that WorkManager is very good at persisting old enqueued work, to the point that old workers were even being resumed after app reinstalls! Adding calls to pruneWork() helps mitigate this, as long as the app was shut down gracefully and old jobs were properly canceled. This frequently isn’t the case on Android, however, so as an additional mitigation we found it useful to tag the work with the native library directory name: + + private fun getNativeLibDir(): String { + val ainfo = this.applicationContext.packageManager.getApplicationInfo( + "im.cwtch.flwtch", // Must be app name + PackageManager.GET_SHARED_LIBRARY_FILES) + return ainfo.nativeLibraryDir + } + +…then, whenever the app is launched, we cancel any jobs that aren’t tagged with the correct current library directory. Since this directory name changes between app installs, this technique prevents us from accidentally resuming with an outdated service worker. \ No newline at end of file diff --git a/security/components/ui/image_previews.md b/security/components/ui/image_previews.md new file mode 100644 index 00000000..f52b3f13 --- /dev/null +++ b/security/components/ui/image_previews.md @@ -0,0 +1,35 @@ +# Image Previews + +Built on the back of filesharing in Cwtch 1.3, image previews are keyed by the suggested filename’s extension (and no, we’re not interested in using MIME types or magic numbers) and advertised size. If enabled, the preview system will automatically download shared images to a configured downloads folder and display them as part of the message itself. (Due to limitations on Android, they’ll go to the app’s private storage cache, and give you the option to save them elsewhere later instead.) The file size limit is TBD but will obviously be much lower than the overall filesharing size limit, which is currently 10 gigabytes. + +For now, we only support single-image messages, and any image editing/cropping will have to be done in a separate application. As we mention in the filesharing FAQ, image files also frequently contain significant hidden metadata, and you should only share them with people you trust. + +## KnownRisks + +## Other Applications and/or the OS Inferring Information from Images + +Images must be stored somewhere, and for now we have chosen to store them unencrypted on the file system. We have done this +for 2 reasons: + +1. In order to support more powerful file sharing schemes like rehosting we require the ability to efficiently +scan files and deliver chunks - doing this through an encrypted database layer would harm performance. +2. This information always has to transit the application boundary (either via display drivers, or storing and viewing + the file in an external application) - there is nothing that Cwtch can do after that point in any case. + +## Malicious Images Crashing or otherwise Compromising Cwtch + +Flutter uses Skia to render Images. While the underlying code is memory unsafe, it is [extensively fuzzed](https://github.com/google/skia/tree/main/fuzz) as part of regular development. + +We also conduct our own fuzz testing of Cwtch components. In that analysis we found a single crash bug related +to a malformed GIF file that caused the renderer to allocate a ridiculous amount of memory (and eventually be refused +by the kernel). To prevent this from impacting Cwtch we have adopted the policy of always enabling a maximum `cacheWidth` +and/or `cacheHeight` for Image widgets. + +## Malicious Images Rendering Differently on Different Platforms, Potentially Exposing Metadata + +Recently [a bug was found in Apple's png parser](https://www.da.vidbuchanan.co.uk/widgets/pngdiff/) which would cause an image to render differently on Apple devices as it would on non-Apple devices. + +We conducted a few tests on our Mac builds and could not replicate this issue for Flutter (because all Flutter builds use Skia for rendering), however we will continue to include such cases in our testing corpus. + +For now image previews will remain experimental and opt-in. + diff --git a/security/components/ui/input.md b/security/components/ui/input.md new file mode 100644 index 00000000..11471ab7 --- /dev/null +++ b/security/components/ui/input.md @@ -0,0 +1,25 @@ +# Input + + +## Risk: Interception of Cwtch content or metadata through an IME on Mobile Devices + +**Status: Partially Mitigated** + +Any component that has the potential to intercept data between a person, and the Cwtch app is a +potential security risk. + +One of the most likely interceptors is a 3rd party IME (Input Method Editor) commonly used +by people to generate characters not natively supported by their device. + +Even benign and stock IME apps may unintentionally leak information about the contents of a persons message e.g. +through cloud synchronization, cloud translation or personal dictionaries. + +Ultimately, this problem cannot be solved by Cwtch alone, and is a wider risk impacting the entire mobile +ecosystem. + +A similar risk exists on desktop through the use of similar input applications (in addition to software keyloggers), +however we consider that fully outside the scope of Cwtch risk assessment (in line with other attacks on the security of the underlying +operating system itself). + +This is partially mitigated in Cwtch 1.2 through the use of `enableIMEPersonalizedLearning: false`. See +[this PR](https://git.openprivacy.ca/cwtch.im/cwtch-ui/pulls/142) for more information. \ No newline at end of file diff --git a/security/components/ui/overlays.md b/security/components/ui/overlays.md new file mode 100644 index 00000000..51f8f5e6 --- /dev/null +++ b/security/components/ui/overlays.md @@ -0,0 +1,87 @@ +# Message Overlays + +[Adapted from: Discreet Log #8: Notes on the Cwtch Chat API](https://openprivacy.ca/discreet-log/08-chatapi/) + +**Note: This section covers overlay protocols on-top of the Cwtch protcol. For information on the Cwtch Protocol +messages themselves please see [Message Formats](../cwtch/message_formats.md)** + +We envision Cwtch as a platform for providing an authenticated transport layer to higher-level applications. +Developers are free to make their own choices about what application layer protocols to use, +whether they want bespoke binary message formats or just want to throw an HTTP library on top and call it a +day. Cwtch can generate new keypairs for you (which become onion addresses; no need for any DNS registrations!) +and you can REST assured that any data your application receives from the (anonymous communication) +network has been authenticated already. + +For our current stack, messages are wrapped in a minimal JSON frame that adds +some contextual information about the message type. +And because serialised JSON objects are just dictionaries, we can easily add more metadata later on as needed. + + +## Chat overlays, lists, and bulletins + +The original Cwtch alpha demoed "overlays": different ways of interpreting the same data channel, +depending on the structure of the atomic data itself. We included simple checklists and BBS/classified ads as overlays that could be viewed +and shared with any Cwtch contact, be it a single peer or a group. The wire format looked like this: + +``` +{o:1,d:"hey there!"} +{o:2,d:"bread",l:"groceries"} +{o:3,d:"garage sale",p:"[parent message signature]"} +``` + +Overlay field `o` determined if it was a chat (1), list (2), or bulletin (3) message. +The data field `d` is overloaded, and lists/bulletins need additional information about what +group/post they belong to. (We use message signatures in place of IDs to avoid things like message +ordering problems and maliciously crafted IDs. This is also how the Cwtch protocol communicates to the +front end which message is being acked.) + +## Data structure + +Implementing tree-structured data on top of a sequential message store comes with obvious +performance disadvantages. For example, consider the message view, which loads most-recent-messages first and only goes back far enough to fetch enough messages to fill the current viewport, in comparison with a (somewhat pathological) forum where almost every message is a child of the very first message in the history, which could have been gigs and gigs of data-ago. If the UI only displays top-level posts until the user expands them, we have to parse the entire history before we get enough info to display anything at all. + +Another problem is that multiplexing all these overlays into one data store creates "holes" in the data that confuse [lazy-loaded listviews](https://api.flutter.dev/flutter/widgets/ListView/ListView.builder.html) and scrollbars. The message count may indicate there is a ton more information to display if the user simply scrolls, but when it actually gets fetched and parsed we might realize that none of it is relevant to the current overlay. + +None of these problems are insurmountable, but they demonstrate a flaw in our initial assumptions about the nature of collaborative message flows and how we should be handling that data. + +# Overlay Types + +As stated above, overlays are specified in a very simple JSON format with the following structure: + + type ChatMessage struct { + O int `json:"o"` + D string `json:"d"` + } + +Where O stands for `Overlay` with the current supported overlays documented below: + + 1: data is a chat string + 2: data is a list state/delta + 3: data is a bulletin state/delta + 100: contact suggestion; data is a peer onion address + 101: contact suggestion; data is a group invite string + +## Chat Messages (Overlay 1) + +The most simple over is a chat message which simply contains raw, unprocessed chat message information. + +``` +{o:1,d:"got milk?"} +``` + +## Invitations (Overlays 100 and 101) + +Instead of receiving the invite as an incoming contact request at the profile level, new inline invites are shared with a particular contact/group, where they can be viewed and/or accepted later, even if they were initially rejected (potentially by accident). + +The wire format for these are equally simple: + +``` +{o:100,d:"u4ypg7yyyrrvf2aceeclq5dgwtkirzletltbqofnb6km7u542qqk4jyd"} +{o:101,d:"torv3eyJHcm91cElEIjoiOWY3MWExYmFhNDkzNTAzMzAyZDFmODRhMzI2ODY2OWUiLCJHcm91cE5hbWUiOiI5ZjcxYTFiYWE0OTM1MDMzMDJkMWY4NGEzMjY4NjY5ZSIsIlNpZ25lZEdyb3VwSUQiOiJyVGY0dlJKRkQ2LzFDZjFwb2JQR0xHYzdMNXBKTGJTelBLRnRvc3lvWkx6R2ZUd2Jld0phWllLUWR5SGNqcnlmdXVRcjk3ckJ2RE9od0NpYndKbCtCZz09IiwiVGltZXN0YW1wIjowLCJTaGFyZWRLZXkiOiJmZVVVQS9OaEM3bHNzSE9lSm5zdDVjNFRBYThvMVJVOStPall2UzI1WUpJPSIsIlNlcnZlckhvc3QiOiJ1cjMzZWRid3ZiZXZjbHM1dWU2anBrb3ViZHB0Z2tnbDViZWR6ZnlhdTJpYmY1Mjc2bHlwNHVpZCJ9"} +``` + +This represents a departure from our original "overlays" thinking to a more action-oriented representation. The chat "overlay" can communicate that someone *did* something, even if it's paraphrased down to "added an item to a list," and the lists and bulletins and other beautifully chaotic data can have their state precomputed and stored separately. + +## Lists / Bulletin Boards + +**Note: Expected to be Defined in Cwtch Beta 1.5** \ No newline at end of file diff --git a/security/deployment.md b/security/deployment.md new file mode 100644 index 00000000..434e8f87 --- /dev/null +++ b/security/deployment.md @@ -0,0 +1,19 @@ +# Deployment + + +## Risk: Binaries are replaced on the website with malicious ones + +**Status: Partially-mitigated** + +While this process is now mostly automated, should this automation ever be +compromised then there is nothing in our current process that would detect this. + +We need: + +* Reproducible Builds - we currently use public docker containers for all builds + which should allow anyone to compare distributed builds with ones built from source. + * Signed Releases - Open Privacy does not yet maintain a public record of staff + public keys. This is likely a necessity for signing released builds and + creating an audit chain backed by the organization. This process must be + manual by definition. + diff --git a/security/development.md b/security/development.md new file mode 100644 index 00000000..dab47d30 --- /dev/null +++ b/security/development.md @@ -0,0 +1,40 @@ +# Development + +The main process to counter malicious actors in development of Cwtch is the +openness of the process. + +To enhance this openness, automated builds, testing and packaging are defined +as part of the repositories - improving te robustness of the code base at every +stage. + +![](https://docs.openprivacy.ca/cwtch-security-handbook/1.png) + +While individual tests aren't perfect, and all processes have gaps, we should be +committed to make it as easy as possible to contribute to Cwtch while also + building pipelines and processes that catch errors (unintential or malicious) + as soon as possible. + +### Risk: Developer Directly Pushes Malicious Code + +**Status: Mitigated** + +`trunk` is currently locked and only 3 Open Privacy staff members have permission +to override it, in addition the responsibility of monitoring changes. + +Further every new pull request and merge triggered automated builds & tests + which trigger emails and audit logs. + +The code is also open source and inspectable by anyone. + +### Risk: Code Regressions + +**Status: Partially Mitigated** (See individual project entries in this + handbook for more information) + +Our automated pipelines have the ability to catch regressions when that + behaviour is detectable. + +The greatest challenge is in defining how such regressions are detected for the +[ui](./ui.md) - where behaviour isn't as strictly defined as it is for the + individual libraries. + \ No newline at end of file diff --git a/security/intro.md b/security/intro.md new file mode 100644 index 00000000..0f29d132 --- /dev/null +++ b/security/intro.md @@ -0,0 +1,74 @@ +--- +sidebar_position: 1 +--- + +# Cwtch Security Handbook + +Welcome to the Cwtch Secure Development Handbook! The purpose of this +handbook is to provide a guide to the various components of the Cwtch +ecosystem, to document the known risks and mitigations, and to enable +discussion about improvements and updates to Cwtch secure development +processes. + +![](https://docs.openprivacy.ca/cwtch-security-handbook/2.png) + + +## What is Cwtch? + +Cwtch (/kʊtʃ/ - a Welsh word roughly translating to “a hug that creates a safe place”) is a decentralized, privacy-preserving, multi-party messaging protocol that can be used to build metadata resistant applications. + +* **Decentralized and Open**: There is no “Cwtch service” or “Cwtch network”. Participants in Cwtch can host their own safe spaces, or lend their infrastructure to others seeking a safe space. The Cwtch protocol is open, and anyone is free to build bots, services and user interfaces and integrate and interact with Cwtch. +* **Privacy Preserving**: All communication in Cwtch is end-to-end encrypted and takes place over Tor v3 onion services. +* **Metadata Resistant**: Cwtch has been designed such that no information is exchanged or available to anyone without their explicit consent, including on-the-wire messages and protocol metadata. + + +## A (Brief) History of Metadata Resistant Chat + +In recent years, public awareness of the need and benefits of end-to-end +encrypted solutions has increased with applications like [Signal](https://signalapp.org), +[Whatsapp](https://whatsapp.com) and [Wire](https://wire.org) now providing +users with secure communications. + +However, these tools require various levels of metadata exposure to function, +and much of this metadata can be used to gain details about how and why a person +is using a tool to communicate. [[rottermanner2015privacy]](https://www.researchgate.net/profile/Peter_Kieseberg/publication/299984940_Privacy_and_data_protection_in_smartphone_messengers/links/5a1a9c29a6fdcc50adeb1335/Privacy-and-data-protection-in-smartphone-messengers.pdf). + +One tool that did seek to reduce metadata is [Ricochet](https://ricochet.im) first released in 2014. +Ricochet used Tor v2 onion services to provide secure end-to-end encrypted communication, +and to protect the metadata of communications. + +There were no centralized servers that assist in routing Ricochet +conversations. No one other than the parties involved in a conversation could +know that such a conversation is taking place. + +Ricochet wasn't without limitations; there was no multi-device support, nor is +there a mechanism for supporting group communication or for a user to send +messages while a contact is offline. + +This made adoption of Ricochet a difficult proposition; with even those in +environments that would be served best by metadata resistance unaware that it +exists [[ermoshina2017can]](www.academia.edu/download/53192589/ermoshina-12.pdf) +[[renaud2014doesn]](https://eprints.gla.ac.uk/116203/1/116203.pdf). + +Additionally, any solution to decentralized, metadata resistant communication faces [fundamental problems](https://code.briarproject.org/briar/briar/-/wikis/Fundamental-Problems) +when it comes to efficiency, privacy and group security (as defined by [transcript consensus and consistency](https://code.briarproject.org/briar/briar/-/wikis/Fundamental-Problems)). + +Modern alternatives to Ricochet include [Briar](https://briarproject.org), [Zbay](https://www.zbay.app/) +and [Ricochet Refresh](https://www.ricochetrefresh.net/) - each tool seeks to optimize for a different +set of trade-offs e.g. Briar seeks to allow people to communicate [even when underlying network infrastructure +is down](https://briarproject.org/how-it-works/) while providing resistant to metadata surveillance. + +
+ +The Cwtch project began in 2017 as an extension protocol for Ricochet providing group conversations via +untrusted servers, with an eye to enabling decentralized, metadata resistant applications (like shared lists +and bulletin board) + +An alpha version of Cwtch was [was launched in February 2019](https://openprivacy.ca/blog/2019/02/14/cwtch-alpha/), and +since then the Cwtch team (run by the [Open Privacy Research Society](https://openprivacy.ca)) has conducted +research and development into cwtch and the underlying protocols and libraries and problem spaces. + + + + + diff --git a/security/references.md b/security/references.md new file mode 100644 index 00000000..ca4682c0 --- /dev/null +++ b/security/references.md @@ -0,0 +1,29 @@ +# References + +* Atwater, Erinn, and Sarah Jamie Lewis. "Token Based Services-Differences from Privacy Pass." + +* Brooks, John. Ricochet: Anonymous instant messaging for real privacy. https://ricochet.im. Accessed: 2018-03-10 + +* Ermoshina K, Halpin H, Musiani F. Can johnny build a protocol? co-ordinating developer and user intentions for privacy-enhanced secure messaging protocols. In European Workshop on Usable Security 2017. + +* Ermoshina, K., Musiani, F. and Halpin, H., 2016, September. End-to-end encrypted messaging protocols: An overview. In International Conference on Internet Science (pp. 244-254). Springer, Cham. + +* Farb, M., Lin, Y.H., Kim, T.H.J., McCune, J. and Perrig, A., 2013, September. Safeslinger: easy-to-use and secure public-key exchange. In Proceedings of the 19th annual international conference on Mobile computing & networking (pp. 417-428). + +* Greschbach, B., Kreitz, G. and Buchegger, S., 2012, March. The devil is in the metadata—New privacy challenges in Decentralised Online Social Networks. In 2012 IEEE international conference on pervasive computing and communications workshops (pp. 333-339). IEEE. + +* Langley, Adam. Pond. https://github.com/agl/pond. Accessed: 2018-05-21. + +* Le Blond, S., Zhang, C., Legout, A., Ross, K. and Dabbous, W., 2011, November. I know where you are and what you are sharing: exploiting p2p communications to invade users' privacy. In Proceedings of the 2011 ACM SIGCOMM conference on Internet measurement conference (pp. 45-60). + +* Lewis, Sarah Jamie. "Cwtch: Privacy Preserving Infrastructure for Asynchronous, Decentralized, Multi-Party and Metadata Resistant Applications." (2018). + +* Kalysch, A., Bove, D. and Müller, T., 2018, November. How Android's UI Security is Undermined by Accessibility. In Proceedings of the 2nd Reversing and Offensive-oriented Trends Symposium (pp. 1-10). + +* Renaud, K., Volkamer, M. and Renkema-Padmos, A., 2014, July. Why doesn’t Jane protect her privacy?. In International Symposium on Privacy Enhancing Technologies Symposium (pp. 244-262). Springer, Cham. + +* Rottermanner, C., Kieseberg, P., Huber, M., Schmiedecker, M. and Schrittwieser, S., 2015, December. Privacy and data protection in smartphone messengers. In Proceedings of the 17th International Conference on Information Integration and Web-based Applications & Services (pp. 1-10). + +* Unger, Nik et al. “SoK: secure messaging”. In: Security and Privacy (SP + ), 2015 IEEE Sympo-sium on. IEEE. 2015, pp. 232–249 [link](http://cacr.uwaterloo.ca/techreports/2015/cacr2015-02.pdf) + \ No newline at end of file diff --git a/security/risk.md b/security/risk.md new file mode 100644 index 00000000..69f47048 --- /dev/null +++ b/security/risk.md @@ -0,0 +1,91 @@ +--- +sidebar_position: 2 +--- + +# Risk Model + +Communications metadata is known to be exploited by various adversaries to +undermine the security of systems, to track victims +and to conduct large scale social network analysis to feed mass surveillance. +Metadata resistant tools are in their infancy and research into the construction +and user experience of such tools is lacking. + +![](/img/4.png) + +Cwtch was originally conceived as an extension of the metadata resistant protocol +Ricochet to support asynchronous, multi-peer group communications through the +use of discardable, untrusted, anonymous infrastructure. + +Since then, Cwtch has evolved into a protocol in its own right, this section +will outline the various known risks that Cwtch attempts to mitigate and will +be heavily referenced throughout the rest of the document when discussing the +various sub-components of the Cwtch Architecture. + +## Threat Model + +It is important to identify and understand that metadata is ubiquitous in +communication protocols, it is indeed necessary for such protocols to +function efficiently and at scale. However, information that is useful to +facilitating peers and servers is also highly relevant to adversaries +wishing to exploit such information. + +For our problem definition, we will assume that the content of a communication is +encrypted in such a way that an adversary is practically unable to break +(see [tapir](/security/category/tapir) and [cwtch](security/category/cwtch) for details on the +encryption that we use, a +and as such we will focus to the context to the communication metadata. + +We seek to protect the following communication contexts: + +* Who is involved in a communication? It may be possible to identify + people or simply device or network identifiers. E.g., “this communication involves Alice, a journalist, and Bob a government employee.”. +* Where are the participants of the conversation? E.g., “during this + communication Alice was in France and Bob was in Canada.” +* When did a conversation take place? The timing and length of communication + can reveal a large amount about the nature of a call, e.g., “Bob a government employee, talked to Alice on the phone for an hour yesterday evening. This is the first time they have communicated.” + *How was the conversation mediated? Whether a conversation took place over an + encrypted or unencrypted email can provide useful intelligence. E.g., “Alice sent an encrypted email to Bob yesterday, whereas they usually only send plaintext emails to each other.” +* What is the conversation about? Even if the content of the communication is + encrypted it is sometimes possible to derive a probable context of a conversation without knowing exactly what is said, e.g. “a person called a pizza store at dinner time” or “someone called a known suicide hotline number at 3am.” + +Beyond individual conversations, we also seek to defend against context correlation attacks, whereby multiple conversations are analyzed to derive higher level information: + +* Relationships: Discovering social relationships between a pair of entities + by analyzing the frequency and length of their communications over a period of time. E.g. Carol and Eve call each other every single day for multiple hours at a time. +* Cliques: Discovering social relationships between a group of entities that + all interact with each other. E.g. Alice, Bob and Eve all communicate with each other. +* Loosely Connected Cliques and Bridge Individuals: Discovering groups that + communicate to each other through intermediaries by analyzing communication chains (e.g. everytime Alice talks to Bob she talks to Carol almost immediately after; Bob and Carol never communicate.) +* Pattern of Life: Discovering which communications are cyclical and + predictable. E.g. Alice calls Eve every Monday evening for around an hour. + + +### Active Attacks + +#### Misrepresentation Attacks + +Cwtch provides no global display name registry, and as such people using Cwtch are more vulnerable to attacks +based around misrepresentation i.e. people pretending to be other people: + +A basic flow of one of these attacks is as follows, although other flows also exist: + +- Alice has a friend named Bob and another called Eve +- Eve finds out Alice has a friend named Bob +- Eve creates thousands of new accounts to find one that has a similar picture / public key to Bob (won't be identical but might fool someone for a few minutes) +- Eve calls this new account "Eve New Account" and adds Alice as a friend. +- Eve then changes her name on "Eve New Account" to "Bob" +- Alice sends messages intended for "Bob" to Eve's fake Bob account + +Because misrepresentation attacks are inherently about trust and verification the only absolute way of preventing them +is for users to absolutely validate the public key. This is obviously not-ideal and in many cases simply *won't-happen*. + +As such we aim to provide some user-experience hints in the [ui](/security/category/cwtch-ui) to guide people in making choices around whether +to trust accounts and/or to distinguish accounts that may be attempting to represent themselves as other users. + +## A note on Physical Attacks + +Cwtch does not consider attacks that require physical access (or equivalent) to +the users machine as practically defendable. However, in the interests of good +security engineering, throughout this document we will still +refer to attacks or conditions that require such privilege and point out +where any mitigations we have put in place will fail. \ No newline at end of file diff --git a/static/img/1.png b/static/img/1.png new file mode 100644 index 00000000..65538ea1 Binary files /dev/null and b/static/img/1.png differ diff --git a/static/img/2.png b/static/img/2.png new file mode 100644 index 00000000..4de6eb1c Binary files /dev/null and b/static/img/2.png differ diff --git a/static/img/3.png b/static/img/3.png new file mode 100644 index 00000000..7aac7c0a Binary files /dev/null and b/static/img/3.png differ diff --git a/static/img/4.png b/static/img/4.png new file mode 100644 index 00000000..b404f458 Binary files /dev/null and b/static/img/4.png differ diff --git a/static/img/BASE_0.png b/static/img/BASE_0.png new file mode 100644 index 00000000..384cbefa Binary files /dev/null and b/static/img/BASE_0.png differ diff --git a/static/img/BASE_1.png b/static/img/BASE_1.png new file mode 100644 index 00000000..0adb8240 Binary files /dev/null and b/static/img/BASE_1.png differ diff --git a/static/img/BASE_2.png b/static/img/BASE_2.png new file mode 100644 index 00000000..d1cbb8e5 Binary files /dev/null and b/static/img/BASE_2.png differ diff --git a/static/img/BASE_5.png b/static/img/BASE_5.png new file mode 100644 index 00000000..0330d03b Binary files /dev/null and b/static/img/BASE_5.png differ diff --git a/static/img/BASE_6.png b/static/img/BASE_6.png new file mode 100644 index 00000000..3de5d899 Binary files /dev/null and b/static/img/BASE_6.png differ diff --git a/static/img/BASE_7.png b/static/img/BASE_7.png new file mode 100644 index 00000000..00f730ad Binary files /dev/null and b/static/img/BASE_7.png differ diff --git a/static/img/BASE_8.png b/static/img/BASE_8.png new file mode 100644 index 00000000..3881065e Binary files /dev/null and b/static/img/BASE_8.png differ diff --git a/static/img/card_header.png b/static/img/card_header.png new file mode 100644 index 00000000..aaa0368b Binary files /dev/null and b/static/img/card_header.png differ diff --git a/static/img/cwtch phones.png b/static/img/cwtch phones.png new file mode 100644 index 00000000..54396db9 Binary files /dev/null and b/static/img/cwtch phones.png differ