<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Doğa Armangil</title>
    <description>The latest articles on Forem by Doğa Armangil (@arma).</description>
    <link>https://forem.com/arma</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1041118%2Fcf26715b-b96c-479f-844d-4df792f52eab.jpeg</url>
      <title>Forem: Doğa Armangil</title>
      <link>https://forem.com/arma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/arma"/>
    <language>en</language>
    <item>
      <title>Preventing supply-chain attacks to the JavaScript ecosystem</title>
      <dc:creator>Doğa Armangil</dc:creator>
      <pubDate>Thu, 24 Oct 2024 22:28:21 +0000</pubDate>
      <link>https://forem.com/arma/preventing-supply-chain-attacks-to-the-javascript-ecosystem-ide</link>
      <guid>https://forem.com/arma/preventing-supply-chain-attacks-to-the-javascript-ecosystem-ide</guid>
      <description>&lt;p&gt;Supply-chain attacks are big problem for the JavaScript ecosystem. In this short post I will outline a straightforward &lt;strong&gt;security measure that can be implemented by all JavaScript runtimes&lt;/strong&gt;, both in-browser and off-browser. This will prevent most of the supply-chain attacks that are plaguing the JavaScript ecosystem today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem: Permission inheritance
&lt;/h2&gt;

&lt;p&gt;Here's a recent incident where websites were hacked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/2024/10/22/researchers-link-polyfill-supply-chain-attack-to-huge-network-of-copycat-gambling-sites/" rel="noopener noreferrer"&gt;Researchers link Polyfill supply chain attack to huge network of copycat gambling sites&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core of the problem is that &lt;strong&gt;JavaScript modules inherit the permissions of the application or module that has called them&lt;/strong&gt;. This is a problem for both in-browser runtimes and off-browser runtimes.&lt;/p&gt;

&lt;p&gt;This problem is further complicated by the fact that the module version that an application depends on can change unbeknownst to the application's author. So even if the codes of all dependencies have been thoroughly reviewed (which is a huge effort in itself), this effort will be wasted if dependency versions haven't been locked down.&lt;/p&gt;

&lt;p&gt;Why not lock down versions and use &lt;a href="https://docs.npmjs.com/cli/v6/using-npm/semver" rel="noopener noreferrer"&gt;semver&lt;/a&gt;-based dependencies? Well, this is mainly because if a module publisher publishes bug-fixes, it's better to use the fixed code. And this is one big reason why JavaScript CDNs such as &lt;a href="https://esm.sh/#docs" rel="noopener noreferrer"&gt;esm.sh&lt;/a&gt; are supporting semvers. &lt;/p&gt;

&lt;h3&gt;
  
  
  💥 How websites are impacted
&lt;/h3&gt;

&lt;p&gt;Web browsers are sandboxed execution environments, so a third-party JavaScript module (3JM) that's imported by a website can't cause any damage to the end-user's device.&lt;/p&gt;

&lt;p&gt;Nevertheless, a 3JM can use the device's compute resources and issue network requests for Bitcoin mining etc, without the website's consent.&lt;/p&gt;

&lt;h3&gt;
  
  
  💥 How off-browser JavaScript applications are impacted
&lt;/h3&gt;

&lt;p&gt;Some off-browser runtimes such as Deno do implement measures to restrict the permissions given to a JavaScript/TypeScript application. But these measures fall short for the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Even if a permission system such as Deno's is enforced, they nevertheless allow JS modules to inherit the caller's permissions without restrictions. This means that if an application has full write permissions, then an email address validator that shouldn't have access to any resources except compute resources can delete user files unbeknownst to the OS user.&lt;/li&gt;
&lt;li&gt;Applications often run with the full privileges of the OS user. For example, for code executed under a tool such &lt;a href="https://jsr.io/@andrewbrey/mdrb" rel="noopener noreferrer"&gt;MDRB&lt;/a&gt; it's currently not possible to restrict permissions to the code that's running.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The current solution
&lt;/h2&gt;

