bugproof 0.1.2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -5
- package/README.md +232 -8
- package/bin/bugproof.cmd +2 -0
- package/dist/capture/env-snapshot.d.ts +53 -0
- package/dist/capture/env-snapshot.d.ts.map +1 -0
- package/dist/capture/env-snapshot.js +122 -0
- package/dist/capture/env-snapshot.js.map +1 -0
- package/dist/capture/language-support.d.ts +55 -0
- package/dist/capture/language-support.d.ts.map +1 -0
- package/dist/capture/language-support.js +505 -0
- package/dist/capture/language-support.js.map +1 -0
- package/dist/capture/packager.d.ts +9 -0
- package/dist/capture/packager.d.ts.map +1 -1
- package/dist/capture/packager.js +23 -2
- package/dist/capture/packager.js.map +1 -1
- package/dist/capture/source-strategy.d.ts +52 -0
- package/dist/capture/source-strategy.d.ts.map +1 -0
- package/dist/capture/source-strategy.js +227 -0
- package/dist/capture/source-strategy.js.map +1 -0
- package/dist/cli.js +373 -12
- package/dist/cli.js.map +1 -1
- package/dist/config/loader.d.ts +44 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +87 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/replay/engine.d.ts +9 -0
- package/dist/replay/engine.d.ts.map +1 -1
- package/dist/replay/engine.js +29 -3
- package/dist/replay/engine.js.map +1 -1
- package/dist/replay/hints.d.ts +18 -0
- package/dist/replay/hints.d.ts.map +1 -0
- package/dist/replay/hints.js +138 -0
- package/dist/replay/hints.js.map +1 -0
- package/dist/replay/sandbox.js +41 -14
- package/dist/replay/sandbox.js.map +1 -1
- package/dist/replay/verdict.d.ts.map +1 -1
- package/dist/replay/verdict.js +41 -5
- package/dist/replay/verdict.js.map +1 -1
- package/dist/sandbox/bugbox.d.ts.map +1 -1
- package/dist/sandbox/bugbox.js +40 -6
- package/dist/sandbox/bugbox.js.map +1 -1
- package/dist/sandbox/container.d.ts +81 -0
- package/dist/sandbox/container.d.ts.map +1 -0
- package/dist/sandbox/container.js +343 -0
- package/dist/sandbox/container.js.map +1 -0
- package/dist/sandbox/cross-platform.d.ts +59 -0
- package/dist/sandbox/cross-platform.d.ts.map +1 -0
- package/dist/sandbox/cross-platform.js +330 -0
- package/dist/sandbox/cross-platform.js.map +1 -0
- package/dist/sandbox/filesystem.d.ts +2 -2
- package/dist/sandbox/filesystem.d.ts.map +1 -1
- package/dist/sandbox/filesystem.js +46 -19
- package/dist/sandbox/filesystem.js.map +1 -1
- package/dist/sandbox/network.d.ts.map +1 -1
- package/dist/sandbox/network.js +31 -2
- package/dist/sandbox/network.js.map +1 -1
- package/dist/share/gist.d.ts +21 -0
- package/dist/share/gist.d.ts.map +1 -0
- package/dist/share/gist.js +158 -0
- package/dist/share/gist.js.map +1 -0
- package/dist/utils/archive.d.ts +1 -0
- package/dist/utils/archive.d.ts.map +1 -1
- package/dist/utils/archive.js +42 -1
- package/dist/utils/archive.js.map +1 -1
- package/dist/utils/artifact-validation.d.ts +7 -0
- package/dist/utils/artifact-validation.d.ts.map +1 -0
- package/dist/utils/artifact-validation.js +212 -0
- package/dist/utils/artifact-validation.js.map +1 -0
- package/dist/utils/dependencies.d.ts +18 -0
- package/dist/utils/dependencies.d.ts.map +1 -0
- package/dist/utils/dependencies.js +218 -0
- package/dist/utils/dependencies.js.map +1 -0
- package/dist/utils/ui.d.ts +1 -0
- package/dist/utils/ui.d.ts.map +1 -1
- package/dist/utils/ui.js +1 -0
- package/dist/utils/ui.js.map +1 -1
- package/package.json +5 -2
- package/scripts/postinstall.cjs +38 -5
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Share Engine — push .bug artifacts to GitHub Gist
|
|
3
|
+
*
|
|
4
|
+
* Creates a secret gist with the artifact contents for easy sharing.
|
|
5
|
+
* Recipients can download and replay with: bugproof pull <gist-url>
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as os from 'os';
|
|
10
|
+
import * as https from 'https';
|
|
11
|
+
import { extractZip } from '../utils/archive.js';
|
|
12
|
+
export function sanitizeShareError(input) {
|
|
13
|
+
return input
|
|
14
|
+
.replace(/Bearer\s+[A-Za-z0-9_\-.]+/gi, 'Bearer [REDACTED]')
|
|
15
|
+
.replace(/(gh[pousr]_[A-Za-z0-9_]+)/g, '[REDACTED_TOKEN]')
|
|
16
|
+
.replace(/("authorization"\s*:\s*")([^"]+)(")/gi, '$1[REDACTED]$3')
|
|
17
|
+
.replace(/(token\s*[=:]\s*)([^\s,]+)/gi, '$1[REDACTED]');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Uploads artifact contents to a GitHub Gist.
|
|
21
|
+
* Requires GITHUB_TOKEN or BUGPROOF_GITHUB_TOKEN env var.
|
|
22
|
+
*/
|
|
23
|
+
export async function shareToGist(artifactPath, options = {}) {
|
|
24
|
+
const token = process.env.BUGPROOF_GITHUB_TOKEN || process.env.GITHUB_TOKEN;
|
|
25
|
+
if (!token) {
|
|
26
|
+
throw new Error('GitHub token required for sharing. Set GITHUB_TOKEN or BUGPROOF_GITHUB_TOKEN environment variable.\n' +
|
|
27
|
+
'Create a token at: https://github.com/settings/tokens (needs "gist" scope)');
|
|
28
|
+
}
|
|
29
|
+
// Extract artifact if it's a zip
|
|
30
|
+
let extractDir;
|
|
31
|
+
let targetDir;
|
|
32
|
+
const stat = fs.statSync(artifactPath);
|
|
33
|
+
if (stat.isFile()) {
|
|
34
|
+
extractDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bugproof-share-'));
|
|
35
|
+
await extractZip(artifactPath, extractDir);
|
|
36
|
+
targetDir = extractDir;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
targetDir = artifactPath;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
// Read key files from the artifact
|
|
43
|
+
const files = {};
|
|
44
|
+
const keyFiles = ['manifest.json', 'failure.json', 'run.json', 'env.schema.json'];
|
|
45
|
+
for (const filename of keyFiles) {
|
|
46
|
+
const filePath = path.join(targetDir, filename);
|
|
47
|
+
if (fs.existsSync(filePath)) {
|
|
48
|
+
files[filename] = { content: fs.readFileSync(filePath, 'utf-8') };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Add a README for context
|
|
52
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(targetDir, 'manifest.json'), 'utf-8'));
|
|
53
|
+
files['README.md'] = {
|
|
54
|
+
content: generateGistReadme(manifest),
|
|
55
|
+
};
|
|
56
|
+
// Add stderr/stdout logs if they exist
|
|
57
|
+
const stderrPath = path.join(targetDir, 'stderr.log');
|
|
58
|
+
const stdoutPath = path.join(targetDir, 'stdout.log');
|
|
59
|
+
if (fs.existsSync(stderrPath)) {
|
|
60
|
+
const content = fs.readFileSync(stderrPath, 'utf-8');
|
|
61
|
+
if (content.length <= 100000) { // Gist file size limit
|
|
62
|
+
files['stderr.log'] = { content };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (fs.existsSync(stdoutPath)) {
|
|
66
|
+
const content = fs.readFileSync(stdoutPath, 'utf-8');
|
|
67
|
+
if (content.length <= 100000) {
|
|
68
|
+
files['stdout.log'] = { content };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Create the gist
|
|
72
|
+
const gistData = JSON.stringify({
|
|
73
|
+
description: options.description || `BugProof: ${manifest.name} — ${manifest.description}`,
|
|
74
|
+
public: options.public || false,
|
|
75
|
+
files,
|
|
76
|
+
});
|
|
77
|
+
const result = await httpPost('https://api.github.com/gists', gistData, token);
|
|
78
|
+
const parsed = JSON.parse(result);
|
|
79
|
+
return {
|
|
80
|
+
url: parsed.html_url,
|
|
81
|
+
gistId: parsed.id,
|
|
82
|
+
rawUrl: parsed.html_url + '/raw',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
if (extractDir) {
|
|
87
|
+
fs.rmSync(extractDir, { recursive: true, force: true });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
92
|
+
function generateGistReadme(manifest) {
|
|
93
|
+
return `# BugProof Artifact: ${manifest.name}
|
|
94
|
+
|
|
95
|
+
> ${manifest.description}
|
|
96
|
+
|
|
97
|
+
## Quick Replay
|
|
98
|
+
|
|
99
|
+
\`\`\`bash
|
|
100
|
+
# Download and replay this bug:
|
|
101
|
+
bugproof pull ${manifest.name}
|
|
102
|
+
\`\`\`
|
|
103
|
+
|
|
104
|
+
## Details
|
|
105
|
+
|
|
106
|
+
| Field | Value |
|
|
107
|
+
|-------|-------|
|
|
108
|
+
| Command | \`${manifest.command.join(' ')}\` |
|
|
109
|
+
| Exit Code | ${manifest.exit_code} |
|
|
110
|
+
| Platform | ${manifest.captured_on.os}/${manifest.captured_on.arch} |
|
|
111
|
+
| Node | ${manifest.captured_on.node_version} |
|
|
112
|
+
| Captured | ${manifest.captured_at} |
|
|
113
|
+
| Git | ${manifest.captured_on.git_branch || 'n/a'} @ ${(manifest.captured_on.git_commit || 'n/a').slice(0, 8)} |
|
|
114
|
+
|
|
115
|
+
## Files
|
|
116
|
+
|
|
117
|
+
${manifest.files_count} files captured (${(manifest.files_size_bytes / 1024).toFixed(1)} KB)
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
*Generated by [BugProof](https://github.com/sidinsearch/BugProof) v${manifest.bugproof_version}*
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
function httpPost(url, data, token) {
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
const urlObj = new URL(url);
|
|
126
|
+
const options = {
|
|
127
|
+
hostname: urlObj.hostname,
|
|
128
|
+
port: 443,
|
|
129
|
+
path: urlObj.pathname,
|
|
130
|
+
method: 'POST',
|
|
131
|
+
headers: {
|
|
132
|
+
'Content-Type': 'application/json',
|
|
133
|
+
'Authorization': `Bearer ${token}`,
|
|
134
|
+
'User-Agent': 'BugProof-CLI',
|
|
135
|
+
'Accept': 'application/vnd.github+json',
|
|
136
|
+
'Content-Length': Buffer.byteLength(data),
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
const req = https.request(options, (res) => {
|
|
140
|
+
let body = '';
|
|
141
|
+
res.on('data', (chunk) => { body += chunk; });
|
|
142
|
+
res.on('end', () => {
|
|
143
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
144
|
+
resolve(body);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
reject(new Error(sanitizeShareError(`GitHub API error ${res.statusCode}: ${body}`)));
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
req.on('error', (err) => {
|
|
152
|
+
reject(new Error(sanitizeShareError(String(err))));
|
|
153
|
+
});
|
|
154
|
+
req.write(data);
|
|
155
|
+
req.end();
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=gist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gist.js","sourceRoot":"","sources":["../../src/share/gist.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/archive.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/utils/archive.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/utils/archive.ts"],"names":[],"mappings":"AAUA,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CASjF;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBpF;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqChF"}
|
package/dist/utils/archive.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
2
3
|
import archiver from 'archiver';
|
|
3
4
|
import extract from 'extract-zip';
|
|
5
|
+
import { isPathWithinBoundary } from './security.js';
|
|
6
|
+
const MAX_ARCHIVE_FILES = 10000;
|
|
7
|
+
const MAX_ARCHIVE_UNCOMPRESSED_BYTES = 500 * 1024 * 1024;
|
|
8
|
+
const MAX_SINGLE_FILE_UNCOMPRESSED_BYTES = 100 * 1024 * 1024;
|
|
9
|
+
export function validateArchiveEntryPath(entryName, destDir) {
|
|
10
|
+
if (!entryName || path.isAbsolute(entryName) || entryName.includes('\0')) {
|
|
11
|
+
throw new Error(`Invalid archive entry path: ${entryName}`);
|
|
12
|
+
}
|
|
13
|
+
const normalized = path.resolve(destDir, entryName);
|
|
14
|
+
if (!isPathWithinBoundary(normalized, destDir)) {
|
|
15
|
+
throw new Error(`Path traversal attempt detected: ${entryName}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
4
18
|
/**
|
|
5
19
|
* Compresses a directory into a ZIP archive.
|
|
6
20
|
* @param sourceDir The directory to compress.
|
|
@@ -30,7 +44,34 @@ export async function zipDirectory(sourceDir, outPath) {
|
|
|
30
44
|
*/
|
|
31
45
|
export async function extractZip(zipPath, destDir) {
|
|
32
46
|
try {
|
|
33
|
-
|
|
47
|
+
const resolvedDest = path.resolve(destDir);
|
|
48
|
+
let fileCount = 0;
|
|
49
|
+
let totalSize = 0;
|
|
50
|
+
await extract(zipPath, {
|
|
51
|
+
dir: resolvedDest,
|
|
52
|
+
onEntry: (entry) => {
|
|
53
|
+
fileCount += 1;
|
|
54
|
+
if (fileCount > MAX_ARCHIVE_FILES) {
|
|
55
|
+
throw new Error('Archive contains too many files');
|
|
56
|
+
}
|
|
57
|
+
const entryName = entry.fileName || '';
|
|
58
|
+
validateArchiveEntryPath(entryName, resolvedDest);
|
|
59
|
+
const size = typeof entry.uncompressedSize === 'number' ? entry.uncompressedSize : 0;
|
|
60
|
+
if (size > MAX_SINGLE_FILE_UNCOMPRESSED_BYTES) {
|
|
61
|
+
throw new Error(`Archive entry too large: ${entryName}`);
|
|
62
|
+
}
|
|
63
|
+
totalSize += size;
|
|
64
|
+
if (totalSize > MAX_ARCHIVE_UNCOMPRESSED_BYTES) {
|
|
65
|
+
throw new Error('Archive uncompressed size limit exceeded');
|
|
66
|
+
}
|
|
67
|
+
if (entry.externalFileAttributes !== undefined) {
|
|
68
|
+
const mode = (entry.externalFileAttributes >> 16) & 0o170000;
|
|
69
|
+
if (mode === 0o120000) {
|
|
70
|
+
throw new Error(`Symbolic links are not allowed in archives: ${entryName}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
});
|
|
34
75
|
}
|
|
35
76
|
catch (err) {
|
|
36
77
|
throw new Error(`Failed to extract artifact: ${err instanceof Error ? err.message : err}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/utils/archive.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,OAAO,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/utils/archive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ArtifactManifest, RunConfig } from '../types/artifact.js';
|
|
2
|
+
import { FailureRecord } from '../types/failure.js';
|
|
3
|
+
export declare function secureJsonParse(raw: string, label: string): unknown;
|
|
4
|
+
export declare function validateArtifactManifest(value: unknown): ArtifactManifest;
|
|
5
|
+
export declare function validateRunConfig(value: unknown): RunConfig;
|
|
6
|
+
export declare function validateFailureRecord(value: unknown): FailureRecord;
|
|
7
|
+
//# sourceMappingURL=artifact-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-validation.d.ts","sourceRoot":"","sources":["../../src/utils/artifact-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAsJpD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAcnE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAgCzE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAgB3D;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAoBnE"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
const MAX_JSON_BYTES = 1024 * 1024;
|
|
2
|
+
const MAX_JSON_DEPTH = 32;
|
|
3
|
+
const MAX_COMMAND_ARGS = 256;
|
|
4
|
+
const MAX_STRING_LENGTH = 8192;
|
|
5
|
+
const MANIFEST_KEYS = new Set([
|
|
6
|
+
'version',
|
|
7
|
+
'bugproof_version',
|
|
8
|
+
'name',
|
|
9
|
+
'description',
|
|
10
|
+
'captured_at',
|
|
11
|
+
'captured_on',
|
|
12
|
+
'command',
|
|
13
|
+
'working_directory',
|
|
14
|
+
'exit_code',
|
|
15
|
+
'duration_ms',
|
|
16
|
+
'files_count',
|
|
17
|
+
'files_size_bytes',
|
|
18
|
+
'secrets_detected',
|
|
19
|
+
'secrets_skipped',
|
|
20
|
+
]);
|
|
21
|
+
const CAPTURED_ON_KEYS = new Set([
|
|
22
|
+
'os',
|
|
23
|
+
'arch',
|
|
24
|
+
'node_version',
|
|
25
|
+
'git_commit',
|
|
26
|
+
'git_branch',
|
|
27
|
+
'git_dirty',
|
|
28
|
+
]);
|
|
29
|
+
const RUN_CONFIG_KEYS = new Set([
|
|
30
|
+
'command',
|
|
31
|
+
'working_directory',
|
|
32
|
+
'environment',
|
|
33
|
+
'timeout_ms',
|
|
34
|
+
'capture_output',
|
|
35
|
+
]);
|
|
36
|
+
const FAILURE_KEYS = new Set([
|
|
37
|
+
'exit_code',
|
|
38
|
+
'signal',
|
|
39
|
+
'stdout_lines',
|
|
40
|
+
'stderr_lines',
|
|
41
|
+
'stderr_snippet',
|
|
42
|
+
'fingerprint',
|
|
43
|
+
'error_patterns',
|
|
44
|
+
'duration_ms',
|
|
45
|
+
'timeout',
|
|
46
|
+
]);
|
|
47
|
+
function ensureObject(value, label) {
|
|
48
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
49
|
+
throw new Error(`${label} must be an object`);
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
function ensureNoUnknownKeys(value, allowed, label) {
|
|
54
|
+
for (const key of Object.keys(value)) {
|
|
55
|
+
if (!allowed.has(key)) {
|
|
56
|
+
throw new Error(`${label} contains unknown field: ${key}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function ensureString(value, label) {
|
|
61
|
+
if (typeof value !== 'string') {
|
|
62
|
+
throw new Error(`${label} must be a string`);
|
|
63
|
+
}
|
|
64
|
+
if (value.length > MAX_STRING_LENGTH) {
|
|
65
|
+
throw new Error(`${label} exceeds maximum length`);
|
|
66
|
+
}
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
function ensureOptionalString(value, label) {
|
|
70
|
+
if (value === undefined) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
return ensureString(value, label);
|
|
74
|
+
}
|
|
75
|
+
function ensureNumber(value, label) {
|
|
76
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
77
|
+
throw new Error(`${label} must be a finite number`);
|
|
78
|
+
}
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
function ensureBoolean(value, label) {
|
|
82
|
+
if (typeof value !== 'boolean') {
|
|
83
|
+
throw new Error(`${label} must be a boolean`);
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
function ensureStringArray(value, label, maxItems = MAX_COMMAND_ARGS) {
|
|
88
|
+
if (!Array.isArray(value)) {
|
|
89
|
+
throw new Error(`${label} must be an array`);
|
|
90
|
+
}
|
|
91
|
+
if (value.length === 0 || value.length > maxItems) {
|
|
92
|
+
throw new Error(`${label} has invalid number of items`);
|
|
93
|
+
}
|
|
94
|
+
return value.map((item, index) => ensureString(item, `${label}[${index}]`));
|
|
95
|
+
}
|
|
96
|
+
function ensureOptionalStringArray(value, label, maxItems = MAX_COMMAND_ARGS) {
|
|
97
|
+
if (value === undefined) {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
if (!Array.isArray(value)) {
|
|
101
|
+
throw new Error(`${label} must be an array`);
|
|
102
|
+
}
|
|
103
|
+
if (value.length > maxItems) {
|
|
104
|
+
throw new Error(`${label} has too many items`);
|
|
105
|
+
}
|
|
106
|
+
return value.map((item, index) => ensureString(item, `${label}[${index}]`));
|
|
107
|
+
}
|
|
108
|
+
function ensurePlainEnvironment(value) {
|
|
109
|
+
const env = ensureObject(value, 'run.environment');
|
|
110
|
+
const safe = {};
|
|
111
|
+
for (const [key, raw] of Object.entries(env)) {
|
|
112
|
+
if (!key || key.length > 128 || /[\r\n\0]/.test(key)) {
|
|
113
|
+
throw new Error(`run.environment contains invalid key: ${key}`);
|
|
114
|
+
}
|
|
115
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
116
|
+
throw new Error(`run.environment contains disallowed key: ${key}`);
|
|
117
|
+
}
|
|
118
|
+
safe[key] = ensureString(raw, `run.environment.${key}`);
|
|
119
|
+
}
|
|
120
|
+
return safe;
|
|
121
|
+
}
|
|
122
|
+
function assertMaxDepth(value, depth = 0) {
|
|
123
|
+
if (depth > MAX_JSON_DEPTH) {
|
|
124
|
+
throw new Error('JSON exceeds maximum nesting depth');
|
|
125
|
+
}
|
|
126
|
+
if (Array.isArray(value)) {
|
|
127
|
+
value.forEach((item) => assertMaxDepth(item, depth + 1));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (value && typeof value === 'object') {
|
|
131
|
+
Object.values(value).forEach((item) => assertMaxDepth(item, depth + 1));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
export function secureJsonParse(raw, label) {
|
|
135
|
+
if (raw.length > MAX_JSON_BYTES) {
|
|
136
|
+
throw new Error(`${label} exceeds maximum size`);
|
|
137
|
+
}
|
|
138
|
+
const parsed = JSON.parse(raw, (key, value) => {
|
|
139
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
140
|
+
throw new Error(`${label} contains disallowed key: ${key}`);
|
|
141
|
+
}
|
|
142
|
+
return value;
|
|
143
|
+
});
|
|
144
|
+
assertMaxDepth(parsed);
|
|
145
|
+
return parsed;
|
|
146
|
+
}
|
|
147
|
+
export function validateArtifactManifest(value) {
|
|
148
|
+
const manifest = ensureObject(value, 'manifest');
|
|
149
|
+
ensureNoUnknownKeys(manifest, MANIFEST_KEYS, 'manifest');
|
|
150
|
+
const capturedOnRaw = ensureObject(manifest.captured_on, 'manifest.captured_on');
|
|
151
|
+
ensureNoUnknownKeys(capturedOnRaw, CAPTURED_ON_KEYS, 'manifest.captured_on');
|
|
152
|
+
return {
|
|
153
|
+
version: ensureString(manifest.version, 'manifest.version'),
|
|
154
|
+
bugproof_version: ensureString(manifest.bugproof_version, 'manifest.bugproof_version'),
|
|
155
|
+
name: ensureString(manifest.name, 'manifest.name'),
|
|
156
|
+
description: ensureString(manifest.description, 'manifest.description'),
|
|
157
|
+
captured_at: ensureString(manifest.captured_at, 'manifest.captured_at'),
|
|
158
|
+
captured_on: {
|
|
159
|
+
os: ensureString(capturedOnRaw.os, 'manifest.captured_on.os'),
|
|
160
|
+
arch: ensureString(capturedOnRaw.arch, 'manifest.captured_on.arch'),
|
|
161
|
+
node_version: ensureString(capturedOnRaw.node_version, 'manifest.captured_on.node_version'),
|
|
162
|
+
git_commit: ensureOptionalString(capturedOnRaw.git_commit, 'manifest.captured_on.git_commit'),
|
|
163
|
+
git_branch: ensureOptionalString(capturedOnRaw.git_branch, 'manifest.captured_on.git_branch'),
|
|
164
|
+
git_dirty: capturedOnRaw.git_dirty === undefined
|
|
165
|
+
? undefined
|
|
166
|
+
: ensureBoolean(capturedOnRaw.git_dirty, 'manifest.captured_on.git_dirty'),
|
|
167
|
+
},
|
|
168
|
+
command: ensureStringArray(manifest.command, 'manifest.command'),
|
|
169
|
+
working_directory: ensureString(manifest.working_directory, 'manifest.working_directory'),
|
|
170
|
+
exit_code: ensureNumber(manifest.exit_code, 'manifest.exit_code'),
|
|
171
|
+
duration_ms: ensureNumber(manifest.duration_ms, 'manifest.duration_ms'),
|
|
172
|
+
files_count: ensureNumber(manifest.files_count, 'manifest.files_count'),
|
|
173
|
+
files_size_bytes: ensureNumber(manifest.files_size_bytes, 'manifest.files_size_bytes'),
|
|
174
|
+
secrets_detected: ensureBoolean(manifest.secrets_detected, 'manifest.secrets_detected'),
|
|
175
|
+
secrets_skipped: ensureOptionalStringArray(manifest.secrets_skipped, 'manifest.secrets_skipped'),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
export function validateRunConfig(value) {
|
|
179
|
+
const run = ensureObject(value, 'run');
|
|
180
|
+
ensureNoUnknownKeys(run, RUN_CONFIG_KEYS, 'run');
|
|
181
|
+
const timeoutMs = ensureNumber(run.timeout_ms, 'run.timeout_ms');
|
|
182
|
+
if (timeoutMs <= 0 || timeoutMs > 60 * 60 * 1000) {
|
|
183
|
+
throw new Error('run.timeout_ms out of range');
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
command: ensureStringArray(run.command, 'run.command'),
|
|
187
|
+
working_directory: ensureString(run.working_directory, 'run.working_directory'),
|
|
188
|
+
environment: ensurePlainEnvironment(run.environment),
|
|
189
|
+
timeout_ms: timeoutMs,
|
|
190
|
+
capture_output: ensureBoolean(run.capture_output, 'run.capture_output'),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
export function validateFailureRecord(value) {
|
|
194
|
+
const failure = ensureObject(value, 'failure');
|
|
195
|
+
ensureNoUnknownKeys(failure, FAILURE_KEYS, 'failure');
|
|
196
|
+
const signal = failure.signal;
|
|
197
|
+
if (!(signal === null || typeof signal === 'string')) {
|
|
198
|
+
throw new Error('failure.signal must be null or string');
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
exit_code: ensureNumber(failure.exit_code, 'failure.exit_code'),
|
|
202
|
+
signal,
|
|
203
|
+
stdout_lines: ensureNumber(failure.stdout_lines, 'failure.stdout_lines'),
|
|
204
|
+
stderr_lines: ensureNumber(failure.stderr_lines, 'failure.stderr_lines'),
|
|
205
|
+
stderr_snippet: ensureString(failure.stderr_snippet, 'failure.stderr_snippet'),
|
|
206
|
+
fingerprint: ensureString(failure.fingerprint, 'failure.fingerprint'),
|
|
207
|
+
error_patterns: ensureOptionalStringArray(failure.error_patterns, 'failure.error_patterns'),
|
|
208
|
+
duration_ms: ensureNumber(failure.duration_ms, 'failure.duration_ms'),
|
|
209
|
+
timeout: ensureBoolean(failure.timeout, 'failure.timeout'),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=artifact-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-validation.js","sourceRoot":"","sources":["../../src/utils/artifact-validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Detection Engine
|
|
3
|
+
*
|
|
4
|
+
* Analyzes stderr output to detect missing dependencies and suggest
|
|
5
|
+
* installation commands. Works across Node.js, Python, Ruby, Go, Rust, and more.
|
|
6
|
+
*/
|
|
7
|
+
export interface MissingDependency {
|
|
8
|
+
name: string;
|
|
9
|
+
language: string;
|
|
10
|
+
installCommand: string;
|
|
11
|
+
confidence: 'high' | 'medium' | 'low';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Scans stderr output and detects missing dependencies.
|
|
15
|
+
* Returns a deduplicated list of dependencies with install commands.
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectMissingDependencies(stderr: string): MissingDependency[];
|
|
18
|
+
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/utils/dependencies.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAmMD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAwB7E"}
|