trusta 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 +73 -0
- package/dist/api.d.ts +54 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +47 -0
- package/dist/api.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +156 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/detect.d.ts +7 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +89 -0
- package/dist/detect.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +8 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +43 -0
- package/dist/output.js.map +1 -0
- package/dist/prompt.d.ts +5 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +23 -0
- package/dist/prompt.js.map +1 -0
- package/dist/scanner.d.ts +27 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +232 -0
- package/dist/scanner.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Trusta (trusta-dev)
|
|
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,73 @@
|
|
|
1
|
+
# trusta
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/trusta)
|
|
4
|
+
[](https://github.com/trusta-dev/trusta-cli/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
Generate your trust page in minutes.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx trusta init
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
1. Detects your project name, GitHub repo, and framework
|
|
16
|
+
2. Creates a Trusta workspace and project at [trusta.dev](https://trusta.dev)
|
|
17
|
+
3. Runs a local security scan across your codebase:
|
|
18
|
+
- Hardcoded secrets (API keys, tokens, credentials)
|
|
19
|
+
- Supabase RLS bypass vulnerabilities
|
|
20
|
+
- Exposed admin routes with client-side auth checks
|
|
21
|
+
- Unprotected API endpoints
|
|
22
|
+
4. Submits findings as evidence — they contribute to your public trust score
|
|
23
|
+
5. Links your GitHub repo so every push triggers an automatic re-scan
|
|
24
|
+
6. Outputs a ready-to-paste GitHub Actions snippet
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
- Node.js 18 or later
|
|
29
|
+
- A [Trusta](https://trusta.dev) account (free)
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx trusta init
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
You'll be prompted for:
|
|
38
|
+
1. Your API token — get it at [app.trusta.dev/app/settings/tokens](https://app.trusta.dev/app/settings/tokens)
|
|
39
|
+
2. Workspace name (your company or app name)
|
|
40
|
+
3. Project name
|
|
41
|
+
|
|
42
|
+
## Environment variables
|
|
43
|
+
|
|
44
|
+
| Variable | Description |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `TRUSTA_API_TOKEN` | Skip the token prompt in CI |
|
|
47
|
+
| `TRUSTA_API_URL` | Override API base URL (default: `https://api.trusta.dev`) |
|
|
48
|
+
| `TRUSTA_APP_URL` | Override app base URL (default: `https://app.trusta.dev`) |
|
|
49
|
+
|
|
50
|
+
## How the security score works
|
|
51
|
+
|
|
52
|
+
Each scan checks your codebase against four rules. Findings map directly to trust controls on your public trust page:
|
|
53
|
+
|
|
54
|
+
| Rule | Trust control |
|
|
55
|
+
|---|---|
|
|
56
|
+
| No hardcoded secrets | `security.no_hardcoded_secrets` |
|
|
57
|
+
| No RLS bypass | `security.rls_policies_enforced` |
|
|
58
|
+
| No exposed admin routes | `security.no_exposed_admin_routes` |
|
|
59
|
+
| No unprotected API endpoints | `security.no_unprotected_api_routes` |
|
|
60
|
+
|
|
61
|
+
Security contributes 25% of the overall trust score.
|
|
62
|
+
|
|
63
|
+
## Contributing
|
|
64
|
+
|
|
65
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) — adding new scanning rules is a great first contribution.
|
|
66
|
+
|
|
67
|
+
## Security
|
|
68
|
+
|
|
69
|
+
See [SECURITY.md](SECURITY.md) for how to report vulnerabilities responsibly.
|
|
70
|
+
|
|
71
|
+
## License
|
|
72
|
+
|
|
73
|
+
[MIT](LICENSE) © [Trusta](https://trusta.dev)
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export interface CliApiTransport {
|
|
2
|
+
readonly baseUrl: string;
|
|
3
|
+
readonly token: string;
|
|
4
|
+
}
|
|
5
|
+
export interface BootstrapResult {
|
|
6
|
+
organization: {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
};
|
|
10
|
+
project: {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
slug: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface CollectorResult {
|
|
17
|
+
collector: {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
secret: {
|
|
22
|
+
value: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export declare function bootstrapWorkspace(transport: CliApiTransport, input: {
|
|
26
|
+
workspaceName: string;
|
|
27
|
+
projectName: string;
|
|
28
|
+
}): Promise<BootstrapResult>;
|
|
29
|
+
export declare function createCollector(transport: CliApiTransport, projectId: string, name: string): Promise<CollectorResult>;
|
|
30
|
+
export interface IngestEvidenceInput {
|
|
31
|
+
readonly projectId: string;
|
|
32
|
+
readonly evidenceType: string;
|
|
33
|
+
readonly sourceType: string;
|
|
34
|
+
readonly sourceRef: string;
|
|
35
|
+
readonly observedAt: string;
|
|
36
|
+
readonly payload: unknown;
|
|
37
|
+
readonly metadataJson?: unknown;
|
|
38
|
+
}
|
|
39
|
+
export declare function ingestEvidence(collectorTransport: CliApiTransport, input: IngestEvidenceInput): Promise<{
|
|
40
|
+
evidenceRecordId: string;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function registerProjectRepo(transport: CliApiTransport, projectId: string, repoUrl: string): Promise<{
|
|
43
|
+
id: string;
|
|
44
|
+
projectId: string;
|
|
45
|
+
repoUrl: string;
|
|
46
|
+
createdAt: string;
|
|
47
|
+
}>;
|
|
48
|
+
export declare function getMe(transport: CliApiTransport): Promise<{
|
|
49
|
+
user: {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
};
|
|
53
|
+
}>;
|
|
54
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAmCD,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3B;AAED,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACpD,OAAO,CAAC,eAAe,CAAC,CAQ1B;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,eAAe,CAAC,CAK1B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAsB,cAAc,CAClC,kBAAkB,EAAE,eAAe,EACnC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC;IAAE,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC,CAOvC;AAED,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAEhF;AAED,wBAAsB,KAAK,CACzB,SAAS,EAAE,eAAe,GACzB,OAAO,CAAC;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAEjD"}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bootstrapWorkspace = bootstrapWorkspace;
|
|
4
|
+
exports.createCollector = createCollector;
|
|
5
|
+
exports.ingestEvidence = ingestEvidence;
|
|
6
|
+
exports.registerProjectRepo = registerProjectRepo;
|
|
7
|
+
exports.getMe = getMe;
|
|
8
|
+
async function apiRequest(transport, method, path, body) {
|
|
9
|
+
const init = {
|
|
10
|
+
method,
|
|
11
|
+
headers: {
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
Authorization: `Bearer ${transport.token}`,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
if (body !== undefined) {
|
|
17
|
+
init.body = JSON.stringify(body);
|
|
18
|
+
}
|
|
19
|
+
const response = await fetch(`${transport.baseUrl}${path}`, init);
|
|
20
|
+
const data = (await response.json());
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
const errorData = data;
|
|
23
|
+
const message = errorData.error?.message ?? `HTTP ${response.status}`;
|
|
24
|
+
throw new Error(message);
|
|
25
|
+
}
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
async function bootstrapWorkspace(transport, input) {
|
|
29
|
+
const result = await apiRequest(transport, 'POST', '/onboarding/bootstrap', input);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
async function createCollector(transport, projectId, name) {
|
|
33
|
+
return apiRequest(transport, 'POST', `/projects/${projectId}/collectors`, {
|
|
34
|
+
name,
|
|
35
|
+
allowedActions: ['evidence:write', 'heartbeat:write'],
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async function ingestEvidence(collectorTransport, input) {
|
|
39
|
+
return apiRequest(collectorTransport, 'POST', '/ingest/evidence', input);
|
|
40
|
+
}
|
|
41
|
+
async function registerProjectRepo(transport, projectId, repoUrl) {
|
|
42
|
+
return apiRequest(transport, 'POST', `/projects/${projectId}/repos`, { repoUrl });
|
|
43
|
+
}
|
|
44
|
+
async function getMe(transport) {
|
|
45
|
+
return apiRequest(transport, 'GET', '/me');
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":";;AAgDA,gDAWC;AAED,0CASC;AAYD,wCAUC;AAED,kDAMC;AAED,sBAIC;AAjGD,KAAK,UAAU,UAAU,CACvB,SAA0B,EAC1B,MAAgC,EAChC,IAAY,EACZ,IAAc;IAEd,MAAM,IAAI,GAAgB;QACxB,MAAM;QACN,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,SAAS,CAAC,KAAK,EAAE;SAC3C;KACF,CAAC;IACF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IAElE,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;IAErD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,IAAgB,CAAC;QACnC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAE,OAAO,IAAI,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,IAAS,CAAC;AACnB,CAAC;AAYM,KAAK,UAAU,kBAAkB,CACtC,SAA0B,EAC1B,KAAqD;IAErD,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,SAAS,EACT,MAAM,EACN,uBAAuB,EACvB,KAAK,CACN,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAEM,KAAK,UAAU,eAAe,CACnC,SAA0B,EAC1B,SAAiB,EACjB,IAAY;IAEZ,OAAO,UAAU,CAAkB,SAAS,EAAE,MAAM,EAAE,aAAa,SAAS,aAAa,EAAE;QACzF,IAAI;QACJ,cAAc,EAAE,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;KACtD,CAAC,CAAC;AACL,CAAC;AAYM,KAAK,UAAU,cAAc,CAClC,kBAAmC,EACnC,KAA0B;IAE1B,OAAO,UAAU,CACf,kBAAkB,EAClB,MAAM,EACN,kBAAkB,EAClB,KAAK,CACN,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,mBAAmB,CACvC,SAA0B,EAC1B,SAAiB,EACjB,OAAe;IAEf,OAAO,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,SAAS,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AACpF,CAAC;AAEM,KAAK,UAAU,KAAK,CACzB,SAA0B;IAE1B,OAAO,UAAU,CAAyC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACrF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAuBA,wBAAsB,IAAI,kBAiJzB"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.init = init;
|
|
4
|
+
const detect_1 = require("../detect");
|
|
5
|
+
const api_1 = require("../api");
|
|
6
|
+
const scanner_1 = require("../scanner");
|
|
7
|
+
const output_1 = require("../output");
|
|
8
|
+
const prompt_1 = require("../prompt");
|
|
9
|
+
const DEFAULT_API_URL = 'https://api.trusta.dev';
|
|
10
|
+
const DEFAULT_APP_URL = 'https://app.trusta.dev';
|
|
11
|
+
async function init() {
|
|
12
|
+
(0, output_1.printBanner)();
|
|
13
|
+
const detection = (0, detect_1.detectProject)();
|
|
14
|
+
const prompter = (0, prompt_1.createPrompter)();
|
|
15
|
+
try {
|
|
16
|
+
// Resolve API base URL
|
|
17
|
+
const apiUrl = (process.env['TRUSTA_API_URL'] ?? DEFAULT_API_URL).replace(/\/$/, '');
|
|
18
|
+
const appUrl = (process.env['TRUSTA_APP_URL'] ?? DEFAULT_APP_URL).replace(/\/$/, '');
|
|
19
|
+
// Resolve API token
|
|
20
|
+
let token = process.env['TRUSTA_API_TOKEN'] ?? '';
|
|
21
|
+
if (!token) {
|
|
22
|
+
(0, output_1.printStep)('Sign in at ' + appUrl + '/app/settings/tokens to get your API token.');
|
|
23
|
+
token = await prompter.ask('Paste your API token');
|
|
24
|
+
if (!token) {
|
|
25
|
+
throw new Error('API token is required. Set TRUSTA_API_TOKEN or enter it when prompted.');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const transport = { baseUrl: apiUrl, token };
|
|
29
|
+
// Workspace name
|
|
30
|
+
const defaultWorkspaceName = detection.projectName
|
|
31
|
+
? toTitleCase(detection.projectName)
|
|
32
|
+
: undefined;
|
|
33
|
+
(0, output_1.printStep)('Name your workspace (your company or app name).');
|
|
34
|
+
const workspaceName = await prompter.ask('Workspace name', defaultWorkspaceName);
|
|
35
|
+
if (!workspaceName) {
|
|
36
|
+
throw new Error('Workspace name is required.');
|
|
37
|
+
}
|
|
38
|
+
// Project name
|
|
39
|
+
const defaultProjectName = detection.projectName ?? undefined;
|
|
40
|
+
const projectName = await prompter.ask('First project name', defaultProjectName);
|
|
41
|
+
if (!projectName) {
|
|
42
|
+
throw new Error('Project name is required.');
|
|
43
|
+
}
|
|
44
|
+
(0, output_1.printDivider)();
|
|
45
|
+
// Bootstrap workspace + project
|
|
46
|
+
(0, output_1.printStep)('Creating workspace and project...');
|
|
47
|
+
const { organization, project } = await (0, api_1.bootstrapWorkspace)(transport, {
|
|
48
|
+
workspaceName,
|
|
49
|
+
projectName,
|
|
50
|
+
});
|
|
51
|
+
(0, output_1.printSuccess)(`Workspace "${organization.name}" created`);
|
|
52
|
+
(0, output_1.printSuccess)(`Project "${project.name}" created`);
|
|
53
|
+
// Create GitHub Actions collector
|
|
54
|
+
(0, output_1.printStep)('Creating collector credential for GitHub Actions...');
|
|
55
|
+
const collector = await (0, api_1.createCollector)(transport, project.id, 'github-actions');
|
|
56
|
+
(0, output_1.printSuccess)('Collector "github-actions" created');
|
|
57
|
+
// Register the GitHub repo URL so push webhooks resolve to this project
|
|
58
|
+
if (detection.githubRepoUrl) {
|
|
59
|
+
try {
|
|
60
|
+
await (0, api_1.registerProjectRepo)(transport, project.id, detection.githubRepoUrl);
|
|
61
|
+
(0, output_1.printSuccess)(`GitHub repo linked: ${detection.githubRepoUrl}`);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
(0, output_1.printWarning)('Could not link GitHub repo — you can add it later in the dashboard.');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
(0, output_1.printDivider)();
|
|
68
|
+
// Run local security scan and push findings as evidence
|
|
69
|
+
(0, output_1.printStep)('Scanning local files for security issues...');
|
|
70
|
+
const cwd = process.cwd();
|
|
71
|
+
try {
|
|
72
|
+
const scanResult = await (0, scanner_1.scanLocalDirectory)(cwd);
|
|
73
|
+
const { summary, findings } = scanResult;
|
|
74
|
+
// Use collector secret as bearer token for evidence ingest
|
|
75
|
+
const collectorTransport = {
|
|
76
|
+
baseUrl: apiUrl,
|
|
77
|
+
token: collector.secret.value,
|
|
78
|
+
};
|
|
79
|
+
await (0, api_1.ingestEvidence)(collectorTransport, {
|
|
80
|
+
projectId: project.id,
|
|
81
|
+
evidenceType: 'security_scan',
|
|
82
|
+
sourceType: 'local_fs',
|
|
83
|
+
sourceRef: cwd,
|
|
84
|
+
observedAt: new Date().toISOString(),
|
|
85
|
+
payload: { findings: findings.slice(0, 100) }, // cap payload size
|
|
86
|
+
metadataJson: summary,
|
|
87
|
+
});
|
|
88
|
+
// Print scan summary
|
|
89
|
+
if (summary.criticalCount > 0 || summary.highCount > 0) {
|
|
90
|
+
(0, output_1.printWarning)(`Security scan found ${summary.criticalCount} critical, ${summary.highCount} high, ` +
|
|
91
|
+
`${summary.mediumCount} medium issues across ${summary.filesScanned} files.`);
|
|
92
|
+
const topFindings = findings
|
|
93
|
+
.filter((f) => f.severity === 'critical' || f.severity === 'high')
|
|
94
|
+
.slice(0, 5);
|
|
95
|
+
for (const finding of topFindings) {
|
|
96
|
+
process.stdout.write(` [${finding.severity.toUpperCase()}] ${finding.filePath}:${finding.lineNumber} — ${finding.ruleId}\n`);
|
|
97
|
+
}
|
|
98
|
+
if (findings.length > 5) {
|
|
99
|
+
process.stdout.write(` ... and ${findings.length - 5} more. See dashboard for details.\n`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
(0, output_1.printSuccess)(`Security scan passed — ${summary.filesScanned} files scanned, score: ${summary.securityScore}/100`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
(0, output_1.printWarning)('Security scan could not complete — you can trigger one from the dashboard.');
|
|
108
|
+
}
|
|
109
|
+
// Output summary
|
|
110
|
+
const trustUrl = `${DEFAULT_APP_URL}/trust/${project.slug}`;
|
|
111
|
+
(0, output_1.printSuccess)('Setup complete!');
|
|
112
|
+
(0, output_1.printDivider)();
|
|
113
|
+
(0, output_1.printInfo)('Trust page:', trustUrl);
|
|
114
|
+
(0, output_1.printInfo)('Dashboard:', `${appUrl}/app`);
|
|
115
|
+
(0, output_1.printDivider)();
|
|
116
|
+
// GitHub Actions YAML snippet
|
|
117
|
+
process.stdout.write(' Add this to your GitHub Actions workflow:\n');
|
|
118
|
+
(0, output_1.printCode)(buildGitHubActionsYaml(collector.secret.value, apiUrl, project.id, detection.githubRepoUrl ?? undefined));
|
|
119
|
+
// Agent setup prompt
|
|
120
|
+
if (detection.framework) {
|
|
121
|
+
process.stdout.write(` Detected framework: ${detection.framework}\n\n`);
|
|
122
|
+
}
|
|
123
|
+
process.stdout.write(' To configure Trusta with an AI agent (Claude Code, Cursor, Windsurf):\n');
|
|
124
|
+
(0, output_1.printCode)(buildAgentPrompt(collector.secret.value, apiUrl, project.id));
|
|
125
|
+
process.stdout.write(' Save TRUSTA_COLLECTOR_SECRET as a GitHub Actions secret to keep it out of your repo.\n\n');
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
prompter.close();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function toTitleCase(name) {
|
|
132
|
+
return name
|
|
133
|
+
.replace(/[-_]/g, ' ')
|
|
134
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
135
|
+
}
|
|
136
|
+
function buildGitHubActionsYaml(secret, apiUrl, projectId, repoUrl) {
|
|
137
|
+
const repoLine = repoUrl ? ` repo_url: '${repoUrl}'\n` : '';
|
|
138
|
+
return `- name: Report to Trusta
|
|
139
|
+
uses: trusta/trusta-action@v1
|
|
140
|
+
with:
|
|
141
|
+
api_url: '${apiUrl}'
|
|
142
|
+
project_id: '${projectId}'
|
|
143
|
+
${repoLine} env:
|
|
144
|
+
TRUSTA_COLLECTOR_SECRET: \${{ secrets.TRUSTA_COLLECTOR_SECRET }}
|
|
145
|
+
# Secret value (save as GitHub Actions secret):
|
|
146
|
+
# ${secret}`;
|
|
147
|
+
}
|
|
148
|
+
function buildAgentPrompt(secret, apiUrl, projectId) {
|
|
149
|
+
return `Set up Trusta evidence collection for this project.
|
|
150
|
+
API URL: ${apiUrl}
|
|
151
|
+
Project ID: ${projectId}
|
|
152
|
+
Collector secret: ${secret}
|
|
153
|
+
Add TRUSTA_COLLECTOR_SECRET=${secret} to CI environment variables.
|
|
154
|
+
Then call POST ${apiUrl}/ingest/evidence with Bearer auth on each deploy.`;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
package/dist/detect.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface ProjectDetection {
|
|
2
|
+
readonly projectName: string | null;
|
|
3
|
+
readonly githubRepoUrl: string | null;
|
|
4
|
+
readonly framework: string | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function detectProject(cwd?: string): ProjectDetection;
|
|
7
|
+
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAsB,GAAG,gBAAgB,CAK3E"}
|
package/dist/detect.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectProject = detectProject;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_child_process_1 = require("node:child_process");
|
|
6
|
+
function detectProject(cwd = process.cwd()) {
|
|
7
|
+
const projectName = detectProjectName(cwd);
|
|
8
|
+
const githubRepoUrl = detectGitHubRepoUrl(cwd);
|
|
9
|
+
const framework = detectFramework(cwd);
|
|
10
|
+
return { projectName, githubRepoUrl, framework };
|
|
11
|
+
}
|
|
12
|
+
function detectProjectName(cwd) {
|
|
13
|
+
const pkgPath = `${cwd}/package.json`;
|
|
14
|
+
if ((0, node_fs_1.existsSync)(pkgPath)) {
|
|
15
|
+
try {
|
|
16
|
+
const pkg = JSON.parse((0, node_fs_1.readFileSync)(pkgPath, 'utf8'));
|
|
17
|
+
if (typeof pkg.name === 'string' && pkg.name.length > 0) {
|
|
18
|
+
return pkg.name.replace(/^@[^/]+\//, '');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// ignore
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return cwd.split('/').at(-1) ?? null;
|
|
26
|
+
}
|
|
27
|
+
function detectGitHubRepoUrl(cwd) {
|
|
28
|
+
try {
|
|
29
|
+
const remote = (0, node_child_process_1.execSync)('git remote get-url origin', {
|
|
30
|
+
cwd,
|
|
31
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
32
|
+
})
|
|
33
|
+
.toString()
|
|
34
|
+
.trim();
|
|
35
|
+
// SSH: git@github.com:owner/repo.git
|
|
36
|
+
const sshMatch = /^git@github\.com:([^/]+\/[^.]+)/.exec(remote);
|
|
37
|
+
if (sshMatch?.[1]) {
|
|
38
|
+
return `https://github.com/${sshMatch[1]}`;
|
|
39
|
+
}
|
|
40
|
+
// HTTPS: https://github.com/owner/repo.git
|
|
41
|
+
const httpsMatch = /^https:\/\/github\.com\/([^/]+\/[^.]+)/.exec(remote);
|
|
42
|
+
if (httpsMatch?.[1]) {
|
|
43
|
+
return `https://github.com/${httpsMatch[1]}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// not a git repo or no remote
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function detectFramework(cwd) {
|
|
52
|
+
const pkgPath = `${cwd}/package.json`;
|
|
53
|
+
if (!(0, node_fs_1.existsSync)(pkgPath))
|
|
54
|
+
return null;
|
|
55
|
+
try {
|
|
56
|
+
const pkg = JSON.parse((0, node_fs_1.readFileSync)(pkgPath, 'utf8'));
|
|
57
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
58
|
+
if ('next' in deps)
|
|
59
|
+
return 'Next.js';
|
|
60
|
+
if ('nuxt' in deps)
|
|
61
|
+
return 'Nuxt';
|
|
62
|
+
if ('remix' in deps || '@remix-run/node' in deps)
|
|
63
|
+
return 'Remix';
|
|
64
|
+
if ('astro' in deps)
|
|
65
|
+
return 'Astro';
|
|
66
|
+
if ('svelte' in deps)
|
|
67
|
+
return 'SvelteKit';
|
|
68
|
+
if ('react' in deps)
|
|
69
|
+
return 'React';
|
|
70
|
+
if ('vue' in deps)
|
|
71
|
+
return 'Vue';
|
|
72
|
+
if ('express' in deps)
|
|
73
|
+
return 'Express';
|
|
74
|
+
if ('fastify' in deps)
|
|
75
|
+
return 'Fastify';
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// ignore
|
|
79
|
+
}
|
|
80
|
+
if ((0, node_fs_1.existsSync)(`${cwd}/requirements.txt`) || (0, node_fs_1.existsSync)(`${cwd}/pyproject.toml`)) {
|
|
81
|
+
return 'Python';
|
|
82
|
+
}
|
|
83
|
+
if ((0, node_fs_1.existsSync)(`${cwd}/go.mod`))
|
|
84
|
+
return 'Go';
|
|
85
|
+
if ((0, node_fs_1.existsSync)(`${cwd}/Cargo.toml`))
|
|
86
|
+
return 'Rust';
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const init_1 = require("./commands/init");
|
|
5
|
+
const [, , command = 'init'] = process.argv;
|
|
6
|
+
if (command === 'init') {
|
|
7
|
+
(0, init_1.init)().catch((error) => {
|
|
8
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
9
|
+
process.stderr.write(`\nError: ${message}\n`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
process.stderr.write(`Unknown command: ${command}\nUsage: npx trusta init\n`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,0CAAuC;AAEvC,MAAM,CAAC,EAAE,AAAD,EAAG,OAAO,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;AAE5C,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;IACvB,IAAA,WAAI,GAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,OAAO,4BAA4B,CAAC,CAAC;IAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function printBanner(): void;
|
|
2
|
+
export declare function printStep(step: string): void;
|
|
3
|
+
export declare function printSuccess(message: string): void;
|
|
4
|
+
export declare function printWarning(message: string): void;
|
|
5
|
+
export declare function printInfo(label: string, value: string): void;
|
|
6
|
+
export declare function printCode(code: string): void;
|
|
7
|
+
export declare function printDivider(): void;
|
|
8
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAQA,wBAAgB,WAAW,SAE1B;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,QAErC;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,QAE3C;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,QAE3C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAErD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,QAOrC;AAED,wBAAgB,YAAY,SAE3B"}
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.printBanner = printBanner;
|
|
4
|
+
exports.printStep = printStep;
|
|
5
|
+
exports.printSuccess = printSuccess;
|
|
6
|
+
exports.printWarning = printWarning;
|
|
7
|
+
exports.printInfo = printInfo;
|
|
8
|
+
exports.printCode = printCode;
|
|
9
|
+
exports.printDivider = printDivider;
|
|
10
|
+
const RESET = '\x1b[0m';
|
|
11
|
+
const BOLD = '\x1b[1m';
|
|
12
|
+
const DIM = '\x1b[2m';
|
|
13
|
+
const GREEN = '\x1b[32m';
|
|
14
|
+
const CYAN = '\x1b[36m';
|
|
15
|
+
const YELLOW = '\x1b[33m';
|
|
16
|
+
const BLUE = '\x1b[34m';
|
|
17
|
+
function printBanner() {
|
|
18
|
+
process.stdout.write(`\n${BOLD}${CYAN} trusta${RESET} — generate your trust page in minutes\n\n`);
|
|
19
|
+
}
|
|
20
|
+
function printStep(step) {
|
|
21
|
+
process.stdout.write(`${DIM}→${RESET} ${step}\n`);
|
|
22
|
+
}
|
|
23
|
+
function printSuccess(message) {
|
|
24
|
+
process.stdout.write(`${GREEN}✓${RESET} ${message}\n`);
|
|
25
|
+
}
|
|
26
|
+
function printWarning(message) {
|
|
27
|
+
process.stdout.write(`${YELLOW}⚠${RESET} ${message}\n`);
|
|
28
|
+
}
|
|
29
|
+
function printInfo(label, value) {
|
|
30
|
+
process.stdout.write(` ${DIM}${label}${RESET} ${BOLD}${value}${RESET}\n`);
|
|
31
|
+
}
|
|
32
|
+
function printCode(code) {
|
|
33
|
+
const lines = code.split('\n');
|
|
34
|
+
process.stdout.write(`\n${DIM}${'─'.repeat(60)}${RESET}\n`);
|
|
35
|
+
for (const line of lines) {
|
|
36
|
+
process.stdout.write(` ${BLUE}${line}${RESET}\n`);
|
|
37
|
+
}
|
|
38
|
+
process.stdout.write(`${DIM}${'─'.repeat(60)}${RESET}\n\n`);
|
|
39
|
+
}
|
|
40
|
+
function printDivider() {
|
|
41
|
+
process.stdout.write(`\n${DIM}${'─'.repeat(60)}${RESET}\n\n`);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":";;AAQA,kCAEC;AAED,8BAEC;AAED,oCAEC;AAED,oCAEC;AAED,8BAEC;AAED,8BAOC;AAED,oCAEC;AAvCD,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,IAAI,GAAG,UAAU,CAAC;AACxB,MAAM,MAAM,GAAG,UAAU,CAAC;AAC1B,MAAM,IAAI,GAAG,UAAU,CAAC;AAExB,SAAgB,WAAW;IACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,IAAI,WAAW,KAAK,6CAA6C,CAAC,CAAC;AACtG,CAAC;AAED,SAAgB,SAAS,CAAC,IAAY;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,YAAY,CAAC,OAAe;IAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,KAAK,IAAI,OAAO,IAAI,CAAC,CAAC;AACzD,CAAC;AAED,SAAgB,YAAY,CAAC,OAAe;IAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED,SAAgB,SAAS,CAAC,KAAa,EAAE,KAAa;IACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED,SAAgB,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;IAC5D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;AAC9D,CAAC;AAED,SAAgB,YAAY;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;AAChE,CAAC"}
|
package/dist/prompt.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc;oBAMC,MAAM,iBAAiB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;;EAc7E"}
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createPrompter = createPrompter;
|
|
4
|
+
const node_readline_1 = require("node:readline");
|
|
5
|
+
function createPrompter() {
|
|
6
|
+
const rl = (0, node_readline_1.createInterface)({
|
|
7
|
+
input: process.stdin,
|
|
8
|
+
output: process.stdout,
|
|
9
|
+
});
|
|
10
|
+
async function ask(question, defaultValue) {
|
|
11
|
+
const suffix = defaultValue ? ` [${defaultValue}]` : '';
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
rl.question(` ${question}${suffix}: `, (answer) => {
|
|
14
|
+
resolve(answer.trim() || defaultValue || '');
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function close() {
|
|
19
|
+
rl.close();
|
|
20
|
+
}
|
|
21
|
+
return { ask, close };
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":";;AAEA,wCAoBC;AAtBD,iDAAgD;AAEhD,SAAgB,cAAc;IAC5B,MAAM,EAAE,GAAG,IAAA,+BAAe,EAAC;QACzB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,KAAK,UAAU,GAAG,CAAC,QAAgB,EAAE,YAAqB;QACxD,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,EAAE,CAAC,QAAQ,CAAC,KAAK,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE;gBACjD,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,YAAY,IAAI,EAAE,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,KAAK;QACZ,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type SecurityFindingSeverity = 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
2
|
+
export interface SecurityFinding {
|
|
3
|
+
readonly findingId: string;
|
|
4
|
+
readonly ruleId: string;
|
|
5
|
+
readonly severity: SecurityFindingSeverity;
|
|
6
|
+
readonly filePath: string;
|
|
7
|
+
readonly lineNumber: number;
|
|
8
|
+
readonly snippet: string;
|
|
9
|
+
readonly fix: string;
|
|
10
|
+
}
|
|
11
|
+
export interface LocalScanSummary {
|
|
12
|
+
readonly criticalCount: number;
|
|
13
|
+
readonly highCount: number;
|
|
14
|
+
readonly mediumCount: number;
|
|
15
|
+
readonly lowCount: number;
|
|
16
|
+
readonly rlsBypassCount: number;
|
|
17
|
+
readonly apiAuthCount: number;
|
|
18
|
+
readonly securityScore: number;
|
|
19
|
+
readonly filesScanned: number;
|
|
20
|
+
}
|
|
21
|
+
export interface LocalScanResult {
|
|
22
|
+
readonly findings: SecurityFinding[];
|
|
23
|
+
readonly summary: LocalScanSummary;
|
|
24
|
+
}
|
|
25
|
+
/** Scans local source files in `dir` and returns findings + summary. No network I/O. */
|
|
26
|
+
export declare function scanLocalDirectory(dir: string): Promise<LocalScanResult>;
|
|
27
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;CACpC;AAwND,wFAAwF;AACxF,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA8C9E"}
|
package/dist/scanner.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanLocalDirectory = scanLocalDirectory;
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
// --- Scanning rules (mirrors packages/domain — pure, no I/O) ---
|
|
7
|
+
const SECRET_PATTERNS = [
|
|
8
|
+
{
|
|
9
|
+
ruleId: 'hardcoded_stripe_secret_key',
|
|
10
|
+
pattern: /\bsk_(live|test)_[a-zA-Z0-9]{24,}\b/g,
|
|
11
|
+
severity: 'critical',
|
|
12
|
+
fix: 'Move this Stripe secret key to an environment variable (e.g. process.env.STRIPE_SECRET_KEY) and add it to your .env file. Never commit secret keys to source control.',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
ruleId: 'hardcoded_supabase_service_role_key',
|
|
16
|
+
pattern: /\beyJ[a-zA-Z0-9+/]{50,}={0,2}\b/g,
|
|
17
|
+
severity: 'critical',
|
|
18
|
+
fix: 'Move this Supabase service role key to a server-only environment variable. Never use the service role key in client-side code — it bypasses all Row Level Security policies.',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
ruleId: 'hardcoded_openai_api_key',
|
|
22
|
+
pattern: /\bsk-(?:proj-)?[a-zA-Z0-9]{32,}\b/g,
|
|
23
|
+
severity: 'critical',
|
|
24
|
+
fix: 'Move this OpenAI API key to an environment variable (e.g. process.env.OPENAI_API_KEY). Exposed API keys can result in unauthorized charges.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
ruleId: 'hardcoded_anthropic_api_key',
|
|
28
|
+
pattern: /\bsk-ant-[a-zA-Z0-9_-]{32,}\b/g,
|
|
29
|
+
severity: 'critical',
|
|
30
|
+
fix: 'Move this Anthropic API key to an environment variable (e.g. process.env.ANTHROPIC_API_KEY). Exposed API keys can result in unauthorized charges.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
ruleId: 'hardcoded_aws_secret_access_key',
|
|
34
|
+
pattern: /(?:AWS_SECRET_ACCESS_KEY|aws_secret_access_key)\s*[=:]\s*["']?([a-zA-Z0-9/+]{40})["']?/g,
|
|
35
|
+
severity: 'critical',
|
|
36
|
+
fix: 'Remove this AWS secret access key from source code. Use IAM roles, environment variables, or AWS Secrets Manager instead.',
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
const CLIENT_SIDE_PATH_PATTERNS = [
|
|
40
|
+
/^(src\/)?components\//,
|
|
41
|
+
/^(src\/)?pages\//,
|
|
42
|
+
/^(src\/)?app\//,
|
|
43
|
+
/^(src\/)?hooks\//,
|
|
44
|
+
/^(src\/)?lib\//,
|
|
45
|
+
/\.(tsx|jsx)$/,
|
|
46
|
+
];
|
|
47
|
+
const SERVER_SIDE_PATH_EXCLUSIONS = [
|
|
48
|
+
/route\.(ts|js)$/,
|
|
49
|
+
/server\.(ts|js)$/,
|
|
50
|
+
/api\//,
|
|
51
|
+
/actions\.(ts|js)$/,
|
|
52
|
+
/middleware\.(ts|js)$/,
|
|
53
|
+
];
|
|
54
|
+
function isClientSidePath(filePath) {
|
|
55
|
+
const isClientLike = CLIENT_SIDE_PATH_PATTERNS.some((p) => p.test(filePath));
|
|
56
|
+
const isServerExcluded = SERVER_SIDE_PATH_EXCLUSIONS.some((p) => p.test(filePath));
|
|
57
|
+
return isClientLike && !isServerExcluded;
|
|
58
|
+
}
|
|
59
|
+
function scanForHardcodedSecrets(fileContent, filePath) {
|
|
60
|
+
const findings = [];
|
|
61
|
+
const lines = fileContent.split('\n');
|
|
62
|
+
for (const rule of SECRET_PATTERNS) {
|
|
63
|
+
rule.pattern.lastIndex = 0;
|
|
64
|
+
let match;
|
|
65
|
+
while ((match = rule.pattern.exec(fileContent)) !== null) {
|
|
66
|
+
const before = fileContent.slice(0, match.index);
|
|
67
|
+
const lineNumber = before.split('\n').length;
|
|
68
|
+
const line = lines[lineNumber - 1] ?? '';
|
|
69
|
+
const snippet = line.trim().slice(0, 120);
|
|
70
|
+
findings.push({
|
|
71
|
+
findingId: `${rule.ruleId}:${filePath}:${lineNumber}`,
|
|
72
|
+
ruleId: rule.ruleId,
|
|
73
|
+
severity: rule.severity,
|
|
74
|
+
filePath,
|
|
75
|
+
lineNumber,
|
|
76
|
+
snippet,
|
|
77
|
+
fix: rule.fix,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
rule.pattern.lastIndex = 0;
|
|
81
|
+
}
|
|
82
|
+
return findings;
|
|
83
|
+
}
|
|
84
|
+
function scanForRlsBypassVulnerabilities(fileContent, filePath) {
|
|
85
|
+
if (!isClientSidePath(filePath))
|
|
86
|
+
return [];
|
|
87
|
+
const findings = [];
|
|
88
|
+
const lines = fileContent.split('\n');
|
|
89
|
+
const serviceRolePattern = /createClient\s*\([^)]*(?:SERVICE_ROLE|service_role|serviceRole)[^)]*\)/g;
|
|
90
|
+
let match;
|
|
91
|
+
while ((match = serviceRolePattern.exec(fileContent)) !== null) {
|
|
92
|
+
const before = fileContent.slice(0, match.index);
|
|
93
|
+
const lineNumber = before.split('\n').length;
|
|
94
|
+
const snippet = (lines[lineNumber - 1] ?? '').trim().slice(0, 120);
|
|
95
|
+
findings.push({
|
|
96
|
+
findingId: `rls_bypass_client_service_role:${filePath}:${lineNumber}`,
|
|
97
|
+
ruleId: 'rls_bypass_client_service_role',
|
|
98
|
+
severity: 'critical',
|
|
99
|
+
filePath,
|
|
100
|
+
lineNumber,
|
|
101
|
+
snippet,
|
|
102
|
+
fix: 'Never use the Supabase service role key in client-side code. It bypasses all Row Level Security policies and exposes all your data. Use the anon key for client code and keep the service role key server-side only.',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return findings;
|
|
106
|
+
}
|
|
107
|
+
function scanForExposedAdminRoutes(fileContent, filePath) {
|
|
108
|
+
if (!isClientSidePath(filePath))
|
|
109
|
+
return [];
|
|
110
|
+
const findings = [];
|
|
111
|
+
const lines = fileContent.split('\n');
|
|
112
|
+
const localStorageAuthPattern = /localStorage\.getItem\s*\(\s*["'](?:role|isAdmin|admin|is_admin|userRole|user_role)["']\s*\)/g;
|
|
113
|
+
let match;
|
|
114
|
+
while ((match = localStorageAuthPattern.exec(fileContent)) !== null) {
|
|
115
|
+
const before = fileContent.slice(0, match.index);
|
|
116
|
+
const lineNumber = before.split('\n').length;
|
|
117
|
+
const snippet = (lines[lineNumber - 1] ?? '').trim().slice(0, 120);
|
|
118
|
+
findings.push({
|
|
119
|
+
findingId: `exposed_admin_route_localstorage:${filePath}:${lineNumber}`,
|
|
120
|
+
ruleId: 'exposed_admin_route_localstorage',
|
|
121
|
+
severity: 'high',
|
|
122
|
+
filePath,
|
|
123
|
+
lineNumber,
|
|
124
|
+
snippet,
|
|
125
|
+
fix: 'Do not use localStorage for admin access control. localStorage can be modified by any user in their browser. Implement server-side role checks using your auth provider (Supabase RLS, session middleware, etc.).',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return findings;
|
|
129
|
+
}
|
|
130
|
+
function scanForUnprotectedApiEndpoints(fileContent, filePath) {
|
|
131
|
+
if (!/(route\.(ts|js)|api\/|handler\.(ts|js))/.test(filePath))
|
|
132
|
+
return [];
|
|
133
|
+
const findings = [];
|
|
134
|
+
const lines = fileContent.split('\n');
|
|
135
|
+
const firstLines = lines.slice(0, 30).join('\n');
|
|
136
|
+
const hasAuthCheck = /\b(?:getServerSession|auth\(\)|verifyJwt|authenticate|requireAuth|withAuth|getSession|supabase\.auth|createServerClient)\b/.test(firstLines);
|
|
137
|
+
const exportedHandlerPattern = /export\s+(?:async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE|handler)\b/g;
|
|
138
|
+
let match;
|
|
139
|
+
while ((match = exportedHandlerPattern.exec(fileContent)) !== null) {
|
|
140
|
+
if (!hasAuthCheck) {
|
|
141
|
+
const before = fileContent.slice(0, match.index);
|
|
142
|
+
const lineNumber = before.split('\n').length;
|
|
143
|
+
const snippet = (lines[lineNumber - 1] ?? '').trim().slice(0, 120);
|
|
144
|
+
findings.push({
|
|
145
|
+
findingId: `unprotected_api_endpoint:${filePath}:${lineNumber}`,
|
|
146
|
+
ruleId: 'unprotected_api_endpoint',
|
|
147
|
+
severity: 'high',
|
|
148
|
+
filePath,
|
|
149
|
+
lineNumber,
|
|
150
|
+
snippet,
|
|
151
|
+
fix: 'Add authentication to this API route. Verify the user session at the start of the handler before processing any data.',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return findings;
|
|
156
|
+
}
|
|
157
|
+
function computeSecurityScore(findings) {
|
|
158
|
+
const weights = {
|
|
159
|
+
critical: 25,
|
|
160
|
+
high: 10,
|
|
161
|
+
medium: 3,
|
|
162
|
+
low: 1,
|
|
163
|
+
info: 0,
|
|
164
|
+
};
|
|
165
|
+
const penalty = findings.reduce((acc, f) => acc + (weights[f.severity] ?? 0), 0);
|
|
166
|
+
return Math.max(0, Math.min(100, 100 - penalty));
|
|
167
|
+
}
|
|
168
|
+
// --- Local directory walker ---
|
|
169
|
+
const SOURCE_EXTENSIONS = /\.(ts|tsx|js|jsx|mjs|cjs|py|rb|go|java|php|cs)$/;
|
|
170
|
+
const EXCLUDED_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', 'out', '.turbo', 'coverage']);
|
|
171
|
+
async function walkDir(dir, root) {
|
|
172
|
+
const entries = await (0, promises_1.readdir)(dir, { withFileTypes: true });
|
|
173
|
+
const files = [];
|
|
174
|
+
for (const entry of entries) {
|
|
175
|
+
if (entry.name.startsWith('.') && entry.isDirectory())
|
|
176
|
+
continue;
|
|
177
|
+
if (entry.isDirectory() && EXCLUDED_DIRS.has(entry.name))
|
|
178
|
+
continue;
|
|
179
|
+
const fullPath = (0, node_path_1.join)(dir, entry.name);
|
|
180
|
+
if (entry.isDirectory()) {
|
|
181
|
+
const nested = await walkDir(fullPath, root);
|
|
182
|
+
files.push(...nested);
|
|
183
|
+
}
|
|
184
|
+
else if (entry.isFile() && SOURCE_EXTENSIONS.test(entry.name)) {
|
|
185
|
+
files.push(fullPath);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return files;
|
|
189
|
+
}
|
|
190
|
+
/** Scans local source files in `dir` and returns findings + summary. No network I/O. */
|
|
191
|
+
async function scanLocalDirectory(dir) {
|
|
192
|
+
const allFiles = await walkDir(dir, dir);
|
|
193
|
+
const findings = [];
|
|
194
|
+
await Promise.all(allFiles.map(async (absolutePath) => {
|
|
195
|
+
const relPath = (0, node_path_1.relative)(dir, absolutePath).replace(/\\/g, '/');
|
|
196
|
+
let content;
|
|
197
|
+
try {
|
|
198
|
+
content = await (0, promises_1.readFile)(absolutePath, 'utf8');
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const fileFindings = [
|
|
204
|
+
...scanForHardcodedSecrets(content, relPath),
|
|
205
|
+
...scanForRlsBypassVulnerabilities(content, relPath),
|
|
206
|
+
...scanForExposedAdminRoutes(content, relPath),
|
|
207
|
+
...scanForUnprotectedApiEndpoints(content, relPath),
|
|
208
|
+
];
|
|
209
|
+
findings.push(...fileFindings);
|
|
210
|
+
}));
|
|
211
|
+
const criticalCount = findings.filter((f) => f.severity === 'critical').length;
|
|
212
|
+
const highCount = findings.filter((f) => f.severity === 'high').length;
|
|
213
|
+
const mediumCount = findings.filter((f) => f.severity === 'medium').length;
|
|
214
|
+
const lowCount = findings.filter((f) => f.severity === 'low').length;
|
|
215
|
+
const rlsBypassCount = findings.filter((f) => f.ruleId.startsWith('rls_bypass')).length;
|
|
216
|
+
const apiAuthCount = findings.filter((f) => f.ruleId.startsWith('unprotected_api')).length;
|
|
217
|
+
const securityScore = computeSecurityScore(findings);
|
|
218
|
+
return {
|
|
219
|
+
findings,
|
|
220
|
+
summary: {
|
|
221
|
+
criticalCount,
|
|
222
|
+
highCount,
|
|
223
|
+
mediumCount,
|
|
224
|
+
lowCount,
|
|
225
|
+
rlsBypassCount,
|
|
226
|
+
apiAuthCount,
|
|
227
|
+
securityScore,
|
|
228
|
+
filesScanned: allFiles.length,
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "trusta",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Generate your trust page in minutes — npx trusta init",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"trusta": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc -p tsconfig.json",
|
|
16
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
17
|
+
"lint": "eslint src --max-warnings=0",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"trust",
|
|
25
|
+
"security",
|
|
26
|
+
"compliance",
|
|
27
|
+
"trusta"
|
|
28
|
+
],
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/trusta-dev/trusta-cli.git"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://trusta.dev",
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.0.0",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
37
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
38
|
+
"eslint": "^9.0.0",
|
|
39
|
+
"typescript": "^5.5.0"
|
|
40
|
+
}
|
|
41
|
+
}
|