&lt;p&gt;Currently, security teams have put automated processes in place for looking for vulnerabilities in modules that are published on well-known registries such as NPM. This security measure has several shortcomings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scanning all versions of all known modules that were published is incredibly resource-intensive.&lt;/li&gt;
&lt;li&gt;There's no guarantee that all modules that are available in the wild have been scanned.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 Solution: Per-module permissions
&lt;/h2&gt;

&lt;p&gt;To fix these issues, I propose a new per-module permissions system that is backwards-compatible with how JS/TS applications currently work.&lt;/p&gt;

&lt;p&gt;This involves a new optional &lt;code&gt;permissions&lt;/code&gt; configuration that each application and module can declare in their &lt;em&gt;deno.json&lt;/em&gt; / &lt;em&gt;deno.jsonc&lt;/em&gt; / &lt;em&gt;package.json&lt;/em&gt; files. &lt;code&gt;permissions&lt;/code&gt; has 2 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;permissions.self&lt;/code&gt; — This is where the application or module declares the permissions that it and its dependencies require.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permissions.imports&lt;/code&gt; — This is where the application or module declares the permissions that it agrees to allocate to its dependencies. This is a superset of the permissions that each dependency is allowed to require.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's how &lt;code&gt;permissions&lt;/code&gt; would be used by the JS/TS runtime:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When an application or module imports a module &lt;em&gt;M&lt;/em&gt;, the runtime checks whether &lt;em&gt;M&lt;/em&gt;'s &lt;code&gt;permissions.self&lt;/code&gt; is within the limits that the importer imposes on &lt;em&gt;M&lt;/em&gt;. The import throws an error (e.g. &lt;code&gt;PermissionError&lt;/code&gt;) if this is not the case.&lt;/li&gt;
&lt;li&gt;A runtime error is also thrown (e.g. &lt;code&gt;PermissionError&lt;/code&gt;) when a module or application tries to do something it isn't permitted to do. This runtime error can be caught and handled without aborting the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The value of &lt;code&gt;permissions&lt;/code&gt; would be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;self&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;net&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imports&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsr:@org/module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;net&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.example/org/module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;net&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[default]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;net&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compared to the current solution, the solution I propose has several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Lightweight&lt;/em&gt; — Published modules do not need to be scanned.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Thorough&lt;/em&gt; — Permissions are enforced at runtime, so if the right JS/TS engine is used, then even unknown modules cannot fall through the cracks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This seems very straightforward. No modification is required to the JS/TS languages. And if the &lt;code&gt;permissions&lt;/code&gt; configuration is absent, then we fall back to the current situation where the application and its dependency graph all have the permissions that were provided by the command-line arguments ∎&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>cybersecurity</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Qworum upgrades the Web platform for better application support</title>
      <dc:creator>Doğa Armangil</dc:creator>
      <pubDate>Mon, 14 Oct 2024 14:58:29 +0000</pubDate>
      <link>https://forem.com/arma/qworum-upgrades-the-web-platform-for-better-application-support-19ea</link>
      <guid>https://forem.com/arma/qworum-upgrades-the-web-platform-for-better-application-support-19ea</guid>
      <description>&lt;p&gt;The Web was initially conceived as a platform for content rather than applications. &lt;a href="https://qworum.net" rel="noopener noreferrer"&gt;Qworum&lt;/a&gt; is proof that the Web still isn't a full-featured application platform, and that, despite JavaScript. Qworum aims to change that.&lt;/p&gt;

&lt;p&gt;Note that Qworum is not a Web framework but an upgrade to the Web platform itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 What's missing from the Web platform?
&lt;/h2&gt;

