securevibe 0.1.13 → 0.1.14
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/README.md +7 -4
- package/dist/index.js +12 -0
- package/dist/update-check.js +12 -2
- package/dist/update-command.js +79 -0
- package/dist/version.js +1 -1
- package/package.json +71 -71
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ midnight). The `--staged` commit guard is never limited. See [`LICENSE`](LICENSE
|
|
|
31
31
|
| `securevibe pr-comment [path]` | Post/update a PR findings summary (used by the GitHub Actions workflow) |
|
|
32
32
|
| `securevibe deps [path]` | Audit dependencies for known CVEs against the local OSV database (SCA) |
|
|
33
33
|
| `securevibe db <update\|status>` | Manage the local OSV database — `update` is networked |
|
|
34
|
+
| `securevibe update` | Update securevibe itself to the latest published version (also networked) |
|
|
34
35
|
| `securevibe ready [path]` | Launch readiness scorecard: pass/fail gates + go/no-go verdict |
|
|
35
36
|
| `securevibe ai-audit [path]` | Focus on the AI-agent attack surface (doc 04) |
|
|
36
37
|
| `securevibe protect [path]` | Remediation-first view: the fix for every finding (doc 05) |
|
|
@@ -71,7 +72,8 @@ is sent to your provider. Needs the same key as `fix` and `explain`
|
|
|
71
72
|
- a **GitHub Actions workflow** (`.github/workflows/securevibe.yml`) that scans every PR and uploads
|
|
72
73
|
SARIF to GitHub code scanning, gates the build on deployment-readiness, and posts a PR comment
|
|
73
74
|
summarizing findings in the *changed* files only (updated in place on new commits, not reposted —
|
|
74
|
-
and the
|
|
75
|
+
and one of the few other commands (besides `db update` and `update`) that talks to the network,
|
|
76
|
+
and only to post a
|
|
75
77
|
findings summary already computed locally, never your source code);
|
|
76
78
|
- gitignores `.env` / backups and drops a minimal `securevibe.config.json`.
|
|
77
79
|
|
|
@@ -142,9 +144,10 @@ against a local copy of the [OSV](https://osv.dev) advisory database, and report
|
|
|
142
144
|
CVE still blocks deployment, and `securevibe fix` bumps the package to the lowest non vulnerable
|
|
143
145
|
version while preserving your range prefix (`^`, `~`, `==`, ...).
|
|
144
146
|
- **Offline first.** A bundled seed (`data/osv-seed.json`) ships with the CLI, so `deps` works with
|
|
145
|
-
no network. `db update`
|
|
146
|
-
|
|
147
|
-
and only a findings summary already computed locally — never your
|
|
147
|
+
no network. `db update` and `update` are the only commands that **download** anything (OSV
|
|
148
|
+
advisory dumps, or the CLI's own next version, respectively). `pr-comment` is the only command
|
|
149
|
+
that **uploads** anything, and only a findings summary already computed locally — never your
|
|
150
|
+
code or package list.
|
|
148
151
|
- **Honest framing.** A clean result reads "no known advisories as of `<db date>`", not "secure" —
|
|
149
152
|
it means nothing matched the local database on that date, which is not a proof of safety.
|
|
150
153
|
|
package/dist/index.js
CHANGED
|
@@ -353,6 +353,18 @@ program
|
|
|
353
353
|
process.stderr.write(` unknown db action: ${action} (use: update | status)\n`);
|
|
354
354
|
process.exit(64);
|
|
355
355
|
});
|
|
356
|
+
program
|
|
357
|
+
.command("update")
|
|
358
|
+
.description("Update securevibe to the latest published version (npm global installs only)")
|
|
359
|
+
.option("--no-color", "disable coloured output")
|
|
360
|
+
.action(async (opts) => {
|
|
361
|
+
if (opts.color === false)
|
|
362
|
+
process.env.NO_COLOR = "1";
|
|
363
|
+
const { runUpdateCommand } = await import("./update-command.js");
|
|
364
|
+
const code = await runUpdateCommand();
|
|
365
|
+
if (code !== 0)
|
|
366
|
+
process.exit(code);
|
|
367
|
+
});
|
|
356
368
|
program
|
|
357
369
|
.command("config")
|
|
358
370
|
.description("Manage local AI-fixer provider keys (Groq/Anthropic), stored in ~/.securevibe/config.json")
|
package/dist/update-check.js
CHANGED
|
@@ -28,6 +28,16 @@ export function isNewer(current, latest) {
|
|
|
28
28
|
}
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* True when the running script is npm's npx cache copy rather than a
|
|
33
|
+
* persistent global install — npx always resolves to the latest published
|
|
34
|
+
* version on every invocation, so there is nothing for `securevibe update`
|
|
35
|
+
* to do in that case. The npx cache directory is named `_npx` on both Unix
|
|
36
|
+
* (~/.npm/_npx/...) and Windows (%LocalAppData%\npm-cache\_npx\...).
|
|
37
|
+
*/
|
|
38
|
+
export function isRunningViaNpx(scriptPath = process.argv[1] ?? "") {
|
|
39
|
+
return scriptPath.split(/[\\/]/).includes("_npx");
|
|
40
|
+
}
|
|
31
41
|
async function readCache(file) {
|
|
32
42
|
try {
|
|
33
43
|
const raw = JSON.parse(await fs.readFile(file, "utf8"));
|
|
@@ -48,7 +58,7 @@ async function writeCache(file, state) {
|
|
|
48
58
|
/* best effort — a failed write must never break the command */
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
|
-
async function fetchLatest(fetchImpl) {
|
|
61
|
+
export async function fetchLatest(fetchImpl) {
|
|
52
62
|
const controller = new AbortController();
|
|
53
63
|
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
54
64
|
try {
|
|
@@ -96,6 +106,6 @@ export async function checkForUpdate(currentVersion, opts = {}) {
|
|
|
96
106
|
export function updateNotice(currentVersion, latestVersion) {
|
|
97
107
|
return [
|
|
98
108
|
` A new version of securevibe is available: ${latestVersion} (you have ${currentVersion}).`,
|
|
99
|
-
" Update: npm install -g securevibe",
|
|
109
|
+
" Update: securevibe update (or: npm install -g securevibe)",
|
|
100
110
|
].join("\n");
|
|
101
111
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `securevibe update` — an explicit, user-triggered self-update for npm
|
|
3
|
+
* global installs. Reuses the same registry check as the passive daily
|
|
4
|
+
* notice (update-check.ts) but always fetches fresh: "check right now" is
|
|
5
|
+
* the whole point of running this command instead of waiting for tomorrow's
|
|
6
|
+
* cached check.
|
|
7
|
+
*/
|
|
8
|
+
import { isNewer, isRunningViaNpx, fetchLatest as defaultFetchLatest } from "./update-check.js";
|
|
9
|
+
import { VERSION } from "./version.js";
|
|
10
|
+
async function defaultSpawnNpmInstall(write) {
|
|
11
|
+
const { spawn } = await import("node:child_process");
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
const child = spawn("npm", ["install", "-g", "securevibe@latest"], {
|
|
14
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
15
|
+
shell: process.platform === "win32",
|
|
16
|
+
});
|
|
17
|
+
let output = "";
|
|
18
|
+
const onChunk = (chunk) => {
|
|
19
|
+
const text = chunk.toString("utf8");
|
|
20
|
+
output += text;
|
|
21
|
+
write(text);
|
|
22
|
+
};
|
|
23
|
+
child.stdout?.on("data", onChunk);
|
|
24
|
+
child.stderr?.on("data", onChunk);
|
|
25
|
+
child.on("error", (err) => resolve({ code: 1, output: output + String(err?.message ?? err) }));
|
|
26
|
+
child.on("close", (code) => resolve({ code, output }));
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function defaultUpdateCommandDeps() {
|
|
30
|
+
return {
|
|
31
|
+
currentVersion: VERSION,
|
|
32
|
+
platform: process.platform,
|
|
33
|
+
isNpx: () => isRunningViaNpx(),
|
|
34
|
+
fetchLatest: defaultFetchLatest,
|
|
35
|
+
fetchImpl: fetch,
|
|
36
|
+
spawnNpmInstall: defaultSpawnNpmInstall,
|
|
37
|
+
write: (text) => process.stderr.write(text),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* True when npm's own output looks like a permission error and a sudo
|
|
42
|
+
* re-run would plausibly help. Never true on Windows, where elevation isn't
|
|
43
|
+
* a one-line fix.
|
|
44
|
+
*/
|
|
45
|
+
export function shouldShowSudoHint(output, platform = process.platform) {
|
|
46
|
+
return platform !== "win32" && /eacces|permission denied/i.test(output);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Runs the `securevibe update` flow. Returns the process exit code (0
|
|
50
|
+
* success, 1 failure) rather than calling process.exit itself, so callers
|
|
51
|
+
* (and tests) control process lifecycle. Never throws.
|
|
52
|
+
*/
|
|
53
|
+
export async function runUpdateCommand(deps = {}) {
|
|
54
|
+
const d = { ...defaultUpdateCommandDeps(), ...deps };
|
|
55
|
+
if (d.isNpx()) {
|
|
56
|
+
d.write(" You're running securevibe via npx, which always uses the latest published version — nothing to update.\n");
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
const latest = await d.fetchLatest(d.fetchImpl);
|
|
60
|
+
if (latest === null) {
|
|
61
|
+
d.write(" Could not reach the npm registry to check for updates. Check your network and try again.\n");
|
|
62
|
+
return 1;
|
|
63
|
+
}
|
|
64
|
+
if (!isNewer(d.currentVersion, latest)) {
|
|
65
|
+
d.write(` Already on the latest version (${d.currentVersion}).\n`);
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
d.write(` Updating securevibe ${d.currentVersion} -> ${latest}...\n`);
|
|
69
|
+
const result = await d.spawnNpmInstall(d.write);
|
|
70
|
+
if (result.code === 0) {
|
|
71
|
+
d.write(` Updated to ${latest}.\n`);
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
d.write(" Update failed.\n");
|
|
75
|
+
if (shouldShowSudoHint(result.output, d.platform)) {
|
|
76
|
+
d.write(" Try: sudo npm install -g securevibe@latest\n");
|
|
77
|
+
}
|
|
78
|
+
return 1;
|
|
79
|
+
}
|
package/dist/version.js
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
// Single source of truth for the CLI's own version, so it can't drift from
|
|
3
3
|
// what commander reports and what the update-check compares against.
|
|
4
4
|
// Kept in sync with the "version" field in package.json by hand at release time.
|
|
5
|
-
export const VERSION = "0.1.
|
|
5
|
+
export const VERSION = "0.1.14";
|
package/package.json
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "securevibe",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Autonomous AI security engineer for AI generated apps: scan, fix, verify, and gate every commit before you launch",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "SEE LICENSE IN LICENSE",
|
|
7
|
-
"author": "Benedict Patrick <benedictroger2006@gmail.com>",
|
|
8
|
-
"homepage": "https://github.com/Benedictpatrick/secure-vibe#readme",
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/Benedictpatrick/secure-vibe.git",
|
|
12
|
-
"directory": "packages/cli"
|
|
13
|
-
},
|
|
14
|
-
"bugs": {
|
|
15
|
-
"url": "https://github.com/Benedictpatrick/secure-vibe/issues"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"security",
|
|
19
|
-
"scanner",
|
|
20
|
-
"sast",
|
|
21
|
-
"ai security",
|
|
22
|
-
"prompt injection",
|
|
23
|
-
"vulnerability",
|
|
24
|
-
"secrets",
|
|
25
|
-
"sca",
|
|
26
|
-
"cve",
|
|
27
|
-
"launch readiness",
|
|
28
|
-
"vibe coding",
|
|
29
|
-
"cli"
|
|
30
|
-
],
|
|
31
|
-
"engines": {
|
|
32
|
-
"node": ">=20"
|
|
33
|
-
},
|
|
34
|
-
"bin": {
|
|
35
|
-
"securevibe": "./dist/index.js"
|
|
36
|
-
},
|
|
37
|
-
"files": [
|
|
38
|
-
"dist",
|
|
39
|
-
"data",
|
|
40
|
-
"LICENSE"
|
|
41
|
-
],
|
|
42
|
-
"scripts": {
|
|
43
|
-
"build": "tsc -p tsconfig.json",
|
|
44
|
-
"dev": "tsx src/index.ts",
|
|
45
|
-
"start": "node dist/index.js",
|
|
46
|
-
"test": "node run-tests.mjs"
|
|
47
|
-
},
|
|
48
|
-
"dependencies": {
|
|
49
|
-
"commander": "^12.1.0",
|
|
50
|
-
"diff": "^5.2.0",
|
|
51
|
-
"ink": "^6.8.0",
|
|
52
|
-
"ink-text-input": "^6.0.0",
|
|
53
|
-
"picocolors": "^1.1.1",
|
|
54
|
-
"react": "^19.2.7",
|
|
55
|
-
"tree-sitter-wasms": "^0.1.12",
|
|
56
|
-
"web-tree-sitter": "^0.25.10",
|
|
57
|
-
"yauzl": "^3.2.0"
|
|
58
|
-
},
|
|
59
|
-
"optionalDependencies": {
|
|
60
|
-
"@anthropic-ai/sdk": "^0.39.0"
|
|
61
|
-
},
|
|
62
|
-
"devDependencies": {
|
|
63
|
-
"@types/diff": "^5.2.0",
|
|
64
|
-
"@types/node": "^20.14.0",
|
|
65
|
-
"@types/react": "^19.2.17",
|
|
66
|
-
"@types/yauzl": "^2.10.3",
|
|
67
|
-
"ink-testing-library": "^4.0.0",
|
|
68
|
-
"tsx": "^4.19.0",
|
|
69
|
-
"typescript": "^5.6.0"
|
|
70
|
-
}
|
|
71
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "securevibe",
|
|
3
|
+
"version": "0.1.14",
|
|
4
|
+
"description": "Autonomous AI security engineer for AI generated apps: scan, fix, verify, and gate every commit before you launch",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
7
|
+
"author": "Benedict Patrick <benedictroger2006@gmail.com>",
|
|
8
|
+
"homepage": "https://github.com/Benedictpatrick/secure-vibe#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/Benedictpatrick/secure-vibe.git",
|
|
12
|
+
"directory": "packages/cli"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/Benedictpatrick/secure-vibe/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"security",
|
|
19
|
+
"scanner",
|
|
20
|
+
"sast",
|
|
21
|
+
"ai security",
|
|
22
|
+
"prompt injection",
|
|
23
|
+
"vulnerability",
|
|
24
|
+
"secrets",
|
|
25
|
+
"sca",
|
|
26
|
+
"cve",
|
|
27
|
+
"launch readiness",
|
|
28
|
+
"vibe coding",
|
|
29
|
+
"cli"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=20"
|
|
33
|
+
},
|
|
34
|
+
"bin": {
|
|
35
|
+
"securevibe": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"data",
|
|
40
|
+
"LICENSE"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc -p tsconfig.json",
|
|
44
|
+
"dev": "tsx src/index.ts",
|
|
45
|
+
"start": "node dist/index.js",
|
|
46
|
+
"test": "node run-tests.mjs"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"commander": "^12.1.0",
|
|
50
|
+
"diff": "^5.2.0",
|
|
51
|
+
"ink": "^6.8.0",
|
|
52
|
+
"ink-text-input": "^6.0.0",
|
|
53
|
+
"picocolors": "^1.1.1",
|
|
54
|
+
"react": "^19.2.7",
|
|
55
|
+
"tree-sitter-wasms": "^0.1.12",
|
|
56
|
+
"web-tree-sitter": "^0.25.10",
|
|
57
|
+
"yauzl": "^3.2.0"
|
|
58
|
+
},
|
|
59
|
+
"optionalDependencies": {
|
|
60
|
+
"@anthropic-ai/sdk": "^0.39.0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/diff": "^5.2.0",
|
|
64
|
+
"@types/node": "^20.14.0",
|
|
65
|
+
"@types/react": "^19.2.17",
|
|
66
|
+
"@types/yauzl": "^2.10.3",
|
|
67
|
+
"ink-testing-library": "^4.0.0",
|
|
68
|
+
"tsx": "^4.19.0",
|
|
69
|
+
"typescript": "^5.6.0"
|
|
70
|
+
}
|
|
71
|
+
}
|