@merupatel/reachable 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/cli/index.d.cts +6 -0
- package/dist/cli/index.js +210740 -0
- package/dist/package.json +3 -0
- package/package.json +79 -0
package/CHANGELOG.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# reachable
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
`reachable` is a local-first CLI that answers the question developers ask after `npm audit`: is the vulnerable code path actually reachable from my application?
|
|
8
|
+
|
|
9
|
+
It parses JavaScript and TypeScript with tree-sitter, builds a project call graph, queries OSV advisories, and reports whether the vulnerable symbol is reachable, unknown, or unreachable from your entry points.
|
|
10
|
+
|
|
11
|
+
## Why reachable?
|
|
12
|
+
|
|
13
|
+
`npm audit` reports package-level risk. It does not know whether your code imports or calls the vulnerable function. That leads to noisy CI failures, broad dependency upgrade churn, and teams ignoring entire audit reports.
|
|
14
|
+
|
|
15
|
+
`reachable` adds source-aware triage:
|
|
16
|
+
|
|
17
|
+
- It traces entry points through your code instead of flagging every installed vulnerable package equally.
|
|
18
|
+
- It separates `REACHABLE`, `UNKNOWN`, and `UNREACHABLE` findings so real risk rises to the top.
|
|
19
|
+
- It works locally in CI without a hosted service, account, or API key.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g @merupatel/reachable
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Run without installing globally:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx reachable scan
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
Scan the current project:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
reachable scan --format table
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Example terminal output:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
REACHABLE
|
|
45
|
+
+-----------+---------+----------------------+------------+-------------------+
|
|
46
|
+
| Severity | Package | GHSA ID | Status | Vulnerable Symbol |
|
|
47
|
+
+-----------+---------+----------------------+------------+-------------------+
|
|
48
|
+
| HIGH | lodash | GHSA-xxxx-yyyy-zzzz | REACHABLE | trim |
|
|
49
|
+
+-----------+---------+----------------------+------------+-------------------+
|
|
50
|
+
src/index.ts::module
|
|
51
|
+
src/index.ts::call:lodash.trim:12
|
|
52
|
+
|
|
53
|
+
UNREACHABLE
|
|
54
|
+
+-----------+---------+----------------------+--------------+-------------------+
|
|
55
|
+
| Severity | Package | GHSA ID | Status | Vulnerable Symbol |
|
|
56
|
+
+-----------+---------+----------------------+--------------+-------------------+
|
|
57
|
+
| HIGH | lodash | GHSA-aaaa-bbbb-cccc | UNREACHABLE | trim |
|
|
58
|
+
+-----------+---------+----------------------+--------------+-------------------+
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Trace a package from the entry point:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
reachable trace lodash
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Inspect a single file's imports, exports, and reachable symbols:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
reachable graph src/index.ts
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Configuration
|
|
74
|
+
|
|
75
|
+
`reachable` loads project configuration from `.reachablerc.json` or `reachable.config.js`.
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"entry": ["src/index.ts", "src/worker.ts"],
|
|
82
|
+
"failOn": "high",
|
|
83
|
+
"ignore": ["GHSA-xxxx-xxxx-xxxx"],
|
|
84
|
+
"devPackages": ["vitest", "@types/node"],
|
|
85
|
+
"cache": {
|
|
86
|
+
"ttlHours": 24,
|
|
87
|
+
"dir": ".reachable-cache"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Configuration fields:
|
|
93
|
+
|
|
94
|
+
| Field | Type | Description |
|
|
95
|
+
| --- | --- | --- |
|
|
96
|
+
| `entry` | `string[]` | Explicit entry points when auto-detection is not enough |
|
|
97
|
+
| `failOn` | `critical \| high \| moderate \| low \| all` | Minimum reachable severity that sets a failing exit code |
|
|
98
|
+
| `ignore` | `string[]` | GHSA IDs to suppress |
|
|
99
|
+
| `devPackages` | `string[]` | Packages treated as dev-only and excluded from lockfile analysis |
|
|
100
|
+
| `cache.ttlHours` | `number` | Advisory cache TTL |
|
|
101
|
+
| `cache.dir` | `string` | Advisory cache directory |
|
|
102
|
+
|
|
103
|
+
## Flags Reference
|
|
104
|
+
|
|
105
|
+
### `reachable scan`
|
|
106
|
+
|
|
107
|
+
| Flag | Type | Default | Description |
|
|
108
|
+
| --- | --- | --- | --- |
|
|
109
|
+
| `--entry <files...>` | `string[]` | auto-detect | Override detected entry points |
|
|
110
|
+
| `--format <format>` | `table \| json \| sarif \| markdown` | `table` | Output format |
|
|
111
|
+
| `--fail-on <severity>` | `critical \| high \| moderate \| low \| all` | `high` | Failure threshold |
|
|
112
|
+
| `--reachable-only` | `boolean` | `false` | Show only reachable advisories |
|
|
113
|
+
| `--no-cache` | `boolean` | `false` | Ignore and clear the local advisory cache |
|
|
114
|
+
| `--dry-run` | `boolean` | `false` | Skip remote advisory fetches and use cache only |
|
|
115
|
+
| `--quiet` | `boolean` | `false` | Suppress formatter output |
|
|
116
|
+
| `--depth <number>` | `number` | `20` | Maximum traversal depth |
|
|
117
|
+
| `--ignore <ids...>` | `string[]` | `[]` | Ignore GHSA identifiers |
|
|
118
|
+
| `--cwd <path>` | `string` | current directory | Project root to analyze |
|
|
119
|
+
| `--verbose` | `boolean` | `false` | Enable debug logging |
|
|
120
|
+
|
|
121
|
+
### `reachable trace`
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
reachable trace <package> [--cwd <path>] [--entry <files...>]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `reachable graph`
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
reachable graph <file> [--cwd <path>] [--entry <files...>]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## CI Integration
|
|
134
|
+
|
|
135
|
+
Minimal GitHub Actions usage:
|
|
136
|
+
|
|
137
|
+
```yaml
|
|
138
|
+
name: Reachability
|
|
139
|
+
|
|
140
|
+
on:
|
|
141
|
+
pull_request:
|
|
142
|
+
|
|
143
|
+
jobs:
|
|
144
|
+
reachable:
|
|
145
|
+
runs-on: ubuntu-latest
|
|
146
|
+
steps:
|
|
147
|
+
- uses: actions/checkout@v4
|
|
148
|
+
- uses: actions/setup-node@v4
|
|
149
|
+
with:
|
|
150
|
+
node-version: 22
|
|
151
|
+
cache: npm
|
|
152
|
+
- run: npm ci
|
|
153
|
+
- run: npx reachable scan --format markdown --fail-on high
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Use `--format sarif` to feed GitHub code scanning or `--format markdown` to post PR-friendly summaries.
|
|
157
|
+
|
|
158
|
+
## Development
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm ci
|
|
162
|
+
npm run lint
|
|
163
|
+
npm run test
|
|
164
|
+
npm run test-integration
|
|
165
|
+
npm run build
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The project uses:
|
|
169
|
+
|
|
170
|
+
- tree-sitter for source parsing
|
|
171
|
+
- commander for the CLI
|
|
172
|
+
- vitest for unit and integration tests
|
|
173
|
+
- semantic-release for release automation
|
|
174
|
+
|
|
175
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for the contributor workflow.
|