&lt;p&gt;There are several big gaps between what applications need and what the current (non-Qworum) Web provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hyperlinks alone are not suitable for linking between applications&lt;/strong&gt;, but they are great for linking between content. When application A1 calls application A2, how will A1 continue its execution once the call to A2 has returned? For this reason, in the Qworum world linking between applications is done through &lt;a href="https://qworum.net/en/specification/v1/#script" rel="noopener noreferrer"&gt;scripts&lt;/a&gt; rather than plain hyperlinks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applications are fundamentally stateful&lt;/strong&gt;, and content is fundamentally stateless. And that's why using the tab history is problematic for applications, but not for content. When was the last time you navigated to a website, signed in, and then went back one page, only to be asked to sign in once again? Last time this happened to me was on Eventbrite. In the Qworum world, the &lt;a href="https://qworum.net/en/specification/v1/#browser-workarounds" rel="noopener noreferrer"&gt;tab history is disabled&lt;/a&gt; so that the UI cannot go out of sync with the application's internal state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object-oriented programming adopted to the Web platform is a winner&lt;/strong&gt;. By structuring web applications and &lt;a href="https://qworum.net/en/specification/v1/#class" rel="noopener noreferrer"&gt;APIs as OOP classes&lt;/a&gt;, Qworum is able to support distributed applications, UI-level integrations, modular application frontends, and composable and distributed user dialogs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚙️ How is Qworum implemented?
&lt;/h2&gt;

&lt;p&gt;Qworum provides a new browser runtime that is implemented as a browser extension. The Qworum runtime is attached to browser tabs instead of individual web pages as the JavaScript runtime is.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧑‍💻 Show me the code
&lt;/h2&gt;

&lt;p&gt;Here is a video presentation I've posted today. If you are short on time the first 6 minutes are conveying the gist of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=AY9kdZYwqco" rel="noopener noreferrer"&gt;🎬 Programming with Qworum&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdtbzw5e1861r8ks3sfai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdtbzw5e1861r8ks3sfai.png" alt="Screenshot of the presentation video" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Time for action
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://qworum.net/en/plans/" rel="noopener noreferrer"&gt;Qworum subscriptions&lt;/a&gt; are available to businesses worldwide at very affordable prices.&lt;/p&gt;

&lt;p&gt;∎&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webapi</category>
      <category>saas</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Qworum upgrades the Web platform with essential application features</title>
      <dc:creator>Doğa Armangil</dc:creator>
      <pubDate>Mon, 14 Oct 2024 14:58:28 +0000</pubDate>
      <link>https://forem.com/arma/qworum-upgrades-the-web-platform-for-better-application-support-cad</link>
      <guid>https://forem.com/arma/qworum-upgrades-the-web-platform-for-better-application-support-cad</guid>
      <description>&lt;p&gt;The Web was initially conceived as a platform for content rather than applications. &lt;a href="https://qworum.net" rel="noopener noreferrer"&gt;Qworum&lt;/a&gt; is proof that the Web still isn't a full-featured application platform, and that, despite JavaScript. Qworum aims to change that.&lt;/p&gt;

&lt;p&gt;Note that Qworum is not a Web framework but an upgrade to the Web platform itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 What's missing from the Web platform?
&lt;/h2&gt;

&lt;p&gt;There is a big gap between what applications need and what the current (non-Qworum) Web provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hyperlinks alone are not suitable for linking between applications&lt;/strong&gt;, but they are great for linking between content. When application A1 calls application A2, how will A1 continue its execution once the call to A2 has returned? For this reason, in the Qworum world, the linking between applications is done through &lt;a href="https://qworum.net/en/specification/v1/#script" rel="noopener noreferrer"&gt;scripts&lt;/a&gt; rather than plain hyperlinks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User dialogs are not "first-class citizens" on the baseline Web&lt;/strong&gt;, yet they are essential for applications. Sending a return address to a dialog as a query parameter (for login, etc) and letting the dialog handle the redirection to the caller at the end is a hack at best, and it doesn't scale. How to keep track of the return address if the dialog calls another dialog? And what if we wish to have a different return address for different error conditions (cancelled by user, etc). These scalability problems are intractable on the baseline Web, yet easily solved on &lt;a href="https://qworum.net/en/platform/" rel="noopener noreferrer"&gt;Qworum's Service Web&lt;/a&gt; through Qworum scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applications are fundamentally stateful&lt;/strong&gt;, and content is fundamentally stateless. And that's why using the tab history is problematic for applications, but not for content. When was the last time you navigated to a website, signed in, and then went back one page, only to be asked to sign in once again? Last time this happened to me was on Eventbrite's website. In the Qworum world, the &lt;a href="https://qworum.net/en/specification/v1/#browser-workarounds" rel="noopener noreferrer"&gt;tab history is disabled&lt;/a&gt; so that the UI cannot go out of sync with the application's internal state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💎 What's in it for me?
&lt;/h2&gt;

