@securecode-ai/mcp 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/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/api/client.d.ts +22 -0
- package/dist/api/client.js +141 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/types.d.ts +129 -0
- package/dist/api/types.js +3 -0
- package/dist/api/types.js.map +1 -0
- package/dist/approval/auditLog.d.ts +3 -0
- package/dist/approval/auditLog.js +67 -0
- package/dist/approval/auditLog.js.map +1 -0
- package/dist/approval/broker.d.ts +11 -0
- package/dist/approval/broker.js +252 -0
- package/dist/approval/broker.js.map +1 -0
- package/dist/approval/types.d.ts +26 -0
- package/dist/approval/types.js +58 -0
- package/dist/approval/types.js.map +1 -0
- package/dist/attack/agentLoop.d.ts +21 -0
- package/dist/attack/agentLoop.js +148 -0
- package/dist/attack/agentLoop.js.map +1 -0
- package/dist/attack/executor.d.ts +17 -0
- package/dist/attack/executor.js +162 -0
- package/dist/attack/executor.js.map +1 -0
- package/dist/attack/policy.d.ts +26 -0
- package/dist/attack/policy.js +73 -0
- package/dist/attack/policy.js.map +1 -0
- package/dist/attack/protocol.d.ts +64 -0
- package/dist/attack/protocol.js +3 -0
- package/dist/attack/protocol.js.map +1 -0
- package/dist/attack/report.d.ts +16 -0
- package/dist/attack/report.js +54 -0
- package/dist/attack/report.js.map +1 -0
- package/dist/auth/credentialStore.d.ts +20 -0
- package/dist/auth/credentialStore.js +148 -0
- package/dist/auth/credentialStore.js.map +1 -0
- package/dist/auth/keychain.d.ts +14 -0
- package/dist/auth/keychain.js +267 -0
- package/dist/auth/keychain.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +170 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +183 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +2 -0
- package/dist/mcp/tools.js +120 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/types.d.ts +26 -0
- package/dist/mcp/types.js +3 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/project-map/astHelpers.d.ts +89 -0
- package/dist/project-map/astHelpers.js +468 -0
- package/dist/project-map/astHelpers.js.map +1 -0
- package/dist/project-map/cache.d.ts +11 -0
- package/dist/project-map/cache.js +86 -0
- package/dist/project-map/cache.js.map +1 -0
- package/dist/project-map/confidence.d.ts +50 -0
- package/dist/project-map/confidence.js +87 -0
- package/dist/project-map/confidence.js.map +1 -0
- package/dist/project-map/crossFile.d.ts +73 -0
- package/dist/project-map/crossFile.js +33 -0
- package/dist/project-map/crossFile.js.map +1 -0
- package/dist/project-map/detectors.d.ts +83 -0
- package/dist/project-map/detectors.js +376 -0
- package/dist/project-map/detectors.js.map +1 -0
- package/dist/project-map/layer1.d.ts +74 -0
- package/dist/project-map/layer1.js +928 -0
- package/dist/project-map/layer1.js.map +1 -0
- package/dist/project-map/layer2.d.ts +30 -0
- package/dist/project-map/layer2.js +249 -0
- package/dist/project-map/layer2.js.map +1 -0
- package/dist/project-map/mapBuilder.d.ts +17 -0
- package/dist/project-map/mapBuilder.js +164 -0
- package/dist/project-map/mapBuilder.js.map +1 -0
- package/dist/project-map/parserLoader.d.ts +61 -0
- package/dist/project-map/parserLoader.js +175 -0
- package/dist/project-map/parserLoader.js.map +1 -0
- package/dist/project-map/schemas.d.ts +28 -0
- package/dist/project-map/schemas.js +131 -0
- package/dist/project-map/schemas.js.map +1 -0
- package/dist/project-map/types.d.ts +232 -0
- package/dist/project-map/types.js +61 -0
- package/dist/project-map/types.js.map +1 -0
- package/dist/tools/attack.d.ts +2 -0
- package/dist/tools/attack.js +80 -0
- package/dist/tools/attack.js.map +1 -0
- package/dist/tools/fix.d.ts +2 -0
- package/dist/tools/fix.js +60 -0
- package/dist/tools/fix.js.map +1 -0
- package/dist/tools/map.d.ts +2 -0
- package/dist/tools/map.js +46 -0
- package/dist/tools/map.js.map +1 -0
- package/dist/tools/scan.d.ts +2 -0
- package/dist/tools/scan.js +55 -0
- package/dist/tools/scan.js.map +1 -0
- package/dist/utils/files.d.ts +8 -0
- package/dist/utils/files.js +79 -0
- package/dist/utils/files.js.map +1 -0
- package/package.json +53 -0
- package/resources/tree-sitter/tree-sitter-javascript.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-python.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-tsx.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-typescript.wasm +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SecureCode
|
|
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,71 @@
|
|
|
1
|
+
# SecureCode MCP
|
|
2
|
+
|
|
3
|
+
Standalone MCP (Model Context Protocol) server for SecureCode AI. Provides security scanning tools to AI coding assistants — Cursor, Claude Code, Codex, Windsurf, and other compatible MCP clients — without requiring the VS Code extension.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @securecode-ai/mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Authenticate
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
securecode-mcp login
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or set the `SECURECODE_API_TOKEN` environment variable.
|
|
18
|
+
|
|
19
|
+
## MCP client configuration
|
|
20
|
+
|
|
21
|
+
### Cursor / Windsurf
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"mcpServers": {
|
|
26
|
+
"securecode": {
|
|
27
|
+
"command": "securecode-mcp",
|
|
28
|
+
"args": ["serve", "--workspace", "/path/to/your/project"]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Claude Code
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
claude mcp add securecode -s user -- securecode-mcp serve --workspace /path/to/your/project
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Tools
|
|
41
|
+
|
|
42
|
+
| Tool | Description | Approval |
|
|
43
|
+
|------|-------------|----------|
|
|
44
|
+
| `securecode.scan` | Scan code for vulnerabilities using the AI pipeline | No |
|
|
45
|
+
| `securecode.map` | Get the Project Map (endpoints, middleware, auth) | No |
|
|
46
|
+
| `securecode.fix` | Generate a patch for a specific finding | Yes |
|
|
47
|
+
| `securecode.attack` | Endpoint red-team testing (beta) | Yes |
|
|
48
|
+
|
|
49
|
+
## CLI
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
securecode-mcp serve [--workspace <path>] Start the MCP stdio server
|
|
53
|
+
securecode-mcp login [--api-url <url>] Store your API token
|
|
54
|
+
securecode-mcp status Show auth status
|
|
55
|
+
securecode-mcp logout Remove credentials
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Security
|
|
59
|
+
|
|
60
|
+
- No API token in MCP client configuration — credentials are stored in `~/.securecode/credentials.json` (mode 0600) or the `SECURECODE_API_TOKEN` env var.
|
|
61
|
+
- File reads are confined to the `--workspace` root.
|
|
62
|
+
- Fixes are returned for review and never auto-applied.
|
|
63
|
+
- No telemetry.
|
|
64
|
+
|
|
65
|
+
## Development
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install
|
|
69
|
+
npm run build
|
|
70
|
+
npm test
|
|
71
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare class ApiClientError extends Error {
|
|
2
|
+
readonly status: number;
|
|
3
|
+
readonly apiCode: string | undefined;
|
|
4
|
+
readonly remaining: number | undefined;
|
|
5
|
+
constructor(status: number, apiCode: string | undefined, message: string, remaining: number | undefined);
|
|
6
|
+
static isInsufficientCredits(err: unknown): boolean;
|
|
7
|
+
static isAuthFailure(err: unknown): boolean;
|
|
8
|
+
static isRateLimit(err: unknown): boolean;
|
|
9
|
+
static isServerUnavailable(err: unknown): boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ApiClientOptions {
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
token: string;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class ApiClient {
|
|
17
|
+
private readonly baseUrl;
|
|
18
|
+
private readonly token;
|
|
19
|
+
private readonly timeoutMs;
|
|
20
|
+
constructor(opts: ApiClientOptions);
|
|
21
|
+
postJson<T>(path: string, body: unknown): Promise<T>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ApiClient = exports.ApiClientError = void 0;
|
|
37
|
+
const http = __importStar(require("http"));
|
|
38
|
+
const https = __importStar(require("https"));
|
|
39
|
+
const DEFAULT_TIMEOUT_MS = 180_000;
|
|
40
|
+
const MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
|
|
41
|
+
class ApiClientError extends Error {
|
|
42
|
+
status;
|
|
43
|
+
apiCode;
|
|
44
|
+
remaining;
|
|
45
|
+
constructor(status, apiCode, message, remaining) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.status = status;
|
|
48
|
+
this.apiCode = apiCode;
|
|
49
|
+
this.remaining = remaining;
|
|
50
|
+
this.name = 'ApiClientError';
|
|
51
|
+
}
|
|
52
|
+
static isInsufficientCredits(err) {
|
|
53
|
+
return err instanceof ApiClientError && err.status === 402;
|
|
54
|
+
}
|
|
55
|
+
static isAuthFailure(err) {
|
|
56
|
+
return err instanceof ApiClientError && err.status === 401;
|
|
57
|
+
}
|
|
58
|
+
static isRateLimit(err) {
|
|
59
|
+
return err instanceof ApiClientError && err.status === 429;
|
|
60
|
+
}
|
|
61
|
+
static isServerUnavailable(err) {
|
|
62
|
+
return err instanceof ApiClientError && err.status === 503;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.ApiClientError = ApiClientError;
|
|
66
|
+
class ApiClient {
|
|
67
|
+
baseUrl;
|
|
68
|
+
token;
|
|
69
|
+
timeoutMs;
|
|
70
|
+
constructor(opts) {
|
|
71
|
+
this.baseUrl = opts.baseUrl.replace(/\/$/, '');
|
|
72
|
+
this.token = opts.token;
|
|
73
|
+
this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
74
|
+
}
|
|
75
|
+
async postJson(path, body) {
|
|
76
|
+
const url = `${this.baseUrl}${path}`;
|
|
77
|
+
const payload = JSON.stringify(body);
|
|
78
|
+
const parsed = new URL(url);
|
|
79
|
+
const lib = parsed.protocol === 'https:' ? https : http;
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
const req = lib.request({
|
|
82
|
+
hostname: parsed.hostname,
|
|
83
|
+
port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80),
|
|
84
|
+
path: parsed.pathname + parsed.search,
|
|
85
|
+
method: 'POST',
|
|
86
|
+
headers: {
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
89
|
+
Authorization: `Bearer ${this.token}`,
|
|
90
|
+
},
|
|
91
|
+
}, (res) => {
|
|
92
|
+
let raw = '';
|
|
93
|
+
let aborted = false;
|
|
94
|
+
res.on('data', (chunk) => {
|
|
95
|
+
if (raw.length + chunk.length > MAX_RESPONSE_BYTES) {
|
|
96
|
+
aborted = true;
|
|
97
|
+
req.destroy();
|
|
98
|
+
reject(new ApiClientError(502, undefined, 'Response too large', undefined));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
raw += chunk.toString('utf8');
|
|
102
|
+
});
|
|
103
|
+
res.on('end', () => {
|
|
104
|
+
if (aborted)
|
|
105
|
+
return;
|
|
106
|
+
let data;
|
|
107
|
+
try {
|
|
108
|
+
data = raw ? JSON.parse(raw) : {};
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
data = { raw };
|
|
112
|
+
}
|
|
113
|
+
const status = res.statusCode ?? 0;
|
|
114
|
+
if (status >= 200 && status < 300) {
|
|
115
|
+
resolve(data);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const apiErr = {
|
|
119
|
+
status,
|
|
120
|
+
code: data.code || data.error_code,
|
|
121
|
+
message: data.error || data.message || `HTTP ${status}`,
|
|
122
|
+
remaining: data.remaining,
|
|
123
|
+
};
|
|
124
|
+
reject(new ApiClientError(apiErr.status, apiErr.code, apiErr.message, apiErr.remaining));
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
req.on('error', (err) => {
|
|
129
|
+
reject(new ApiClientError(0, undefined, `Network error: ${err.message}`, undefined));
|
|
130
|
+
});
|
|
131
|
+
req.setTimeout(this.timeoutMs, () => {
|
|
132
|
+
req.destroy();
|
|
133
|
+
reject(new ApiClientError(0, undefined, `Request timed out after ${this.timeoutMs}ms`, undefined));
|
|
134
|
+
});
|
|
135
|
+
req.write(payload);
|
|
136
|
+
req.end();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
exports.ApiClient = ApiClient;
|
|
141
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAC7B,6CAA+B;AAG/B,MAAM,kBAAkB,GAAG,OAAO,CAAC;AACnC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,MAAa,cAAe,SAAQ,KAAK;IAEjB;IACA;IAEA;IAJpB,YACoB,MAAc,EACd,OAA2B,EAC3C,OAAe,EACC,SAA6B;QAE7C,KAAK,CAAC,OAAO,CAAC,CAAC;QALC,WAAM,GAAN,MAAM,CAAQ;QACd,YAAO,GAAP,OAAO,CAAoB;QAE3B,cAAS,GAAT,SAAS,CAAoB;QAG7C,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,qBAAqB,CAAC,GAAY;QACrC,OAAO,GAAG,YAAY,cAAc,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC;IAC/D,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,GAAY;QAC7B,OAAO,GAAG,YAAY,cAAc,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC;IAC/D,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,GAAY;QAC3B,OAAO,GAAG,YAAY,cAAc,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC;IAC/D,CAAC;IAED,MAAM,CAAC,mBAAmB,CAAC,GAAY;QACnC,OAAO,GAAG,YAAY,cAAc,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC;IAC/D,CAAC;CACJ;AA1BD,wCA0BC;AAQD,MAAa,SAAS;IACD,OAAO,CAAS;IAChB,KAAK,CAAS;IACd,SAAS,CAAS;IAEnC,YAAY,IAAsB;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,QAAQ,CAAI,IAAY,EAAE,IAAa;QACzC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAExD,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CACnB;gBACI,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,IAAI,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM;gBACrC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACL,cAAc,EAAE,kBAAkB;oBAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;oBAC5C,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;iBACxC;aACJ,EACD,CAAC,GAAG,EAAE,EAAE;gBACJ,IAAI,GAAG,GAAG,EAAE,CAAC;gBACb,IAAI,OAAO,GAAG,KAAK,CAAC;gBACpB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;oBAC7B,IAAI,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;wBACjD,OAAO,GAAG,IAAI,CAAC;wBACf,GAAG,CAAC,OAAO,EAAE,CAAC;wBACd,MAAM,CAAC,IAAI,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,SAAS,CAAC,CAAC,CAAC;wBAC5E,OAAO;oBACX,CAAC;oBACD,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAClC,CAAC,CAAC,CAAC;gBACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACf,IAAI,OAAO;wBAAE,OAAO;oBACpB,IAAI,IAAS,CAAC;oBACd,IAAI,CAAC;wBACD,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtC,CAAC;oBAAC,MAAM,CAAC;wBACL,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC;oBACnB,CAAC;oBACD,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC;oBACnC,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;wBAChC,OAAO,CAAC,IAAS,CAAC,CAAC;oBACvB,CAAC;yBAAM,CAAC;wBACJ,MAAM,MAAM,GAAa;4BACrB,MAAM;4BACN,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU;4BAClC,OAAO,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,MAAM,EAAE;4BACvD,SAAS,EAAE,IAAI,CAAC,SAAS;yBAC5B,CAAC;wBACF,MAAM,CAAC,IAAI,cAAc,CACrB,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,SAAS,CACnB,CAAC,CAAC;oBACP,CAAC;gBACL,CAAC,CAAC,CAAC;YACP,CAAC,CACJ,CAAC;YAEF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACpB,MAAM,CAAC,IAAI,cAAc,CAAC,CAAC,EAAE,SAAS,EAAE,kBAAkB,GAAG,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;YACzF,CAAC,CAAC,CAAC;YAEH,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;gBAChC,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,MAAM,CAAC,IAAI,cAAc,CAAC,CAAC,EAAE,SAAS,EAAE,2BAA2B,IAAI,CAAC,SAAS,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;YACvG,CAAC,CAAC,CAAC;YAEH,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC;CACJ;AApFD,8BAoFC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
export interface ScanRequest {
|
|
2
|
+
code: string;
|
|
3
|
+
language: string;
|
|
4
|
+
filePath?: string;
|
|
5
|
+
scanDepth?: 'auto' | 'deep';
|
|
6
|
+
workspaceHints?: {
|
|
7
|
+
frameworkHint?: string;
|
|
8
|
+
relatedFiles?: Array<{
|
|
9
|
+
path: string;
|
|
10
|
+
content: string;
|
|
11
|
+
role: string;
|
|
12
|
+
}>;
|
|
13
|
+
endpointContext?: unknown;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface ScanFinding {
|
|
17
|
+
check_id?: string;
|
|
18
|
+
type?: string;
|
|
19
|
+
path?: string;
|
|
20
|
+
start?: {
|
|
21
|
+
line: number;
|
|
22
|
+
col?: number;
|
|
23
|
+
};
|
|
24
|
+
end?: {
|
|
25
|
+
line: number;
|
|
26
|
+
col?: number;
|
|
27
|
+
};
|
|
28
|
+
message?: string;
|
|
29
|
+
severity?: string;
|
|
30
|
+
extra?: {
|
|
31
|
+
message?: string;
|
|
32
|
+
severity?: string;
|
|
33
|
+
lines?: string;
|
|
34
|
+
fix?: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface FinalFinding {
|
|
38
|
+
final_id: string;
|
|
39
|
+
type: string;
|
|
40
|
+
severity: string;
|
|
41
|
+
confidence: number;
|
|
42
|
+
location: {
|
|
43
|
+
line_start: number;
|
|
44
|
+
line_end: number;
|
|
45
|
+
};
|
|
46
|
+
evidence_snippet: string;
|
|
47
|
+
decision_basis: string;
|
|
48
|
+
why_real?: string;
|
|
49
|
+
fix_strategy?: string;
|
|
50
|
+
fix_snippet?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface ScanResponse {
|
|
53
|
+
scanType: 'basic' | 'advanced';
|
|
54
|
+
scanTypeMessage?: string | null;
|
|
55
|
+
scanId?: string;
|
|
56
|
+
findings?: ScanFinding[];
|
|
57
|
+
finalFindings?: FinalFinding[];
|
|
58
|
+
groupedFindings?: unknown;
|
|
59
|
+
scanSummary?: string;
|
|
60
|
+
remainingAIScans?: number;
|
|
61
|
+
aiScanLimit?: number | null;
|
|
62
|
+
plan?: string;
|
|
63
|
+
degraded?: boolean;
|
|
64
|
+
costs?: {
|
|
65
|
+
totalCostUsd: number;
|
|
66
|
+
stages: Array<{
|
|
67
|
+
stage: string;
|
|
68
|
+
provider: string;
|
|
69
|
+
model: string;
|
|
70
|
+
costUsd: number;
|
|
71
|
+
degraded: boolean;
|
|
72
|
+
fallbackFired: boolean;
|
|
73
|
+
}>;
|
|
74
|
+
};
|
|
75
|
+
scanCredits?: number;
|
|
76
|
+
attackerCredits?: number;
|
|
77
|
+
}
|
|
78
|
+
export interface FixRequest {
|
|
79
|
+
code: string;
|
|
80
|
+
language: string;
|
|
81
|
+
vulnerability: {
|
|
82
|
+
type: string;
|
|
83
|
+
line_start: number;
|
|
84
|
+
line_end: number;
|
|
85
|
+
evidence_snippet: string;
|
|
86
|
+
};
|
|
87
|
+
framework?: string;
|
|
88
|
+
}
|
|
89
|
+
export interface FixResponse {
|
|
90
|
+
fixed_code: string;
|
|
91
|
+
diff?: string;
|
|
92
|
+
fix_summary?: string;
|
|
93
|
+
security_notes?: string[];
|
|
94
|
+
why_secure?: string;
|
|
95
|
+
imports_needed?: string[];
|
|
96
|
+
confidence?: number;
|
|
97
|
+
}
|
|
98
|
+
export interface ApiError {
|
|
99
|
+
status: number;
|
|
100
|
+
code?: string;
|
|
101
|
+
message: string;
|
|
102
|
+
remaining?: number;
|
|
103
|
+
scanType?: string;
|
|
104
|
+
}
|
|
105
|
+
export interface EndpointContext {
|
|
106
|
+
method: string;
|
|
107
|
+
path: string;
|
|
108
|
+
mountedPath?: string;
|
|
109
|
+
handlerName: string;
|
|
110
|
+
sourceFile: string;
|
|
111
|
+
line: number;
|
|
112
|
+
middleware: unknown[];
|
|
113
|
+
params: unknown[];
|
|
114
|
+
authScheme: string;
|
|
115
|
+
dataLayer: string;
|
|
116
|
+
validatorLibrary: string;
|
|
117
|
+
callGraph: unknown[];
|
|
118
|
+
responseShape: string;
|
|
119
|
+
confidence: number;
|
|
120
|
+
runtimeConfirmed: boolean;
|
|
121
|
+
}
|
|
122
|
+
export interface ProjectMap {
|
|
123
|
+
endpoints: EndpointContext[];
|
|
124
|
+
files?: Record<string, {
|
|
125
|
+
endpoints?: EndpointContext[];
|
|
126
|
+
}>;
|
|
127
|
+
builtAt?: string;
|
|
128
|
+
version?: number;
|
|
129
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.appendAudit = appendAudit;
|
|
37
|
+
exports.readAudit = readAudit;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const os = __importStar(require("os"));
|
|
41
|
+
const AUDIT_DIR = path.join(os.homedir(), '.securecode');
|
|
42
|
+
const AUDIT_FILE = path.join(AUDIT_DIR, 'approval-audit.log');
|
|
43
|
+
function appendAudit(entry) {
|
|
44
|
+
try {
|
|
45
|
+
if (!fs.existsSync(AUDIT_DIR)) {
|
|
46
|
+
fs.mkdirSync(AUDIT_DIR, { recursive: true, mode: 0o700 });
|
|
47
|
+
}
|
|
48
|
+
const line = JSON.stringify(entry) + '\n';
|
|
49
|
+
fs.appendFileSync(AUDIT_FILE, line, { mode: 0o600 });
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// best effort — audit failure must not block the operation
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function readAudit(limit = 100) {
|
|
56
|
+
try {
|
|
57
|
+
if (!fs.existsSync(AUDIT_FILE))
|
|
58
|
+
return [];
|
|
59
|
+
const raw = fs.readFileSync(AUDIT_FILE, 'utf8');
|
|
60
|
+
const lines = raw.trim().split('\n').filter(Boolean);
|
|
61
|
+
return lines.slice(-limit).map((line) => JSON.parse(line));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=auditLog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditLog.js","sourceRoot":"","sources":["../../src/approval/auditLog.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,kCAUC;AAED,8BASC;AA7BD,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AAGzB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAE9D,SAAgB,WAAW,CAAC,KAAiB;IACzC,IAAI,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QAC1C,EAAE,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACL,2DAA2D;IAC/D,CAAC;AACL,CAAC;AAED,SAAgB,SAAS,CAAC,QAAgB,GAAG;IACzC,IAAI,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ApprovalResult } from './types';
|
|
2
|
+
export declare class ApprovalBroker {
|
|
3
|
+
private server;
|
|
4
|
+
private port;
|
|
5
|
+
private pending;
|
|
6
|
+
start(): Promise<number>;
|
|
7
|
+
stop(): Promise<void>;
|
|
8
|
+
getPort(): number;
|
|
9
|
+
requestApproval(tool: string, summary: string, operationParts: unknown[], timeoutMs?: number): Promise<ApprovalResult>;
|
|
10
|
+
private handle;
|
|
11
|
+
}
|