bugproof 0.1.1
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 +65 -0
- package/README.md +256 -0
- package/assets/icon-16x16.png +0 -0
- package/assets/icon-32x32.png +0 -0
- package/assets/icon-512x512.png +0 -0
- package/dist/capture/engine.d.ts +12 -0
- package/dist/capture/engine.d.ts.map +1 -0
- package/dist/capture/engine.js +129 -0
- package/dist/capture/engine.js.map +1 -0
- package/dist/capture/packager.d.ts +39 -0
- package/dist/capture/packager.d.ts.map +1 -0
- package/dist/capture/packager.js +145 -0
- package/dist/capture/packager.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +538 -0
- package/dist/cli.js.map +1 -0
- package/dist/diff/engine.d.ts +28 -0
- package/dist/diff/engine.d.ts.map +1 -0
- package/dist/diff/engine.js +88 -0
- package/dist/diff/engine.js.map +1 -0
- package/dist/replay/engine.d.ts +41 -0
- package/dist/replay/engine.d.ts.map +1 -0
- package/dist/replay/engine.js +69 -0
- package/dist/replay/engine.js.map +1 -0
- package/dist/replay/sandbox.d.ts +33 -0
- package/dist/replay/sandbox.d.ts.map +1 -0
- package/dist/replay/sandbox.js +167 -0
- package/dist/replay/sandbox.js.map +1 -0
- package/dist/replay/verdict.d.ts +8 -0
- package/dist/replay/verdict.d.ts.map +1 -0
- package/dist/replay/verdict.js +32 -0
- package/dist/replay/verdict.js.map +1 -0
- package/dist/sandbox/bugbox.d.ts +38 -0
- package/dist/sandbox/bugbox.d.ts.map +1 -0
- package/dist/sandbox/bugbox.js +122 -0
- package/dist/sandbox/bugbox.js.map +1 -0
- package/dist/sandbox/capabilities.d.ts +33 -0
- package/dist/sandbox/capabilities.d.ts.map +1 -0
- package/dist/sandbox/capabilities.js +53 -0
- package/dist/sandbox/capabilities.js.map +1 -0
- package/dist/sandbox/filesystem.d.ts +50 -0
- package/dist/sandbox/filesystem.d.ts.map +1 -0
- package/dist/sandbox/filesystem.js +134 -0
- package/dist/sandbox/filesystem.js.map +1 -0
- package/dist/sandbox/network.d.ts +68 -0
- package/dist/sandbox/network.d.ts.map +1 -0
- package/dist/sandbox/network.js +136 -0
- package/dist/sandbox/network.js.map +1 -0
- package/dist/sandbox/process.d.ts +17 -0
- package/dist/sandbox/process.d.ts.map +1 -0
- package/dist/sandbox/process.js +30 -0
- package/dist/sandbox/process.js.map +1 -0
- package/dist/sandbox/resources.d.ts +21 -0
- package/dist/sandbox/resources.d.ts.map +1 -0
- package/dist/sandbox/resources.js +60 -0
- package/dist/sandbox/resources.js.map +1 -0
- package/dist/types/artifact.d.ts +57 -0
- package/dist/types/artifact.d.ts.map +1 -0
- package/dist/types/artifact.js +2 -0
- package/dist/types/artifact.js.map +1 -0
- package/dist/types/failure.d.ts +12 -0
- package/dist/types/failure.d.ts.map +1 -0
- package/dist/types/failure.js +2 -0
- package/dist/types/failure.js.map +1 -0
- package/dist/utils/archive.d.ts +13 -0
- package/dist/utils/archive.d.ts.map +1 -0
- package/dist/utils/archive.js +39 -0
- package/dist/utils/archive.js.map +1 -0
- package/dist/utils/associations.d.ts +10 -0
- package/dist/utils/associations.d.ts.map +1 -0
- package/dist/utils/associations.js +46 -0
- package/dist/utils/associations.js.map +1 -0
- package/dist/utils/exclude.d.ts +12 -0
- package/dist/utils/exclude.d.ts.map +1 -0
- package/dist/utils/exclude.js +42 -0
- package/dist/utils/exclude.js.map +1 -0
- package/dist/utils/fingerprint.d.ts +16 -0
- package/dist/utils/fingerprint.d.ts.map +1 -0
- package/dist/utils/fingerprint.js +72 -0
- package/dist/utils/fingerprint.js.map +1 -0
- package/dist/utils/git.d.ts +13 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +41 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/json-output.d.ts +36 -0
- package/dist/utils/json-output.d.ts.map +1 -0
- package/dist/utils/json-output.js +49 -0
- package/dist/utils/json-output.js.map +1 -0
- package/dist/utils/paths.d.ts +19 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +43 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/secrets.d.ts +13 -0
- package/dist/utils/secrets.d.ts.map +1 -0
- package/dist/utils/secrets.js +52 -0
- package/dist/utils/secrets.js.map +1 -0
- package/dist/utils/security.d.ts +27 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +75 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/ui.d.ts +31 -0
- package/dist/utils/ui.d.ts.map +1 -0
- package/dist/utils/ui.js +54 -0
- package/dist/utils/ui.js.map +1 -0
- package/package.json +80 -0
- package/scripts/bugproof-file-association-linux.sh +80 -0
- package/scripts/bugproof-file-association-macos.sh +48 -0
- package/scripts/bugproof-file-association-windows.reg +44 -0
- package/scripts/postinstall.cjs +215 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes a path to consistently use forward slashes (/) across all platforms.
|
|
3
|
+
* This ensures artifact portability between Windows, Linux, and macOS.
|
|
4
|
+
*/
|
|
5
|
+
export declare function normalizeArtifactPath(p: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Converts a portable artifact path back to the platform-specific path separator.
|
|
8
|
+
* Useful during replay on a host machine.
|
|
9
|
+
*/
|
|
10
|
+
export declare function toPlatformPath(artifactPath: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Reconstructs the absolute path on the host during replay,
|
|
13
|
+
* mapping the original absolute path to a temporary replay directory.
|
|
14
|
+
*
|
|
15
|
+
* @param originalPath The absolute path captured in the artifact
|
|
16
|
+
* @param tempReplayRoot The root of the temporary replay environment
|
|
17
|
+
*/
|
|
18
|
+
export declare function mapToReplayEnvironment(originalPath: string, tempReplayRoot: string): string;
|
|
19
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAoB3F"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes a path to consistently use forward slashes (/) across all platforms.
|
|
4
|
+
* This ensures artifact portability between Windows, Linux, and macOS.
|
|
5
|
+
*/
|
|
6
|
+
export function normalizeArtifactPath(p) {
|
|
7
|
+
// Use posix-style normalization for the artifact internal representations
|
|
8
|
+
return p.split(path.sep).join(path.posix.sep);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Converts a portable artifact path back to the platform-specific path separator.
|
|
12
|
+
* Useful during replay on a host machine.
|
|
13
|
+
*/
|
|
14
|
+
export function toPlatformPath(artifactPath) {
|
|
15
|
+
return artifactPath.split(path.posix.sep).join(path.sep);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Reconstructs the absolute path on the host during replay,
|
|
19
|
+
* mapping the original absolute path to a temporary replay directory.
|
|
20
|
+
*
|
|
21
|
+
* @param originalPath The absolute path captured in the artifact
|
|
22
|
+
* @param tempReplayRoot The root of the temporary replay environment
|
|
23
|
+
*/
|
|
24
|
+
export function mapToReplayEnvironment(originalPath, tempReplayRoot) {
|
|
25
|
+
// Strip the leading root from the original path (e.g. C:\ or /)
|
|
26
|
+
// so it can be appended safely to the temp root.
|
|
27
|
+
// Handle Windows absolute paths (e.g., D:\path\to\file or C:/path/to/file)
|
|
28
|
+
// regardless of the current platform, since artifact paths may be cross-platform
|
|
29
|
+
const windowsAbsolutePattern = /^[A-Z]:[/\\]/i;
|
|
30
|
+
if (windowsAbsolutePattern.test(originalPath)) {
|
|
31
|
+
// Strip the drive letter and colon (e.g., "D:\" -> "")
|
|
32
|
+
const pathWithoutRoot = originalPath.slice(2);
|
|
33
|
+
// Normalize to forward slashes for cross-platform consistency
|
|
34
|
+
// Explicitly replace both forward and backward slashes with forward slashes
|
|
35
|
+
const normalized = pathWithoutRoot.replace(/\\/g, '/').replace(/\/+/g, '/');
|
|
36
|
+
return path.posix.join(tempReplayRoot, normalized);
|
|
37
|
+
}
|
|
38
|
+
// Handle Unix absolute paths
|
|
39
|
+
const parsed = path.parse(originalPath);
|
|
40
|
+
const pathWithoutRoot = originalPath.slice(parsed.root.length);
|
|
41
|
+
return path.join(tempReplayRoot, pathWithoutRoot);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAAS;IAC7C,0EAA0E;IAC1E,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,YAAoB;IACjD,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,YAAoB,EAAE,cAAsB;IACjF,gEAAgE;IAChE,iDAAiD;IAEjD,2EAA2E;IAC3E,iFAAiF;IACjF,MAAM,sBAAsB,GAAG,eAAe,CAAC;IAC/C,IAAI,sBAAsB,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9C,uDAAuD;QACvD,MAAM,eAAe,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9C,8DAA8D;QAC9D,4EAA4E;QAC5E,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5E,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IACrD,CAAC;IAED,6BAA6B;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACxC,MAAM,eAAe,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const SECRET_PATTERNS: RegExp[];
|
|
2
|
+
export interface SecretScanResult {
|
|
3
|
+
hasSecrets: boolean;
|
|
4
|
+
detectedKeys: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function scanEnvironmentForSecrets(env: NodeJS.ProcessEnv): SecretScanResult;
|
|
7
|
+
export declare function buildEnvironmentSchema(env: NodeJS.ProcessEnv, detectedSecrets: string[]): {
|
|
8
|
+
required: string[];
|
|
9
|
+
optional: string[];
|
|
10
|
+
secrets: string[];
|
|
11
|
+
captured_env_keys: string[];
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/utils/secrets.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,UAU3B,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,gBAAgB,CAwBlF;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAAE,CAkBpL"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export const SECRET_PATTERNS = [
|
|
2
|
+
/api_?key/i,
|
|
3
|
+
/secret/i,
|
|
4
|
+
/token/i,
|
|
5
|
+
/password/i,
|
|
6
|
+
/bearer/i,
|
|
7
|
+
/aws_secret_access_key/i,
|
|
8
|
+
/github_token/i,
|
|
9
|
+
/stripe_sk_/i,
|
|
10
|
+
/^[A-Z0-9]{20,128}$/ // Likely tokens (bounded to prevent excessive matching)
|
|
11
|
+
];
|
|
12
|
+
export function scanEnvironmentForSecrets(env) {
|
|
13
|
+
const detectedKeys = [];
|
|
14
|
+
for (const [key, value] of Object.entries(env)) {
|
|
15
|
+
if (!value)
|
|
16
|
+
continue;
|
|
17
|
+
// Check if key matches known secret patterns
|
|
18
|
+
let isSecret = false;
|
|
19
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
20
|
+
if (pattern.test(key) || (pattern.test(value) && value.length > 15)) {
|
|
21
|
+
isSecret = true;
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (isSecret) {
|
|
26
|
+
detectedKeys.push(key);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
hasSecrets: detectedKeys.length > 0,
|
|
31
|
+
detectedKeys
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function buildEnvironmentSchema(env, detectedSecrets) {
|
|
35
|
+
// In a real scenario, we'd determine which env vars are actually required by the app.
|
|
36
|
+
// For v0.1, we classify everything non-standard as 'optional' unless explicitly mapped,
|
|
37
|
+
// except secrets which are separated out.
|
|
38
|
+
const standardKeys = ['PATH', 'HOME', 'USER', 'SHELL', 'TEMP', 'TMPDIR', 'USERPROFILE'];
|
|
39
|
+
const optional = [];
|
|
40
|
+
const required = []; // We will let users specify required later, or infer
|
|
41
|
+
const secrets = [...detectedSecrets];
|
|
42
|
+
const captured_env_keys = Object.keys(env);
|
|
43
|
+
for (const key of Object.keys(env)) {
|
|
44
|
+
if (standardKeys.includes(key))
|
|
45
|
+
continue;
|
|
46
|
+
if (secrets.includes(key))
|
|
47
|
+
continue;
|
|
48
|
+
optional.push(key);
|
|
49
|
+
}
|
|
50
|
+
return { required, optional, secrets, captured_env_keys };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/utils/secrets.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,WAAW;IACX,SAAS;IACT,QAAQ;IACR,WAAW;IACX,SAAS;IACT,wBAAwB;IACxB,eAAe;IACf,aAAa;IACb,oBAAoB,CAAC,wDAAwD;CAC9E,CAAC;AAOF,MAAM,UAAU,yBAAyB,CAAC,GAAsB;IAC9D,MAAM,YAAY,GAAa,EAAE,CAAC;IAElC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,6CAA6C;QAC7C,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;YACtC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC;gBACpE,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO;QACL,UAAU,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC;QACnC,YAAY;KACb,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,GAAsB,EAAE,eAAyB;IACtF,sFAAsF;IACtF,wFAAwF;IACxF,0CAA0C;IAC1C,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAExF,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAa,EAAE,CAAC,CAAC,qDAAqD;IACpF,MAAM,OAAO,GAAG,CAAC,GAAG,eAAe,CAAC,CAAC;IACrC,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QACzC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QACpC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security validation utilities for BugProof.
|
|
3
|
+
* Prevents path traversal, command injection, git ref injection,
|
|
4
|
+
* and environment variable hijacking from untrusted artifact data.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Validates that a resolved file path stays within the expected boundary directory.
|
|
8
|
+
* Prevents path traversal attacks via `../` sequences.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isPathWithinBoundary(filePath: string, boundaryDir: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Validates a git ref string to prevent flag injection.
|
|
13
|
+
* Git interprets arguments starting with `-` as flags, so we reject those.
|
|
14
|
+
* Accepts: hex commit SHAs, branch names (alphanumeric, dots, slashes, dashes, underscores).
|
|
15
|
+
*/
|
|
16
|
+
export declare function isValidGitRef(ref: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Environment variable names that must NEVER be overridden from untrusted artifact data.
|
|
19
|
+
* These can be used to hijack process execution.
|
|
20
|
+
*/
|
|
21
|
+
export declare const DANGEROUS_ENV_VARS: Set<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Filters an environment record, removing keys that could hijack execution.
|
|
24
|
+
* Used during replay to prevent artifact environment from overriding critical host vars.
|
|
25
|
+
*/
|
|
26
|
+
export declare function sanitizeArtifactEnvironment(artifactEnv: Record<string, string>): Record<string, string>;
|
|
27
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAInF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,aA0B7B,CAAC;AAEH;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security validation utilities for BugProof.
|
|
3
|
+
* Prevents path traversal, command injection, git ref injection,
|
|
4
|
+
* and environment variable hijacking from untrusted artifact data.
|
|
5
|
+
*/
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
/**
|
|
8
|
+
* Validates that a resolved file path stays within the expected boundary directory.
|
|
9
|
+
* Prevents path traversal attacks via `../` sequences.
|
|
10
|
+
*/
|
|
11
|
+
export function isPathWithinBoundary(filePath, boundaryDir) {
|
|
12
|
+
const resolved = path.resolve(filePath);
|
|
13
|
+
const boundary = path.resolve(boundaryDir);
|
|
14
|
+
return resolved.startsWith(boundary + path.sep) || resolved === boundary;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validates a git ref string to prevent flag injection.
|
|
18
|
+
* Git interprets arguments starting with `-` as flags, so we reject those.
|
|
19
|
+
* Accepts: hex commit SHAs, branch names (alphanumeric, dots, slashes, dashes, underscores).
|
|
20
|
+
*/
|
|
21
|
+
export function isValidGitRef(ref) {
|
|
22
|
+
if (!ref || ref.length === 0 || ref.length > 256)
|
|
23
|
+
return false;
|
|
24
|
+
// Must not start with a dash (flag injection)
|
|
25
|
+
if (ref.startsWith('-'))
|
|
26
|
+
return false;
|
|
27
|
+
// Allow hex SHAs or branch-like names
|
|
28
|
+
// Valid chars: a-z, A-Z, 0-9, /, ., _, -
|
|
29
|
+
return /^[a-zA-Z0-9._/-]+$/.test(ref);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Environment variable names that must NEVER be overridden from untrusted artifact data.
|
|
33
|
+
* These can be used to hijack process execution.
|
|
34
|
+
*/
|
|
35
|
+
export const DANGEROUS_ENV_VARS = new Set([
|
|
36
|
+
'PATH',
|
|
37
|
+
'LD_PRELOAD',
|
|
38
|
+
'LD_LIBRARY_PATH',
|
|
39
|
+
'DYLD_INSERT_LIBRARIES',
|
|
40
|
+
'DYLD_LIBRARY_PATH',
|
|
41
|
+
'NODE_OPTIONS',
|
|
42
|
+
'NODE_PATH',
|
|
43
|
+
'HOME',
|
|
44
|
+
'USERPROFILE',
|
|
45
|
+
'SHELL',
|
|
46
|
+
'COMSPEC',
|
|
47
|
+
'SYSTEMROOT',
|
|
48
|
+
'WINDIR',
|
|
49
|
+
'PYTHONPATH',
|
|
50
|
+
'RUBYLIB',
|
|
51
|
+
'PERL5LIB',
|
|
52
|
+
'TEMP',
|
|
53
|
+
'TMP',
|
|
54
|
+
'TMPDIR',
|
|
55
|
+
'APPDATA',
|
|
56
|
+
'LOCALAPPDATA',
|
|
57
|
+
'XDG_RUNTIME_DIR',
|
|
58
|
+
'NODE_EXTRA_CA_CERTS',
|
|
59
|
+
'SSL_CERT_FILE',
|
|
60
|
+
'CURL_CA_BUNDLE',
|
|
61
|
+
]);
|
|
62
|
+
/**
|
|
63
|
+
* Filters an environment record, removing keys that could hijack execution.
|
|
64
|
+
* Used during replay to prevent artifact environment from overriding critical host vars.
|
|
65
|
+
*/
|
|
66
|
+
export function sanitizeArtifactEnvironment(artifactEnv) {
|
|
67
|
+
const safe = {};
|
|
68
|
+
for (const [key, val] of Object.entries(artifactEnv)) {
|
|
69
|
+
if (!DANGEROUS_ENV_VARS.has(key.toUpperCase())) {
|
|
70
|
+
safe[key] = val;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return safe;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,WAAmB;IACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3C,OAAO,QAAQ,CAAC,UAAU,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,QAAQ,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IAC/D,8CAA8C;IAC9C,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,sCAAsC;IACtC,yCAAyC;IACzC,OAAO,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACxC,MAAM;IACN,YAAY;IACZ,iBAAiB;IACjB,uBAAuB;IACvB,mBAAmB;IACnB,cAAc;IACd,WAAW;IACX,MAAM;IACN,aAAa;IACb,OAAO;IACP,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,YAAY;IACZ,SAAS;IACT,UAAU;IACV,MAAM;IACN,KAAK;IACL,QAAQ;IACR,SAAS;IACT,cAAc;IACd,iBAAiB;IACjB,qBAAqB;IACrB,eAAe;IACf,gBAAgB;CACjB,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,WAAmC;IAEnC,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colored terminal output for BugProof CLI.
|
|
3
|
+
* Uses ANSI codes directly so we avoid ESM-only import issues with chalk v5.
|
|
4
|
+
*/
|
|
5
|
+
export declare const c: {
|
|
6
|
+
bold: (t: string) => string;
|
|
7
|
+
dim: (t: string) => string;
|
|
8
|
+
red: (t: string) => string;
|
|
9
|
+
green: (t: string) => string;
|
|
10
|
+
yellow: (t: string) => string;
|
|
11
|
+
blue: (t: string) => string;
|
|
12
|
+
magenta: (t: string) => string;
|
|
13
|
+
cyan: (t: string) => string;
|
|
14
|
+
gray: (t: string) => string;
|
|
15
|
+
};
|
|
16
|
+
export declare const icons: {
|
|
17
|
+
check: string;
|
|
18
|
+
cross: string;
|
|
19
|
+
warning: string;
|
|
20
|
+
arrow: string;
|
|
21
|
+
bug: string;
|
|
22
|
+
box: string;
|
|
23
|
+
dot: string;
|
|
24
|
+
};
|
|
25
|
+
export declare function banner(text: string): void;
|
|
26
|
+
export declare function success(msg: string): void;
|
|
27
|
+
export declare function warn(msg: string): void;
|
|
28
|
+
export declare function error(msg: string): void;
|
|
29
|
+
export declare function info(msg: string): void;
|
|
30
|
+
export declare function kvLine(key: string, value: string): void;
|
|
31
|
+
//# sourceMappingURL=ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/utils/ui.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,eAAO,MAAM,CAAC;cACC,MAAM;aACN,MAAM;aACN,MAAM;eACN,MAAM;gBACN,MAAM;cACN,MAAM;iBACN,MAAM;cACN,MAAM;cACN,MAAM;CACpB,CAAC;AAEF,eAAO,MAAM,KAAK;;;;;;;;CAQjB,CAAC;AAEF,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAOzC;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEzC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEvC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAEvD"}
|
package/dist/utils/ui.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colored terminal output for BugProof CLI.
|
|
3
|
+
* Uses ANSI codes directly so we avoid ESM-only import issues with chalk v5.
|
|
4
|
+
*/
|
|
5
|
+
const isColorSupported = process.stdout.isTTY && !process.env['NO_COLOR'];
|
|
6
|
+
function wrap(code, resetCode, text) {
|
|
7
|
+
if (!isColorSupported)
|
|
8
|
+
return text;
|
|
9
|
+
return `\x1b[${code}m${text}\x1b[${resetCode}m`;
|
|
10
|
+
}
|
|
11
|
+
export const c = {
|
|
12
|
+
bold: (t) => wrap(1, 22, t),
|
|
13
|
+
dim: (t) => wrap(2, 22, t),
|
|
14
|
+
red: (t) => wrap(31, 39, t),
|
|
15
|
+
green: (t) => wrap(32, 39, t),
|
|
16
|
+
yellow: (t) => wrap(33, 39, t),
|
|
17
|
+
blue: (t) => wrap(34, 39, t),
|
|
18
|
+
magenta: (t) => wrap(35, 39, t),
|
|
19
|
+
cyan: (t) => wrap(36, 39, t),
|
|
20
|
+
gray: (t) => wrap(90, 39, t),
|
|
21
|
+
};
|
|
22
|
+
export const icons = {
|
|
23
|
+
check: isColorSupported ? '\u2714' : '+',
|
|
24
|
+
cross: isColorSupported ? '\u2718' : 'x',
|
|
25
|
+
warning: isColorSupported ? '\u26A0' : '!',
|
|
26
|
+
arrow: isColorSupported ? '\u279C' : '>', // Sleeker arrow
|
|
27
|
+
bug: isColorSupported ? '\uD83E\uDEB2' : '*', // Beetle emoji for modern look
|
|
28
|
+
box: isColorSupported ? '\u25A0' : '#',
|
|
29
|
+
dot: isColorSupported ? '\u2022' : '-',
|
|
30
|
+
};
|
|
31
|
+
export function banner(text) {
|
|
32
|
+
const line = '\u2500'.repeat(Math.max(text.length + 4, 40));
|
|
33
|
+
console.log();
|
|
34
|
+
console.log(c.cyan(`\u256D${line}\u256E`));
|
|
35
|
+
console.log(c.cyan(`\u2502 ${c.bold(text.padEnd(line.length - 2))}\u2502`));
|
|
36
|
+
console.log(c.cyan(`\u2570${line}\u256F`));
|
|
37
|
+
console.log();
|
|
38
|
+
}
|
|
39
|
+
export function success(msg) {
|
|
40
|
+
console.log(` ${c.green(icons.check)} ${msg}`);
|
|
41
|
+
}
|
|
42
|
+
export function warn(msg) {
|
|
43
|
+
console.log(` ${c.yellow(icons.warning)} ${msg}`);
|
|
44
|
+
}
|
|
45
|
+
export function error(msg) {
|
|
46
|
+
console.log(` ${c.red(icons.cross)} ${msg}`);
|
|
47
|
+
}
|
|
48
|
+
export function info(msg) {
|
|
49
|
+
console.log(` ${c.blue(icons.arrow)} ${msg}`);
|
|
50
|
+
}
|
|
51
|
+
export function kvLine(key, value) {
|
|
52
|
+
console.log(` ${c.dim(key.padEnd(16))} ${value}`);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/utils/ui.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bugproof",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Executable bug artifacts — portable, reproducible bug reports",
|
|
5
|
+
"main": "dist/cli.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"bugproof": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
13
|
+
"prepublishOnly": "npm run build && npm run test && npm run lint",
|
|
14
|
+
"dev": "tsx watch src/index.ts",
|
|
15
|
+
"test": "jest",
|
|
16
|
+
"test:watch": "jest --watch",
|
|
17
|
+
"test:coverage": "jest --coverage",
|
|
18
|
+
"lint": "eslint src --ext .ts",
|
|
19
|
+
"format": "prettier --write 'src/**/*.ts'",
|
|
20
|
+
"cli": "tsx src/cli.ts",
|
|
21
|
+
"test:e2e": "node scripts/e2e-matrix.js",
|
|
22
|
+
"test:comprehensive": "node scripts/comprehensive-test.js",
|
|
23
|
+
"release": "node scripts/release.cjs"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"bug",
|
|
27
|
+
"reproducible",
|
|
28
|
+
"artifact",
|
|
29
|
+
"cli",
|
|
30
|
+
"debugging",
|
|
31
|
+
"issue-tracking",
|
|
32
|
+
"portable"
|
|
33
|
+
],
|
|
34
|
+
"author": "BugProof Contributors",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/archiver": "^7.0.0",
|
|
38
|
+
"@types/extract-zip": "^2.0.0",
|
|
39
|
+
"@types/jest": "^29.5.14",
|
|
40
|
+
"@types/node": "^20.0.0",
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
42
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
43
|
+
"eslint": "^8.0.0",
|
|
44
|
+
"jest": "^29.7.0",
|
|
45
|
+
"node-ssh": "^13.2.1",
|
|
46
|
+
"prettier": "^3.0.0",
|
|
47
|
+
"ts-jest": "^29.4.9",
|
|
48
|
+
"tsx": "^4.0.0",
|
|
49
|
+
"typescript": "^5.0.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"archiver": "^7.0.1",
|
|
53
|
+
"commander": "^11.0.0",
|
|
54
|
+
"extract-zip": "^2.0.1"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=18.0.0"
|
|
58
|
+
},
|
|
59
|
+
"files": [
|
|
60
|
+
"dist",
|
|
61
|
+
"assets",
|
|
62
|
+
"scripts/bugproof-file-association-*.sh",
|
|
63
|
+
"scripts/bugproof-file-association-*.reg",
|
|
64
|
+
"scripts/postinstall.cjs",
|
|
65
|
+
"README.md",
|
|
66
|
+
"LICENSE",
|
|
67
|
+
"CHANGELOG.md"
|
|
68
|
+
],
|
|
69
|
+
"directories": {
|
|
70
|
+
"doc": "docs"
|
|
71
|
+
},
|
|
72
|
+
"repository": {
|
|
73
|
+
"type": "git",
|
|
74
|
+
"url": "git+https://github.com/sidinsearch/BugProof.git"
|
|
75
|
+
},
|
|
76
|
+
"bugs": {
|
|
77
|
+
"url": "https://github.com/sidinsearch/BugProof/issues"
|
|
78
|
+
},
|
|
79
|
+
"homepage": "https://github.com/sidinsearch/BugProof#readme"
|
|
80
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# BugProof Linux file association setup
|
|
3
|
+
# Registers .bug files and creates MIME type association
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "🐧 Setting up BugProof file associations on Linux..."
|
|
8
|
+
|
|
9
|
+
# Create MIME type file
|
|
10
|
+
MIME_FILE="/usr/share/mime/packages/bugproof-bug.xml"
|
|
11
|
+
if [ -f "$MIME_FILE" ]; then
|
|
12
|
+
echo "✓ MIME type already registered"
|
|
13
|
+
else
|
|
14
|
+
sudo tee "$MIME_FILE" > /dev/null <<'EOF'
|
|
15
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
16
|
+
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
|
17
|
+
<mime-type type="application/x-bugproof">
|
|
18
|
+
<comment>BugProof Bug Artifact</comment>
|
|
19
|
+
<glob pattern="*.bug"/>
|
|
20
|
+
<magic priority="50">
|
|
21
|
+
<match type="string" value="PK\x03\x04" offset="0"/>
|
|
22
|
+
</magic>
|
|
23
|
+
</mime-type>
|
|
24
|
+
</mime-info>
|
|
25
|
+
EOF
|
|
26
|
+
echo "✓ MIME type registered at $MIME_FILE"
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Update MIME database
|
|
30
|
+
if command -v update-mime-database &> /dev/null; then
|
|
31
|
+
sudo update-mime-database /usr/share/mime
|
|
32
|
+
echo "✓ MIME database updated"
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Create .desktop file for replay action
|
|
36
|
+
DESKTOP_REPLAY="/usr/share/applications/bugproof-replay.desktop"
|
|
37
|
+
sudo tee "$DESKTOP_REPLAY" > /dev/null <<'EOF'
|
|
38
|
+
[Desktop Entry]
|
|
39
|
+
Type=Application
|
|
40
|
+
Name=BugProof Replay
|
|
41
|
+
Exec=bugproof replay %F
|
|
42
|
+
MimeType=application/x-bugproof
|
|
43
|
+
Icon=bugproof
|
|
44
|
+
NoDisplay=true
|
|
45
|
+
EOF
|
|
46
|
+
echo "✓ Desktop entry created for replay"
|
|
47
|
+
|
|
48
|
+
# Create .desktop file for inspect action
|
|
49
|
+
DESKTOP_INSPECT="/usr/share/applications/bugproof-inspect.desktop"
|
|
50
|
+
sudo tee "$DESKTOP_INSPECT" > /dev/null <<'EOF'
|
|
51
|
+
[Desktop Entry]
|
|
52
|
+
Type=Application
|
|
53
|
+
Name=BugProof Inspect
|
|
54
|
+
Exec=bugproof inspect %F
|
|
55
|
+
MimeType=application/x-bugproof
|
|
56
|
+
Icon=bugproof
|
|
57
|
+
NoDisplay=true
|
|
58
|
+
EOF
|
|
59
|
+
echo "✓ Desktop entry created for inspect"
|
|
60
|
+
|
|
61
|
+
# Install icon
|
|
62
|
+
ICON_DIR="/usr/share/icons/hicolor/512x512/apps"
|
|
63
|
+
if [ -d "$ICON_DIR" ]; then
|
|
64
|
+
sudo cp assets/icon-512x512.png "$ICON_DIR/bugproof.png" 2>/dev/null || true
|
|
65
|
+
echo "✓ Icon installed to $ICON_DIR"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Set default handler for .bug files
|
|
69
|
+
if command -v xdg-mime &> /dev/null; then
|
|
70
|
+
xdg-mime default bugproof-replay.desktop application/x-bugproof
|
|
71
|
+
echo "✓ Set default handler to BugProof Replay"
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
echo ""
|
|
75
|
+
echo "✅ BugProof file association setup complete!"
|
|
76
|
+
echo ""
|
|
77
|
+
echo "🎯 You can now:"
|
|
78
|
+
echo " • Double-click .bug files to replay them"
|
|
79
|
+
echo " • Right-click → Open With → BugProof Replay"
|
|
80
|
+
echo " • Command: bugproof replay artifact.bug"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# BugProof macOS file association setup
|
|
3
|
+
# Registers .bug files for macOS
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "🍎 Setting up BugProof file associations on macOS..."
|
|
8
|
+
|
|
9
|
+
# Create UTType definition
|
|
10
|
+
PLIST_FILE="$HOME/Library/LaunchAgents/com.bugproof.uti.plist"
|
|
11
|
+
mkdir -p "$(dirname "$PLIST_FILE")"
|
|
12
|
+
|
|
13
|
+
cat > "$PLIST_FILE" <<'EOF'
|
|
14
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
15
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
16
|
+
<plist version="1.0">
|
|
17
|
+
<dict>
|
|
18
|
+
<key>UTTypeIdentifier</key>
|
|
19
|
+
<string>com.bugproof.artifact</string>
|
|
20
|
+
<key>UTTypeDescription</key>
|
|
21
|
+
<string>BugProof Bug Artifact</string>
|
|
22
|
+
<key>UTTypeConformsTo</key>
|
|
23
|
+
<array>
|
|
24
|
+
<string>public.data</string>
|
|
25
|
+
</array>
|
|
26
|
+
<key>UTTypeTagSpecification</key>
|
|
27
|
+
<dict>
|
|
28
|
+
<key>com.apple.ostype</key>
|
|
29
|
+
<string>BUGF</string>
|
|
30
|
+
<key>public.filename-extension</key>
|
|
31
|
+
<array>
|
|
32
|
+
<string>bug</string>
|
|
33
|
+
</array>
|
|
34
|
+
<key>public.mime-type</key>
|
|
35
|
+
<string>application/x-bugproof</string>
|
|
36
|
+
</dict>
|
|
37
|
+
</dict>
|
|
38
|
+
</plist>
|
|
39
|
+
EOF
|
|
40
|
+
|
|
41
|
+
# Update LaunchServices database
|
|
42
|
+
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user
|
|
43
|
+
|
|
44
|
+
echo "✓ macOS UTType registered"
|
|
45
|
+
echo ""
|
|
46
|
+
echo "✅ BugProof file association setup complete on macOS!"
|
|
47
|
+
echo ""
|
|
48
|
+
echo "🎯 You can now double-click .bug files to replay them"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Windows Registry Editor Version 5.00
|
|
2
|
+
|
|
3
|
+
; BugProof .bug file association for Windows
|
|
4
|
+
; This script associates .bug files with BugProof CLI and assigns an icon
|
|
5
|
+
|
|
6
|
+
[HKEY_CLASSES_ROOT\.bug]
|
|
7
|
+
@="BugProof.Artifact"
|
|
8
|
+
|
|
9
|
+
[HKEY_CLASSES_ROOT\.bug\ShellNew]
|
|
10
|
+
"FileName"=""
|
|
11
|
+
|
|
12
|
+
[HKEY_CLASSES_ROOT\BugProof.Artifact]
|
|
13
|
+
@="BugProof Bug Artifact"
|
|
14
|
+
"AppUserModelID"="BugProof.CLI"
|
|
15
|
+
|
|
16
|
+
[HKEY_CLASSES_ROOT\BugProof.Artifact\DefaultIcon]
|
|
17
|
+
@="C:\\Program Files\\BugProof\\assets\\icon.ico,0"
|
|
18
|
+
|
|
19
|
+
[HKEY_CLASSES_ROOT\BugProof.Artifact\shell]
|
|
20
|
+
@=""
|
|
21
|
+
|
|
22
|
+
[HKEY_CLASSES_ROOT\BugProof.Artifact\shell\open]
|
|
23
|
+
@="Replay"
|
|
24
|
+
|
|
25
|
+
[HKEY_CLASSES_ROOT\BugProof.Artifact\shell\open\command]
|
|
26
|
+
@="cmd.exe /c \"bugproof replay \"%1\"\""
|
|
27
|
+
|
|
28
|
+
[HKEY_CLASSES_ROOT\BugProof.Artifact\shell\inspect]
|
|
29
|
+
@="Inspect"
|
|
30
|
+
|
|
31
|
+
[HKEY_CLASSES_ROOT\BugProof.Artifact\shell\inspect\command]
|
|
32
|
+
@="cmd.exe /c \"bugproof inspect \"%1\" && pause\""
|
|
33
|
+
|
|
34
|
+
; Add BugProof to PATH via registry (optional, requires admin)
|
|
35
|
+
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
|
|
36
|
+
; Note: User must manually add BugProof bin to PATH or run: npm link
|
|
37
|
+
|
|
38
|
+
; Right-click context menu
|
|
39
|
+
[HKEY_CLASSES_ROOT\*\shell\BugProof Capture]
|
|
40
|
+
@="Capture with BugProof"
|
|
41
|
+
"Icon"="C:\\Program Files\\BugProof\\assets\\icon.ico,0"
|
|
42
|
+
|
|
43
|
+
[HKEY_CLASSES_ROOT\*\shell\BugProof Capture\command]
|
|
44
|
+
@="cmd.exe /c \"bugproof capture -- \"%1\"\""
|