Last active
September 19, 2025 11:11
-
-
Save kekru/ec02d97b26b891cea0c44b3d65d2b1aa to your computer and use it in GitHub Desktop.
Revisions
-
kekru revised this gist
Sep 19, 2025 . 1 changed file with 1 addition and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -67,7 +67,7 @@ Add the `cdxgen` to the package.json with a run script Install and create the sbom ```bash npm install # or "npm ci" to be more strict npm run build-app # run whatever you need for your app to build # Create the sbom and prettify the resulting json @@ -77,17 +77,6 @@ npm run pretty-sbom > The file ending `*.cdx.json` is important, at least for Trivy, see [SBOM Detection inside Targets](https://trivy.dev/v0.66/docs/supply-chain/sbom/#sbom-detection-inside-targets) ## Add SBOM to your container image The final step is **just copy the sbom.cdx.json into the root of your container image**. -
kekru renamed this gist
Sep 18, 2025 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
kekru revised this gist
Sep 18, 2025 . 4 changed files with 197 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,6 @@ node_modules/ sbom.cdx.json index.html # this is only for demo purposes, in your real project you want to check in the package-lock.json package-lock.json This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +1,150 @@ # Scan minified node.js JavaScript apps like Angular with your docker container scanner In the (docker) container world, we should use cve scanners like [Trivy](https://trivy.dev/) (free) or [JFrog Xray](https://jfrog.com/xray/) to scan for known vulnerabilities. In most cases, this just works. But it typically does **not** work for statically compiled and minified JavaScript apps like Angular or React apps. This is how to make your minified frontend app scannable with common scanners. In my tests during september 2025, this worked for: * [trivy](https://trivy.dev/) (free) * [JFrog Xray](https://jfrog.com/xray/) (company wide, high priced license) * [Docker Desktop](https://docs.docker.com/scout/) (personal company license) It did not work for * [grype](https://github.com/anchore/grype) (free) ## How do container vulnerability scanners work? Vulnerability scanners typically do the following * Download a database of known vulnerabilities. In my tests JFrog Xray often knows much more vulnerabilities, than Trivy. JFrog seems to have quite a good database * Trying to find out, which components are inside an image and creating an **SBOM** on the fly. They look for linux package managers, common named files, descriptor files like a package-lock.json, etc. to find out what is installed * Compare the created SBOM with the database of known vulnerabilities ## What is the problem with our minified frontend apps? Our frontend apps are compiled and minified to a folder of static html and javascript files. These files are put into a webserver like nginx. We loose the information, what the sources are, from that the app was built. Vulnerability scanners can not find out anymore, which node_modules were needed to build the app, so they can not create a valid SBOM. ## How to solve the problem? We need to help the vulnerability scanner by creating an SBOM at build time and provide it to the final docker image. We use [cdxgen](https://github.com/CycloneDX/cdxgen) here. I also tested trivy to create an SBOM, but cdxgen created a way larger SBOM with much more identified packages. > If you want to try this out yourself, clone this gist: `git clone https://gist.github.com/ec02d97b26b891cea0c44b3d65d2b1aa.git` ## Create the SBOM Lets say we have a small project with the provided [package.json](./package.json) with a few dependencies. Add the `cdxgen` to the package.json with a run script ```json { ... "scripts": { "build-app": "echo 'Hello World' > index.html", // Here you would build your app "create-sbom": "cdxgen --type npm --output sbom.cdx.json", // Create the sbom. File name is important "pretty-sbom": "node -e \"const fs=require('fs');fs.writeFileSync('sbom.cdx.json',JSON.stringify(JSON.parse(fs.readFileSync('sbom.cdx.json','utf8')),null,2))\"" }, ... "devDependencies": { "@cyclonedx/cdxgen": "11.5.0" } } ``` Install and create the sbom ```bash npm install npm run build-app # run whatever you need for your app to build # Create the sbom and prettify the resulting json npm run create-sbom npm run pretty-sbom ``` > The file ending `*.cdx.json` is important, at least for Trivy, see [SBOM Detection inside Targets](https://trivy.dev/v0.66/docs/supply-chain/sbom/#sbom-detection-inside-targets) ### Alternative: Create SBOM without package.json modification If you dont want to add cdxgen to your package.json, here is another two-liner, that does the same: ```bash npx -y @cyclonedx/[email protected] --type npm --output sbom.cdx.json # Formatting: node -e "const fs=require('fs');fs.writeFileSync('sbom.cdx.json',JSON.stringify(JSON.parse(fs.readFileSync('sbom.cdx.json','utf8')),null,2))" ``` ## Add SBOM to your container image The final step is **just copy the sbom.cdx.json into the root of your container image**. The vulnerability scanners will find it there. Lets build a docker image based on nginx, with our app and the SBOM added: docker-compose.yaml: ```yaml services: app: image: example.com/my-app:0.0.1 pull_policy: build build: context: . dockerfile_inline: | FROM nginx:1.28.0-alpine # index.html is your app COPY index.html /usr/share/nginx/html/index.html # SBOM containing all modules that were needed to build the app COPY sbom.cdx.json /sbom.cdx.json ports: - 80:80 ``` ```bash # Build it, resulting in an image "example.com/my-app:0.0.1" $ docker compose build # Scan using trivy -> it should find vulnerabilities for axios and form-data $ trivy image --severity HIGH,CRITICAL example.com/my-app:0.0.1 Node.js (node-pkg) ================== Total: 2 (HIGH: 1, CRITICAL: 1) ┌───────────┬────────────────┬──────────┬────────┬───────────────────┬─────────────────────┬────────────────────────────────────────────────┐ │ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title │ ├───────────┼────────────────┼──────────┼────────┼───────────────────┼─────────────────────┼────────────────────────────────────────────────┤ │ axios │ CVE-2025-58754 │ HIGH │ fixed │ 1.8.4 │ 1.12.0 │ axios: Axios DoS via lack of data size check │ │ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2025-58754 │ ├───────────┼────────────────┼──────────┤ ├───────────────────┼─────────────────────┼────────────────────────────────────────────────┤ │ form-data │ CVE-2025-7783 │ CRITICAL │ │ 4.0.2 │ 2.5.4, 3.0.4, 4.0.4 │ form-data: Unsafe random function in form-data │ │ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2025-7783 │ └───────────┴────────────────┴──────────┴────────┴───────────────────┴─────────────────────┴────────────────────────────────────────────────┘ # Scan using docker scout (only if you have a paid Docker Desktop) $ docker scout cves --only-severity critical,high example.com/my-app:0.0.1 # In a paid Docker Desktop, you can also open the Docker Desktop UI -> Images -> Search "example.com/my-app:0.0.1" and click "Start analysis" # If your "example.com" is your Artifactory with Xray enabled, push the app and view the results in Artifactorys web ui $ docker compose build --push ``` ## Summary Whenever you have a compiled/minified app, that can not be easily introspected by common scanners, provide an SBOM in the cyclonedx format and put it into `/sbom.cdx.json` inside your resulting container image. Then the vulnerability scanners should find it and use it as the source to compare against their vulnerability database. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,14 @@ services: app: image: example.com/my-app:0.0.1 pull_policy: build build: context: . dockerfile_inline: | FROM nginx:1.28.0-alpine # index.html is your app COPY index.html /usr/share/nginx/html/index.html # SBOM containing all modules that were needed to build the app COPY sbom.cdx.json /sbom.cdx.json ports: - 80:80 This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,28 @@ { "name": "scan-minified-node-apps", "version": "0.0.1", "description": "", "main": "index.js", "scripts": { "build-app": "echo 'Hello World' > index.html", "create-sbom": "cdxgen --type npm --output sbom.cdx.json", "pretty-sbom": "node -e \"const fs=require('fs');fs.writeFileSync('sbom.cdx.json',JSON.stringify(JSON.parse(fs.readFileSync('sbom.cdx.json','utf8')),null,2))\"" }, "repository": { "type": "git", "url": "git+ssh://[email protected]/ec02d97b26b891cea0c44b3d65d2b1aa.git" }, "author": "", "license": "MIT", "bugs": { "url": "https://gist.github.com/ec02d97b26b891cea0c44b3d65d2b1aa" }, "homepage": "https://gist.github.com/ec02d97b26b891cea0c44b3d65d2b1aa", "dependencies": { "axios": "1.8.4", "form-data": "4.0.2" }, "devDependencies": { "@cyclonedx/cdxgen": "11.5.0" } } -
kekru created this gist
Sep 18, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ # Scan minified node.js JavaScript apps like Angular with your docker container scanner