From 338d2c111ffb9f687300e6c4ccc6037796a4b704 Mon Sep 17 00:00:00 2001 From: jaschdoc <60233376+jaschdoc@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:07:00 +0100 Subject: [PATCH 1/7] docs: add section on trust --- src/packages.md | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/packages.md b/src/packages.md index da38dd5c..e469b7e9 100644 --- a/src/packages.md +++ b/src/packages.md @@ -1,7 +1,7 @@ ## Package Management Every non-trivial Flix project should have a `flix.toml` manifest. The manifest -contains information about the project and its dependencies. +contains information about the project and its dependencies. A minimal manifest is of the form: @@ -15,7 +15,7 @@ license = "Apache-2.0" authors = ["John Doe "] ``` -> **Note:** The `flix` field is not yet used, but it will be used in the future. +> **Note:** The `flix` field is not yet used, but it will be used in the future. ### Adding Flix Dependencies @@ -43,9 +43,9 @@ We can also add dependencies on Maven packages to the manifest: Flix dependency resolution works as follows: 1. Flix reads `flix.toml` and computes the transitive set of Flix package - dependencies. + dependencies. 2. Flix downloads all of these Flix packages. -3. Flix inspects each package for its Maven dependencies and downloads these. +3. Flix inspects each package for its Maven dependencies and downloads these. We illustrate with an example. Assume we have a Flix package with: @@ -87,3 +87,35 @@ This happens because `flix/museum` has the following dependency tree: - `flix/museum-clerk` - `flix/museum-restaurant` which depends on - `org.apache.commons:commons-lang3` + +### Security +To prevent supply-chain attacks (some, not all), all dependencies +have a *trust* level--even when you don't specify one. +A trust level defines what features of the language are enabled. +Setting a higher trust level enables more features. +However, these features are also more unsafe and may expose you +to supply-chain attacks. +The levels are as follows (from lowest to highest): +- `pure`: prohibits any use of the `IO`, Java, and unchecked casts. +- `plain` (default): allows the `IO` effect, but prohibits any use of + Java and unchecked casts. +- `unrestricted`: allows everything, including `IO`, Java, and unchecked casts. + +Java and unchecked casts are always bundled together since Java may have +effects that are not captured by the effect system. +Similarly, using unchecked casts allows an author to lie to the type system, +e.g., when using default handlers, thus allowing them to perform effects +from within pure Flix code which is equally dangerous. + +You can set the trust level of each dependency in the manifest like so: +```toml +[dependencies] +"github:flix/museum" = { "version" = "1.4.0", "trust" = "plain" } +"github:magnus-madsen/helloworld" = { "version" = "1.3.0", "trust" = "unrestricted" } +``` + +#### Transitive dependencies +TODO +- Graph inconsistency +- Mentioning Java deps (prevents static initializers since nothing is downloaded) +- Language feature check in Safety From 7afdb83ac8d1062abcc413ab06ec2eea80ed4ce0 Mon Sep 17 00:00:00 2001 From: jaschdoc <60233376+jaschdoc@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:36:01 +0100 Subject: [PATCH 2/7] revise paragraph --- src/packages.md | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/packages.md b/src/packages.md index e469b7e9..58391fd7 100644 --- a/src/packages.md +++ b/src/packages.md @@ -95,18 +95,13 @@ A trust level defines what features of the language are enabled. Setting a higher trust level enables more features. However, these features are also more unsafe and may expose you to supply-chain attacks. + The levels are as follows (from lowest to highest): - `pure`: prohibits any use of the `IO`, Java, and unchecked casts. - `plain` (default): allows the `IO` effect, but prohibits any use of Java and unchecked casts. - `unrestricted`: allows everything, including `IO`, Java, and unchecked casts. -Java and unchecked casts are always bundled together since Java may have -effects that are not captured by the effect system. -Similarly, using unchecked casts allows an author to lie to the type system, -e.g., when using default handlers, thus allowing them to perform effects -from within pure Flix code which is equally dangerous. - You can set the trust level of each dependency in the manifest like so: ```toml [dependencies] @@ -114,8 +109,27 @@ You can set the trust level of each dependency in the manifest like so: "github:magnus-madsen/helloworld" = { "version" = "1.3.0", "trust" = "unrestricted" } ``` -#### Transitive dependencies -TODO -- Graph inconsistency -- Mentioning Java deps (prevents static initializers since nothing is downloaded) -- Language feature check in Safety +Trust levels apply transitively, so any transitive dependency are also +trusted with your original trust level (or lower if one of your dependencies +specifies its own dependencies with less trust). +In case two or more dependencies depend on the same library, the lowest +level of trust given to the library is used. + +The recommended approach is to not specify a trust level, i.e., using `plain`, +which is maximally flexible while keeping you safe. +You strive towards never using `unrestricted`, as it allows the dependencies +along with its transitive dependencies code to do *anything*. +Even running the Flix compiler on code with `unrestricted` trust may expose +you to a security risk. + +If you are the author of a Flix library and you choose to use Java, +the best course of action is to split the library in two; +One library that defines the core logic and uses custom effects +to achieve its goals and another library that defines handlers +for these effects. +The added benefit is that the core library is easier to test than +if the effects were performed by Java. +Additionally, you should attempt to keep your effects simple +and document how users can handle your effects if they do +not want to use your handler library, e.g., how the effects +should behave on certain inputs. From 1fb1ec75dc19be1c15cf73fc95a39e0432f934ad Mon Sep 17 00:00:00 2001 From: jaschdoc <60233376+jaschdoc@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:45:59 +0100 Subject: [PATCH 3/7] revise paragraph --- src/packages.md | 71 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/src/packages.md b/src/packages.md index 58391fd7..73de6a38 100644 --- a/src/packages.md +++ b/src/packages.md @@ -89,18 +89,17 @@ This happens because `flix/museum` has the following dependency tree: - `org.apache.commons:commons-lang3` ### Security -To prevent supply-chain attacks (some, not all), all dependencies -have a *trust* level--even when you don't specify one. -A trust level defines what features of the language are enabled. -Setting a higher trust level enables more features. -However, these features are also more unsafe and may expose you -to supply-chain attacks. - -The levels are as follows (from lowest to highest): -- `pure`: prohibits any use of the `IO`, Java, and unchecked casts. -- `plain` (default): allows the `IO` effect, but prohibits any use of - Java and unchecked casts. -- `unrestricted`: allows everything, including `IO`, Java, and unchecked casts. +To reduce supply-chain attacks, every dependency has a *trust* +level--even if you don't set one explicitly. +Trust levels control which language features a dependency may use. +Higher trust levels enable more features but also increase +the risk of supply-chain attacks. + +The trust levels are as follows (from lowest to highest): +- `pure`: forbids Java interop, the `IO` effect, and unchecked casts. +- `plain` (default): permits the `IO` effect but forbids Java interop + and unchecked casts. +- `unrestricted`: allows Java interop, the IO effect, and unchecked casts. You can set the trust level of each dependency in the manifest like so: ```toml @@ -109,27 +108,27 @@ You can set the trust level of each dependency in the manifest like so: "github:magnus-madsen/helloworld" = { "version" = "1.3.0", "trust" = "unrestricted" } ``` -Trust levels apply transitively, so any transitive dependency are also -trusted with your original trust level (or lower if one of your dependencies -specifies its own dependencies with less trust). -In case two or more dependencies depend on the same library, the lowest -level of trust given to the library is used. - -The recommended approach is to not specify a trust level, i.e., using `plain`, -which is maximally flexible while keeping you safe. -You strive towards never using `unrestricted`, as it allows the dependencies -along with its transitive dependencies code to do *anything*. -Even running the Flix compiler on code with `unrestricted` trust may expose -you to a security risk. - -If you are the author of a Flix library and you choose to use Java, -the best course of action is to split the library in two; -One library that defines the core logic and uses custom effects -to achieve its goals and another library that defines handlers -for these effects. -The added benefit is that the core library is easier to test than -if the effects were performed by Java. -Additionally, you should attempt to keep your effects simple -and document how users can handle your effects if they do -not want to use your handler library, e.g., how the effects -should behave on certain inputs. +Trust levels are transitive: a dependency's trust level also applies +to its transitive dependencies, unless a dependency explicitly declares +a lower trust level. +If multiple dependencies require the same library, +the library inherits the lowest trust level requested. + +The recommended approach is to **not** specify a trust level, thus +defaulting to `plain`. +It provides the best balance of flexibility and safety. +You should avoid unrestricted when possible, as it permits +(transitive) dependencies to do *anything*. +Even building or compiling code that includes unrestricted dependencies +can by itself expose you to a supply-chain attack. +To keep you safe, the package manager never downloads a package +that requires Java dependencies if it has trust level `plain` +or lower. + +If you author a Flix library that uses Java, split it into two +packages: a core library that implements pure logic and custom +effects, and a separate handler package that performs Java interop. +This makes the core library easier to test and review. +Keep effects small and document the expected handler behavior so +users can implement their own handlers if they do no wish to +use handler library. From 03e02f8271005a0140d679ad4cb7652b97a2d0bd Mon Sep 17 00:00:00 2001 From: jaschdoc <60233376+jaschdoc@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:48:37 +0100 Subject: [PATCH 4/7] revise wording --- src/packages.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/packages.md b/src/packages.md index 73de6a38..45294e56 100644 --- a/src/packages.md +++ b/src/packages.md @@ -116,14 +116,14 @@ the library inherits the lowest trust level requested. The recommended approach is to **not** specify a trust level, thus defaulting to `plain`. -It provides the best balance of flexibility and safety. +It provides the best balance between flexibility and safety. You should avoid unrestricted when possible, as it permits (transitive) dependencies to do *anything*. Even building or compiling code that includes unrestricted dependencies can by itself expose you to a supply-chain attack. -To keep you safe, the package manager never downloads a package -that requires Java dependencies if it has trust level `plain` -or lower. +However, the package manager never downloads a package +that declares Java dependencies in its manifest if it has +trust level `plain` or lower. If you author a Flix library that uses Java, split it into two packages: a core library that implements pure logic and custom From fdf3a2674dc84fc0fb573468344077498eb166ef Mon Sep 17 00:00:00 2001 From: jaschdoc <60233376+jaschdoc@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:49:36 +0100 Subject: [PATCH 5/7] fix io styling --- src/packages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages.md b/src/packages.md index 45294e56..1e5a8617 100644 --- a/src/packages.md +++ b/src/packages.md @@ -99,7 +99,7 @@ The trust levels are as follows (from lowest to highest): - `pure`: forbids Java interop, the `IO` effect, and unchecked casts. - `plain` (default): permits the `IO` effect but forbids Java interop and unchecked casts. -- `unrestricted`: allows Java interop, the IO effect, and unchecked casts. +- `unrestricted`: allows Java interop, the `IO` effect, and unchecked casts. You can set the trust level of each dependency in the manifest like so: ```toml From 1365e5e8f5ee07427bc9ccdb0a73585a16fdbe6b Mon Sep 17 00:00:00 2001 From: jaschdoc <60233376+jaschdoc@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:53:34 +0100 Subject: [PATCH 6/7] add paragraph --- src/packages.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/packages.md b/src/packages.md index 1e5a8617..f032d406 100644 --- a/src/packages.md +++ b/src/packages.md @@ -117,18 +117,24 @@ the library inherits the lowest trust level requested. The recommended approach is to **not** specify a trust level, thus defaulting to `plain`. It provides the best balance between flexibility and safety. -You should avoid unrestricted when possible, as it permits +You should avoid `unrestricted` when possible, as it permits (transitive) dependencies to do *anything*. -Even building or compiling code that includes unrestricted dependencies +Even building or compiling code that includes `unrestricted` dependencies can by itself expose you to a supply-chain attack. However, the package manager never downloads a package that declares Java dependencies in its manifest if it has trust level `plain` or lower. +You should attempt to only depend on core library packages +and use your own handlers (or in some cases default handlers). +This allows you to limit what parts of the system a program +can access, e.g., such as only allowing certain directories +to be accessed or black/white-listing URLs. + If you author a Flix library that uses Java, split it into two packages: a core library that implements pure logic and custom effects, and a separate handler package that performs Java interop. -This makes the core library easier to test and review. -Keep effects small and document the expected handler behavior so -users can implement their own handlers if they do no wish to -use handler library. +Doing so also makes the core library easier to test and review. +Try to keep effects small and focues and document the expected +handler behavior so users can implement their own handlers if +they do no wish to use handler library. From ab984e858993faf4b091c3b68ce4ad76f1f19891 Mon Sep 17 00:00:00 2001 From: jaschdoc <60233376+jaschdoc@users.noreply.github.com> Date: Wed, 29 Oct 2025 18:10:22 +0100 Subject: [PATCH 7/7] update with feedback --- src/packages.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/packages.md b/src/packages.md index f032d406..46c31564 100644 --- a/src/packages.md +++ b/src/packages.md @@ -88,15 +88,15 @@ This happens because `flix/museum` has the following dependency tree: - `flix/museum-restaurant` which depends on - `org.apache.commons:commons-lang3` -### Security -To reduce supply-chain attacks, every dependency has a *trust* -level--even if you don't set one explicitly. +### Security & Trust Levels +To reduce the risk of supply-chain attacks, every dependency +has a *trust* level--even if you don't set one explicitly. Trust levels control which language features a dependency may use. Higher trust levels enable more features but also increase the risk of supply-chain attacks. The trust levels are as follows (from lowest to highest): -- `pure`: forbids Java interop, the `IO` effect, and unchecked casts. +- `paranoid`: forbids Java interop, the `IO` effect, and unchecked casts. - `plain` (default): permits the `IO` effect but forbids Java interop and unchecked casts. - `unrestricted`: allows Java interop, the `IO` effect, and unchecked casts. @@ -131,9 +131,10 @@ This allows you to limit what parts of the system a program can access, e.g., such as only allowing certain directories to be accessed or black/white-listing URLs. -If you author a Flix library that uses Java, split it into two -packages: a core library that implements pure logic and custom -effects, and a separate handler package that performs Java interop. +If you author a Flix library, e.g., `webserver`, that uses Java, +split it into two packages: a core library `webserver-lib` that +implements pure logic and custom effects, and a separate handler +package `webserver-lib-handlers` that performs Java interop. Doing so also makes the core library easier to test and review. Try to keep effects small and focues and document the expected handler behavior so users can implement their own handlers if