:rotating_light: We have published an additional f...
# javascript
s
🚨 We have published an additional follow-up post on how to use yarn.lock with Kotlin/JS, and disable Yarn’s lifecycle scripts. The solutions outlined in the blog post are workarounds, and we’re working on providing direct support for persistent 
yarn.lock
 files and fine-grained control over Yarn’s lifecycle scripts in Kotlin/JS and Kotlin Multiplatform projects directly. https://blog.jetbrains.com/kotlin/2021/10/control-over-npm-dependencies-in-kotlin-js/
🙏 1
🙏 5
👍 3
o
Good to hear that you are actively working on this. This is not a new phenomenon but reminds us of its severity. Npm accounts have seen peaceful takeovers by malevolent "maintainers" before (see this article from 2018 https://lwn.net/Articles/773121/). The current incident appeared to have started with stolen credentials, and opens up a path for further supply-chain attacks by stealing even more passwords (https://www.bleepingcomputer.com/news/security/popular-npm-library-hijacked-to-install-password-stealers-miners/). If there is something to be learned from this and previous incidents, I'd say it is that we all must accept more responsibility for the safety and integrity of anything we install and publish, and this includes all of its dependencies. The current state of the Npm ecosystem seems to be that most projects blindly trust their dependencies. With "ua-parser", Karma trusted everything from 0.7.28 to <1.0.0. Then 0.7.29 compromised developer systems. Now Karma accepts 0.7.30 to <1.0.0. History can (and most probably will) repeat itself. Freezing dependencies via "yarn.lock" is a band-aid, as it puts all the burden on the final developer in the supply chain. Not only must she check her dependencies, but also the dependencies of dependencies, and so on. While this is probably the best short-term solution we have and should be implemented quickly, it does not scale with increasing numbers of updates to (transitive) dependencies. And who would have the time and qualification to check dependencies several levels up the supply chain? It would be ideal if each project would carefully select and vet each dependency and then pin its version number (i.e. use "0.7.30" instead of "^0.7.30"). Then each of us would only have to check direct dependencies for trustworthiness. If projects won't accept responsibility for this (and I am not optimistic in that regard), what can we do to enjoy a safe development environment? Build a web of trust for published packages? Use measurements to at least delay the spread of unverified code? What are the best options available today and what might be a viable path into the future?
m
I'm confused how much of this code is required. In the maven world, I think it's pretty well established that version ranges shouldn't be used. Not only are they exposing you to malware but they make builds irreproducible.
I would expect the huge majority of Kotlin/JS dev to use fixed JS dependencies with something like:
Copy code
implementation(npm("myDep", "1.2.3"))
If I do that for all my dependencies, do I still need the code from the article?
o
Yes, you do. Pinning version numbers for your direct dependencies still exposes you to dynamic transitive dependencies. The latter are uncommon for Maven and Gradle users, but they are routine in the JS ecosystem.
Also note that disabling lifecycle (install) scripts is essential. These are executed right after a dependency is downloaded from the npm registry, even before you have a chance of validating your
yarn.lock
file. After installation, there are two kinds of javascript executables: Runtime dependencies and development dependencies. • Runtime dependencies execute in the browser's sandbox, which reduces the attack surface. However, their code may have access to whatever data your app processes. • Development dependencies (such as the Karma test runner) execute in a Node environment with local user privileges, including file system access.
I wanted to avoid auto-running any JS dependency which might just have been installed and not yet captured in a verified yarn.lock file. To achieve this, I have added a
kotlinNpmInstall.finalizedBy(yarnLockValidate)
dependency to my Gradle build script, which stops the build process if the verification fails. (Note that my build script slightly differs from the one posted in the Blog, as I'm using delegates and a different name, but you should get the idea.)
m
The latter are uncommon for Maven and Gradle users, but they are routine in the JS ecosystem.
I see, thanks!
🙂 1
f
also FYI if you are doing this step-by-step: first only add the
disableGranularWorkspaces
part and the
backupYarnLock
gradle task, then generate the
yarn.lock.bak
file by executing the
backupYarnLock
task, and then add the remaining tasks described in the article
🙏 1
n
Can someone help me debug this?
Task with name 'kotlinNpmInstall' not found in project ':web-app'.
Even when I did them step by step as @functionaldude described
f
@Nikola Milovic I just took a look at your `build.gradle.kts`file, my project setup and `build.gradle.kts`file for my frontend is very similar. maybe the issue lies in the root project`s gradle file?
n
@functionaldude thanks for taking a look, I added more gradle files in the stackoverflow question. But honestly my gradle setup is quite minimal, not sure that these other files are the culprits.
f
@Nikola Milovic I just took a look and now i’m a little confused. so you have a root gradle file (same here), then you have a gradle file in the “web-app” directory (i assume this is declared with an “include” in the
settings.gradle.kts
) but what’s the “BuildSrc build.gradle”?
n
@functionaldude Yeah, I have a multiplatform project, so Web-app is just a module targeting the web. Hence I have the rootlevel buildgradle, and for the buildSrc, can't say much other than it specifies my project level Gradle dependencies ( classpath?). Since I got this architecture/ project setup from some github project I cannot say for sure but that's basically the idea behind this setup. I keep my deps inside the buildSrc alongside my plugins
f
@Nikola Milovic hmmm… strange. I think the problem is that the gradle files get evaluated in the wrong order, because `kotlinNpmInstall`is missing from the root project. can you maybe point me to the github project, where you got the project setup?
n