Skip to content

Commit 83f6b63

Browse files
committed
feat: scan for npx usage in package.json and shell scripts
1 parent 5a3355b commit 83f6b63

File tree

5 files changed

+179
-0
lines changed

5 files changed

+179
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
rules:
2+
- id: npx-usage-json
3+
languages:
4+
- json
5+
severity: WARNING
6+
metadata:
7+
tags: [security]
8+
shortDescription: "npx usage introduces supply chain security risks"
9+
confidence: HIGH
10+
help: |
11+
Using npx to install and run packages introduces significant supply chain security risks for the following reasons:
12+
13+
1. **Unpinned by default**: Running `npx <package>` fetches the latest release outside of your lockfile. If a malicious version of a package is published ([example])(https://socket.dev/blog/npm-author-qix-compromised-in-major-supply-chain-attack), `npx` will install and execute it the next time it is run.
14+
15+
2. **Bypasses lockfile guarantees**: Packages executed with npx are not added to your project's package.json or lockfile. As a result, their versions and lockfile integrity hashes are not captured for reproducibility, making builds non-deterministic and harder to audit
16+
17+
### Recommended practice
18+
- Add packages as dependencies or devDependencies in `package.json`.
19+
- Use your package manager to install and execute them (e.g., `yarn add <package> --dev` followed by `yarn <package> <command>`).
20+
21+
**Bad example (using npx):**
22+
```json
23+
{
24+
"scripts": {
25+
"lint": "npx eslint src/"
26+
}
27+
}
28+
```
29+
30+
**Good example (proper dependency):**
31+
```json
32+
{
33+
"scripts": {
34+
"lint": "eslint src/"
35+
},
36+
"devDependencies": {
37+
"eslint": "^8.0.0"
38+
}
39+
}
40+
```
41+
42+
message: >-
43+
Avoid using 'npx' to run packages due to supply chain security risks. Instead, install the package
44+
as a dependency / devDependency and invoke it using your package manager to ensure version pinning
45+
and reproducibility.
46+
pattern-regex: '"[^"]*":\s*"(\s*npx\s|npx\s)[^"]*"'
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
rules:
2+
- id: npx-usage-shell
3+
languages:
4+
- sh
5+
- dockerfile
6+
severity: WARNING
7+
metadata:
8+
tags: [security]
9+
shortDescription: "npx usage introduces supply chain security risks"
10+
confidence: HIGH
11+
help: |
12+
Using npx to install and run packages introduces significant supply chain security risks for the following reasons:
13+
14+
1. **Unpinned by default**: Running `npx <package>` fetches the latest release outside of your lockfile. If a malicious version of a package is published ([example])(https://socket.dev/blog/npm-author-qix-compromised-in-major-supply-chain-attack), `npx` will install and execute it the next time it is run.
15+
16+
2. **Bypasses lockfile guarantees**: Packages executed with npx are not added to your project's package.json or lockfile. As a result, their versions and lockfile integrity hashes are not captured for reproducibility, making builds non-deterministic and harder to audit
17+
18+
19+
### Recommended practice
20+
- Add packages as dependencies or devDependencies in `package.json`.
21+
- Use your package manager to install and execute them (e.g., `yarn add <package> --dev` followed by `yarn <package> <command>`).
22+
23+
message: >-
24+
Avoid using 'npx' to run packages due to supply chain security risks. Instead, install the package
25+
as a dependency / devDependency and invoke it using your package manager to ensure version pinning
26+
and reproducibility.
27+
patterns:
28+
- pattern: npx ...
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "test-package",
3+
"version": "1.0.0",
4+
"scripts": {
5+
// ruleid: npx-usage-json
6+
"lint": "npx eslint .",
7+
// ruleid: npx-usage-json
8+
"format": "npx prettier --write .",
9+
// ruleid: npx-usage-json
10+
"type-check": "npx tsc --noEmit",
11+
// ruleid: npx-usage-json
12+
"storybook": "npx storybook dev -p 6006",
13+
// ok: npx-usage-json
14+
"test": "yarn jest",
15+
// ok: npx-usage-json
16+
"build": "yarn build",
17+
// ok: npx-usage-json
18+
"start": "yarn start",
19+
// ok: npx-usage-json
20+
"npxify": "yarn npxify",
21+
// ok: npx-usage-json
22+
"setup": "some-npx-tool --config",
23+
// ok: npx-usage-json
24+
"install-npx": "yarn add global-npx"
25+
},
26+
"devDependencies": {
27+
"eslint": "^8.0.0",
28+
"prettier": "^2.8.0"
29+
},
30+
"config": {
31+
// ruleid: npx-usage-json
32+
"setupCommand": "npx setup-tool"
33+
},
34+
"description": "A test package with npx in description - should not be flagged"
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
FROM node:18
2+
3+
WORKDIR /app
4+
5+
COPY package.json yarn.lock ./
6+
7+
# Test npx usage in Dockerfile - should be flagged
8+
# ruleid: npx-usage-shell
9+
RUN npx create-react-app /tmp/test-app
10+
11+
# ruleid: npx-usage-shell
12+
RUN npx --yes @storybook/cli init
13+
14+
# ruleid: npx-usage-shell
15+
RUN npx prettier@2.8.0 --write .
16+
17+
# Test good alternatives - should not be flagged
18+
# ok: npx-usage-shell
19+
RUN yarn install
20+
21+
# ok: npx-usage-shell
22+
RUN yarn build
23+
24+
# ok: npx-usage-shell
25+
RUN yarn dlx create-react-app /tmp/test-app
26+
27+
COPY . .
28+
29+
# ok: npx-usage-shell
30+
RUN yarn test
31+
32+
EXPOSE 3000
33+
34+
CMD ["yarn", "start"]
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
3+
# Test direct npx usage - should be flagged
4+
# ruleid: npx-usage-shell
5+
npx eslint src/
6+
7+
# ruleid: npx-usage-shell
8+
echo "hello world" && npx eslint src/
9+
10+
# ruleid: npx-usage-shell
11+
npx create-react-app my-app
12+
13+
# ruleid: npx-usage-shell
14+
npx @typescript-eslint/parser
15+
16+
# ruleid: npx-usage-shell
17+
npx prettier@2.8.0 --write .
18+
19+
# ruleid: npx-usage-shell
20+
npx --yes create-next-app
21+
22+
# Test good alternatives - should not be flagged
23+
# ok: npx-usage-shell
24+
yarn eslint src/
25+
26+
# ok: npx-usage-shell
27+
yarn dlx create-react-app my-app
28+
29+
# ok: npx-usage-shell
30+
npm run build
31+
32+
# ok: npx-usage-shell
33+
yarn create next-app
34+
35+
# ok: npx-usage-shell
36+
yarn prettier --write .

0 commit comments

Comments
 (0)