&lt;p&gt;On the technical front, Qworum is able to support distributed applications, UI-level integrations, modular application frontends, and composable and distributed user dialogs.&lt;/p&gt;

&lt;p&gt;On the business front, building cohesive IT systems on top of today's fragmented IT landscape consisting of multiple internal applications, partner applications, SaaS and micro-SaaS is a problem that is largely unsolved. As a result, the employee UX is fragmented across multiple applications. Qworum solves this problem, regardless of the degree of fragmentation of the underlying IT landscape.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ How is Qworum implemented?
&lt;/h2&gt;

&lt;p&gt;Qworum provides a new browser runtime that is implemented as a browser extension. The Qworum runtime is attached to browser tabs instead of individual web pages as the JavaScript runtime is.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧑‍💻 Show me a demo, and show me the code
&lt;/h2&gt;

&lt;p&gt;Here is a video presentation I've posted today. If you are short on time the first 6 minutes are conveying the gist of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=AY9kdZYwqco" rel="noopener noreferrer"&gt;🎬 Programming with Qworum&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdtbzw5e1861r8ks3sfai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdtbzw5e1861r8ks3sfai.png" alt="Screenshot of the presentation video" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Time for action
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://qworum.net/en/plans/" rel="noopener noreferrer"&gt;Qworum subscriptions&lt;/a&gt; are available to businesses worldwide at very affordable prices.&lt;/p&gt;

&lt;p&gt;∎&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webapi</category>
      <category>saas</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Interactive Microservices as an Alternative to Micro Front-Ends</title>
      <dc:creator>Doğa Armangil</dc:creator>
      <pubDate>Wed, 08 Mar 2023 12:48:16 +0000</pubDate>
      <link>https://forem.com/arma/interactive-microservices-as-an-alternative-to-micro-front-ends-35fc</link>
      <guid>https://forem.com/arma/interactive-microservices-as-an-alternative-to-micro-front-ends-35fc</guid>
      <description>&lt;p&gt;&lt;strong&gt;[TRENDING ON INFOQ]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.infoq.com/articles/qworum-modular-ui-architecture/" rel="noopener noreferrer"&gt;❝Interactive Microservices as an Alternative to Micro Front-Ends for Modularizing the UI Layer❞&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you may know, the rate of adoption for micro front-ends have been tepid so far, and as a result monolithic frontends remain a significant impediment for microservices architectures. Qworum is a solution to this issue which plagues large-scale software systems.&lt;/p&gt;

&lt;p&gt;Qworum is a frontend PaaS that brings all the benefits of microservices to the UI layer, and makes web UIs fully compatible with microservices architectures. &lt;/p&gt;

&lt;p&gt;Qworum is pioneering several industry-firsts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a new type of microservice (the interactive microservice), &lt;/li&gt;
&lt;li&gt;a new type of web API (the multi-phase web API), &lt;/li&gt;
&lt;li&gt;a platform for distributed web applications,&lt;/li&gt;
&lt;li&gt;a new type of web (Qworum’s Service Web is about interlinked microservices, whereas the World Wide Web and the Semantic Web are about interlinked content).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft4co5gyivu7jwbcwx8u5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft4co5gyivu7jwbcwx8u5.png" alt="Qworum’s “everything is a microservice, including applications” UI paradigm and the “micro frontends plus container applications” UI paradigm" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Qworum’s “everything is a microservice, including applications” UI paradigm and the “micro frontends plus container applications” UI paradigm&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>microservices</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
