codeproof 1.1.0 → 1.1.2
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 +130 -0
- package/commands/help.js +10 -14
- package/commands/run.js +17 -0
- package/commands/whoami.js +1 -0
- package/core/usageCheck.js +98 -0
- package/package.json +1 -1
package/Readme.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
CodeProof CLI
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
CodeProof is a security-focused CLI that scans your codebase, blocks risky commits, and reports findings to a server-backed dashboard.
|
|
5
|
+
|
|
6
|
+
Features
|
|
7
|
+
--------
|
|
8
|
+
- Run security scans on staged or full files.
|
|
9
|
+
- Enforce commit safety with configurable rules.
|
|
10
|
+
- Generate local reports and optionally sync them to the server.
|
|
11
|
+
- Usage tracking with monthly limits (free tier default 20 runs).
|
|
12
|
+
|
|
13
|
+
Installation
|
|
14
|
+
------------
|
|
15
|
+
Use npx (recommended):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx codeproof init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or install globally:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g codeproof
|
|
25
|
+
codeproof init
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Quick Start
|
|
29
|
+
-----------
|
|
30
|
+
1. Initialize in a Git repo:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
codeproof init
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. Run a scan:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
codeproof run
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
3. View reports in the dashboard (requires server):
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
codeproof report@dashboard
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Commands
|
|
49
|
+
--------
|
|
50
|
+
- init: Initialize CodeProof in the current Git repo.
|
|
51
|
+
- run: Run a security scan based on your config.
|
|
52
|
+
- report@dashboard: Send latest report and show dashboard link.
|
|
53
|
+
- move-secret: Move high-risk secrets to .env safely.
|
|
54
|
+
- ignore: Temporarily disable commit enforcement.
|
|
55
|
+
- apply: Re-enable commit enforcement.
|
|
56
|
+
- whoami: Show the local clientId.
|
|
57
|
+
- help: Show CLI help.
|
|
58
|
+
|
|
59
|
+
Configuration
|
|
60
|
+
-------------
|
|
61
|
+
CodeProof uses codeproof.config.json at the repo root.
|
|
62
|
+
|
|
63
|
+
Example:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"projectId": "<uuid>",
|
|
68
|
+
"projectType": "Node",
|
|
69
|
+
"scanMode": "staged",
|
|
70
|
+
"enforcement": "enabled",
|
|
71
|
+
"features": {
|
|
72
|
+
"reporting": true,
|
|
73
|
+
"integration": true,
|
|
74
|
+
"aiEscalation": false,
|
|
75
|
+
"secretRemediation": false
|
|
76
|
+
},
|
|
77
|
+
"integration": {
|
|
78
|
+
"enabled": true,
|
|
79
|
+
"endpointUrl": "http://127.0.0.1:4000/api/reports"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Usage Limits (Server-Enforced)
|
|
85
|
+
------------------------------
|
|
86
|
+
CodeProof enforces monthly run limits on the server.
|
|
87
|
+
|
|
88
|
+
- Default plan: free
|
|
89
|
+
- Default monthly limit: 20
|
|
90
|
+
- The CLI checks usage before each run
|
|
91
|
+
- If the server is unreachable, the CLI fails closed and stops the run
|
|
92
|
+
|
|
93
|
+
API Base Override
|
|
94
|
+
-----------------
|
|
95
|
+
By default the CLI uses http://127.0.0.1:4000/api for usage checks.
|
|
96
|
+
Override with:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
set CODEPROOF_API_BASE=http://your-server:4000/api
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
move-secret Command
|
|
103
|
+
-------------------
|
|
104
|
+
Safely moves high-risk secrets to .env with backups:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
codeproof move-secret --yes
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Server Setup (Required for Dashboard)
|
|
111
|
+
-------------------------------------
|
|
112
|
+
This CLI expects the CodeProof server to be running for:
|
|
113
|
+
|
|
114
|
+
- Usage enforcement
|
|
115
|
+
- Report ingestion
|
|
116
|
+
- Dashboard views
|
|
117
|
+
|
|
118
|
+
If you only want local scanning, disable integration in your config.
|
|
119
|
+
|
|
120
|
+
Dashboard
|
|
121
|
+
---------
|
|
122
|
+
The Next.js dashboard displays:
|
|
123
|
+
|
|
124
|
+
- Project and report metrics
|
|
125
|
+
- Analytics charts
|
|
126
|
+
- Usage and limit graphs
|
|
127
|
+
|
|
128
|
+
License
|
|
129
|
+
-------
|
|
130
|
+
Proprietary. All rights reserved.
|
package/commands/help.js
CHANGED
|
@@ -7,21 +7,17 @@ import { formatBlock } from "../ui/formatting.js";
|
|
|
7
7
|
const HELP_TEXT = `Usage: codeproof <command>
|
|
8
8
|
|
|
9
9
|
Commands:
|
|
10
|
-
init Initialize CodeProof in a Git repository
|
|
11
|
-
run Run CodeProof checks
|
|
12
|
-
report@dashboard Send latest report and show dashboard link
|
|
13
|
-
move-secret Move high-risk secrets to .env
|
|
14
|
-
ignore Temporarily disable commit enforcement
|
|
15
|
-
apply Re-enable commit enforcement
|
|
16
|
-
whoami Show the local CodeProof client ID
|
|
17
|
-
help Show this help menu
|
|
18
|
-
-h, --help Show this help menu
|
|
10
|
+
codeproof init Initialize CodeProof in a Git repository
|
|
11
|
+
codeproof run Run CodeProof checks
|
|
12
|
+
codeproof report@dashboard Send latest report and show dashboard link
|
|
13
|
+
codeproof move-secret Move high-risk secrets to .env
|
|
14
|
+
codeproof ignore Temporarily disable commit enforcement
|
|
15
|
+
codeproof apply Re-enable commit enforcement
|
|
16
|
+
codeproof whoami Show the local CodeProof client ID
|
|
17
|
+
codeproof help Show this help menu
|
|
18
|
+
codeproof -h, --help Show this help menu
|
|
19
|
+
|
|
19
20
|
|
|
20
|
-
Examples:
|
|
21
|
-
codeproof init
|
|
22
|
-
codeproof run
|
|
23
|
-
codeproof move-secret --yes
|
|
24
|
-
codeproof help
|
|
25
21
|
`;
|
|
26
22
|
|
|
27
23
|
/**
|
package/commands/run.js
CHANGED
|
@@ -13,6 +13,7 @@ import { sendReportToServer } from "../utils/apiClient.js";
|
|
|
13
13
|
import { resolveFeatureFlags, isVerbose } from "../core/featureFlags.js";
|
|
14
14
|
import { getClientId } from "../core/identity.js";
|
|
15
15
|
import { getEnforcementState } from "../core/enforcement.js";
|
|
16
|
+
import { checkUsageOrThrow } from "../core/usageCheck.js";
|
|
16
17
|
import {
|
|
17
18
|
reportFeatureDisabled,
|
|
18
19
|
warnExperimentalOnce,
|
|
@@ -67,6 +68,22 @@ export async function runCli({ args = [], cwd }) {
|
|
|
67
68
|
process.exit(1);
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
const clientId = getClientId();
|
|
72
|
+
try {
|
|
73
|
+
const usage = await checkUsageOrThrow({ clientId, config });
|
|
74
|
+
if (!usage.allowed) {
|
|
75
|
+
const limit = usage.limit ?? 20;
|
|
76
|
+
const used = usage.used ?? limit;
|
|
77
|
+
logError(`Free limit reached (${used}/${limit} runs/month).`);
|
|
78
|
+
logError("Upgrade to premium to continue.");
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
} catch (error) {
|
|
82
|
+
logError("Usage check failed. Unable to reach CodeProof server.");
|
|
83
|
+
logError(error?.message || "Usage enforcement failed.");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
70
87
|
const scanMode = String(config.scanMode).toLowerCase();
|
|
71
88
|
let targets = [];
|
|
72
89
|
|
package/commands/whoami.js
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import http from "http";
|
|
2
|
+
import https from "https";
|
|
3
|
+
|
|
4
|
+
const DEFAULT_API_BASE = "http://127.0.0.1:4000/api";
|
|
5
|
+
|
|
6
|
+
function resolveApiBase(config) {
|
|
7
|
+
const envBase = typeof process.env.CODEPROOF_API_BASE === "string"
|
|
8
|
+
? process.env.CODEPROOF_API_BASE.trim()
|
|
9
|
+
: "";
|
|
10
|
+
if (envBase) {
|
|
11
|
+
return envBase.replace(/\/+$/, "");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const endpoint = typeof config?.integration?.endpointUrl === "string"
|
|
15
|
+
? config.integration.endpointUrl.trim()
|
|
16
|
+
: "";
|
|
17
|
+
|
|
18
|
+
if (endpoint) {
|
|
19
|
+
try {
|
|
20
|
+
const url = new URL(endpoint);
|
|
21
|
+
return `${url.origin}/api`;
|
|
22
|
+
} catch {
|
|
23
|
+
return DEFAULT_API_BASE;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return DEFAULT_API_BASE;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function checkUsageOrThrow({ clientId, config }) {
|
|
31
|
+
const apiBase = resolveApiBase(config);
|
|
32
|
+
const endpoint = `${apiBase}/usage/check-and-increment`;
|
|
33
|
+
const payload = JSON.stringify({ clientId });
|
|
34
|
+
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
try {
|
|
37
|
+
const url = new URL(endpoint);
|
|
38
|
+
const transport = url.protocol === "http:" ? http : https;
|
|
39
|
+
const portNumber = url.port
|
|
40
|
+
? parseInt(url.port, 10)
|
|
41
|
+
: url.protocol === "http:"
|
|
42
|
+
? 80
|
|
43
|
+
: 443;
|
|
44
|
+
|
|
45
|
+
const request = transport.request(
|
|
46
|
+
{
|
|
47
|
+
method: "POST",
|
|
48
|
+
hostname: url.hostname,
|
|
49
|
+
port: portNumber,
|
|
50
|
+
path: `${url.pathname}${url.search}`,
|
|
51
|
+
headers: {
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
"Content-Length": Buffer.byteLength(payload),
|
|
54
|
+
},
|
|
55
|
+
timeout: 5000,
|
|
56
|
+
},
|
|
57
|
+
(res) => {
|
|
58
|
+
let body = "";
|
|
59
|
+
res.on("data", (chunk) => {
|
|
60
|
+
body += chunk;
|
|
61
|
+
});
|
|
62
|
+
res.on("end", () => {
|
|
63
|
+
if (res.statusCode !== 200) {
|
|
64
|
+
reject(new Error(`Usage check failed (${res.statusCode})`));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const data = body ? JSON.parse(body) : null;
|
|
70
|
+
if (!data || typeof data.allowed !== "boolean") {
|
|
71
|
+
reject(new Error("Invalid usage response"));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
resolve(data);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
reject(new Error("Invalid usage response"));
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
res.resume();
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
request.on("timeout", () => {
|
|
84
|
+
request.destroy();
|
|
85
|
+
reject(new Error("Usage check timeout"));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
request.on("error", (err) => {
|
|
89
|
+
reject(new Error(`Usage check error: ${err.message}`));
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
request.write(payload);
|
|
93
|
+
request.end();
|
|
94
|
+
} catch (error) {
|
|
95
|
+
reject(new Error("Usage check failed"));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|