Security Features and Practices are just as important in Tauri as in any other technology you are using to develop your applications.
When using Tauri, it provides developers with tools using which
the developers can Lockdown their Tauri Applications and further secure their applications.
In this Article, we will take a closer look at these Security Features and Practices like
- Secure Content Loading using Content Security Policy (CSP)
- Freezing Object Prototype
- Isolation Pattern
- The Allowlist
- API Scoping
- Filesystem Scoping
- Asset Protocol Scoping
- HTTP Scoping
- Shell Scoping
- Importance of Using Specific Rust Commands instead of Generic API Use
- And Finally, Some Big Ole Don’ts by Tauri Developers
to better Understand How to configure Tauri for increased security.
Now, for those who have been following along the article Series
there will be mention of the tauri.conf.json file in this article,
which is the Main Configuration File for a Tauri Application.
Because I know that people following this article series are new to Rust and Tauri,
I thought about just postponing this article as I didn’t want to confuse them
but the information in this article is really important and will help you in Correctly Setting up your Tauri Projects
so even if it confuses you a bit and you don’t understand some of the code,
please bear with me just for this article,
as this article will be Foundation for creating a Secure Tauri Application.
Well that’s it for the introduction.
So, without further ado, let’s get started!
This Article is part of Minimalist Text Editor Using Rust and Tauri Tutorial Series
- Setting Up The Development Environment for Rust Programming Language
- Creating The Rust Project Using Cargo and Understanding Rust Project Folder Structure
- Tauri and Reasons For Using It in Our Rust based Minimalist Text Editor
- Understanding Tauri Multi-Process Architecture, Core Process & WebView Process
- Understanding Tauri Inter-Process Communication (IPC) | Events & Commands
- What is Isolation Pattern in Tauri and Why you should be using it
- Security Features and Practices to understand when Developing Applications using Tauri <— You’re Currently Here :p
Secure Content Loading using Content Security Policy (CSP) | Security Features & Practices
Content Security Policy (CSP) is a layer of security that helps to detect and mitigate certain types of attacks, like
- Cross-Site Scripting (XSS)
- Packet Sniffing
- Data Injection Attacks
- and more.
These attacks are used by Malicious Actors for everything from Data Theft to Malware Distribution.
According to Tauri Documentation, when CSP Protection is enabled in Tauri Configuration File of your project (tauri.conf.json).
Tauri will restricts the Content Security Policy (CSP) of your HTML pages.
Local Scripts are Hashed, Styles and External Scripts are Referenced using a Cryptographic Nonce,
which prevents Unallowed content from being loaded.
The CSP protection is only enabled if csp is set correctly in the “security” section of Tauri configuration file.
By default, csp will be set to null.
{
"tauri": {
"security": {
"csp": null
}
}
}
Freezing Object Prototype | Security Features & Practices
JavaScript is a prototype-based object-oriented programming language instead of a class based one like Java.
So in JavaScript, Each object is linked to a “prototype” and these prototype will be shared between multiple objects
For example, when we use an inbuilt method like toString() with an object,
it is actually a method defined on the prototype rather than that particular object.
Now there is a special type of Injection Attack known as Prototype Pollution
using which a malicious actor can control the default values of the object prototype.
This can be extremely destructive and if successful will allows the attacker to
- Tamper with the logic of the application
- Gain Administrator level access to the server or application
- Allow Remote Code Execution
- or even take down the whole server
with just performing a Malicious Request to an Vulnerable API via HTTP.
Now, I won’t go into much detail here but if you are interested
I found a great article on Prototype Pollution on snyk.io
which will help you a lot in understanding the Dangers of Prototype Pollution.
Now moving on, Tauri, allow you to Freeze the Object Prototype
with just a single key : value pair in the Tauri Configuration File.
{
"tauri": {
"security": {
"freezePrototype": true
}
}
}
By default, freezePrototype is set to false
because a lot of Frontend Frameworks like to mess around with the Object Prototype
and if freezePrototype is set to true then you will get errors when building your application.
If you are interested in using the freezePrototype feature, one of the founders of Tauri, Denjell Thompson-Yvetot
said in a presentation that Svelte works perfectly fine with freezePrototype set to true,
so might want to use Svelte as your JavaScript Framework, atleast when working with Tauri.
Presentation – Tauri Foundations by Daniel Thompson-Yvetot – Rust Linz, February 2022
Isolation Pattern | Security Features & Practices
I’ve talked about Isolation Pattern in detail in the previous article, but to give an overview
Isolation Pattern basically just injects another Isolated Application between the Frontend and the Core Process
to intercept, verify and modify Frontend IPC Messages,
mitigating Unnecessary, Unwanted, Unallowed or Downright Malicious IPC Requests.
Now as I’ve already written an article on it, I’ll not go into more details here
You can refer that article for more details.
Article – Isolation Pattern
The Allowlist | Security Features & Practices
The Allowlist gives developers the power to enable, only the API packages that they need in the WebView i.e. Frontend
while Stripping the functionality of Unnecessary API interfaces from the final binary.
For example, if you don’t need to work with the Filesystem from the WebView, (which is how it should be)
you can modify the tauri.conf.json file and set in all to false for the fs module
or if you just want to not allow Removing Directory from the Frontend,
then you will set only removeDir to false for the fs module
{
"tauri": {
"allowlist": {
"fs": {
"all": false,
"copyFile": false,
"createDir": false,
"readDir": false,
"readFile": false,
"removeDir": false,
"removeFile": false,
"renameFile": false,
"writeFile": false
}
}
}
}
By doing this not only are you reducing the Attack Vectors
using which Malicious Actors can attack your Tauri Application,
but you are also Tree-shaking and removing Unnecessary Functionality
which will in turn reduce the size of your Final Binary Application
API Scoping | Security Features & Practices
Now if you can’t go on without using an API functionality in the Frontend i.e. WebView
Some API modules provides the ability to use API Scoping to restrict the usage of the said API functionality in the Frontend.
Filesystem API Scoping
Filesystem API Scoping allows you to restrict which files and folders can be accessed using the fs module from the Frontend
The “scope” array can be used to write down which paths will be allowed to be accessed from the Frontend,
using glob patterns and predefined variables that resolves to the System Base Directory.
The Predefined Variables include :
$AUDIO, $CACHE, $CONFIG, $DATA, $LOCALDATA, $DESKTOP, $DOCUMENT, $DOWNLOAD, $EXE,
$FONT, $HOME, $PICTURE, $PUBLIC, $RUNTIME, $TEMPLATE, $VIDEO, $RESOURCE, $APP and $CWD
An example of API Scoping the fs module
{
"tauri": {
"allowlist": {
"fs": {
"scope": ["$APP/db/*", "$RESOURCE/check.png"]
}
}
}
}
Asset Protocol API Scoping
You can also restrict what files and folders can be accessed using the Asset Protocol from the Frontend
and the syntax is and predefined variables are the same as with the fs module.
An example of API Scoping the Asset Protocol
{
"tauri": {
"allowlist": {
"path": { "all": true },
"protocol": {
"asset": true,
"assetScope": ["$APP/assets/*"]
}
}
}
}
The above example will only allow the Asset Protocol to access the assets folder inside the App Directory
but if you tried to access anything inside any other directory or even the App Directory itself, you will not be allowed to do so.
HTTP API Scoping
HTTP API Scoping can be used to restrict which URLs and Paths can be accessed using the HTTP module from the Frontend.
An example of API Scoping the HTTP module
{
"tauri": {
"allowlist": {
"http": {
"scope": ["https://*.bitesizedtech.com/*"]
}
}
}
}
Using the above example, the Frontend HTTP module will be able to access bitesizedtech.com and any of it’s subdomains
but will not be able to access for example, google.com or tauri.studio
Shell API Scoping
Tauri offers configuration to define programs and command line arguments that are allowed to be used,
to prevent unrestricted access to Process Spawning,
and it is also a good security hygiene to lock down shell commands from spawning other, unexpected commands.
An Example of Shell API Scoping
{
"tauri": {
"allowlist": {
"shell": {
"scope": [
{
"name": "install-dep",
"cmd": "apt-get",
"args": [
"install",
{
"validator": "(gcc|rustc)$"
}
]
}
],
// allows using the `open` API only using arguments that match this regex
// `true` is also a valid value, which defines the regex as `https?://`.
"open": "^https://github.com/tauri-apps/"
}
}
}
}
Importance of Using Specific Rust Commands instead of Generic API Use | Security Features & Practices
The Tauri API provides access to common native functionality such as
- Filesystem Access
- HTTP requests
- System Notifications
- and more.
These API provide an easy path to JavaScript developers to access the operating system,
but using them can be detrimental to your application’s security if they are not used carefully.
I’ll be using the example given by Tauri Developers below
import { writeFile, Dir } from '@tauri-apps/api/fs'
await writeFile(
{
path: 'report.txt',
contents: 'the file content',
},
{
dir: Dir.App,
}
)
If you have not enabled the Isolation Pattern, an attacker with Remote Code Execution
can overwrite the contents of report.txt in the example above, since that API is Generic and Enabled.
Instead, if you use a Dedicated Rust Command, this is not an issue:
And Yes, I Know that we have not gone into the coding part for or Minimalist Text Editor yet
and most probably you won’t understand the Rust Code below
but there was not other way that i could think of explaining this.
Below we are creating an Asynchronous Function named write_report and are using [tauri::command] annotation to tell Rust that it is a Command
then we are using the .invokehandler() in the main() function and are generating a new handler for write_report inside it
so that write_report function will be available to our Frontend JavaScript
after that in the JavaScript Code we are invoking write_report function.
#[tauri::command]
async fn write_report(app: tauri::AppHandle) -> Result<(), String> {
let app_dir = app.path_resolver().app_dir().expect("failed to get app dir");
let report_path = app_dir.join("report.txt");
std::fs::write(&report_path, "the file content")
.map_err(|e| e.to_string());
Ok(())
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![write_report])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
import { invoke } from '@tauri-apps/api/tauri'
await invoke('write_report')
This example Rust Command written in the Backend cannot be exploited.
Tauri recommends using the WebView as only a UI layer,
keeping the Important logic on the Core layer i.e. the Rust Backend.
Some Big Ole Don’t Dos by Tauri Developers | Security Features & Practices
- DON’T accept content over http:// or ws://
- DON’T ship an app with the Development Console enabled
- DON’T forget to read about XSS i.e. Cross Site Scripting.
- DON’T ship any kind of localhost server unless the app needs to talk to other devices
- DON’T consume JS from a CDN without using an integrity checksum
This Article is part of Minimalist Text Editor Using Rust and Tauri Tutorial Series
- Setting Up The Development Environment for Rust Programming Language
- Creating The Rust Project Using Cargo and Understanding Rust Project Folder Structure
- Tauri and Reasons For Using It in Our Rust based Minimalist Text Editor
- Understanding Tauri Multi-Process Architecture, Core Process & WebView Process
- Understanding Tauri Inter-Process Communication (IPC) | Events & Commands
- What is Isolation Pattern in Tauri and Why you should be using it
- Security Features and Practices to understand when Developing Applications using Tauri <— You’re Currently Here :p
Conclusion
Well Folks! That does it for this article.
I hope that you found this information on Security Practices when Developing Applications using Tauri useful.
In the next article, we will move forward and do a Primer on CSS Grid Layout as we will need it to create our GUI.
May you have success in your career whatever it may be.
See you again in the upcoming articles!
Share this post on Social Media platforms, if you think our content is great.
If you like the content and would like to follow us, we are present on the platforms below
Follow Us On Social Media
Goodbye For Now,
This is your host VP
Signing Off.
Articles On Minimalist Text Editor Using Rust Programming Language And Tauri
Setting Up The Development Environment for Rust Programming Language
Creating The Rust Project Using Cargo and Understanding Rust Project Folder Structure
Tauri and Reasons For Using It in Our Rust based Minimalist Text Editor
Understanding Tauri Multi-Process Architecture, Core Process & WebView Process
Understanding Tauri Inter-Process Communication (IPC) | Events & Commands
What is Isolation Pattern in Tauri and Why you should be using it
Security Features and Practices to understand when Developing Applications using Tauri