@nuetzliches/croniq-runner 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/README.md +25 -2
- package/dist/client.d.ts +61 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +87 -0
- package/dist/client.js.map +1 -1
- package/dist/context.d.ts +9 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -1
- package/dist/dispatcher.d.ts +1 -1
- package/dist/dispatcher.d.ts.map +1 -1
- package/dist/dispatcher.js +39 -8
- package/dist/dispatcher.js.map +1 -1
- package/dist/duration.d.ts +6 -0
- package/dist/duration.d.ts.map +1 -1
- package/dist/duration.js +11 -0
- package/dist/duration.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/log-writer.d.ts +1 -1
- package/dist/log-writer.d.ts.map +1 -1
- package/dist/log-writer.js +17 -3
- package/dist/log-writer.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +10 -2
- package/dist/logger.js.map +1 -1
- package/dist/options.d.ts +42 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +21 -1
- package/dist/options.js.map +1 -1
- package/dist/protocol.d.ts +5 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +145 -6
- package/dist/runner.js.map +1 -1
- package/dist/sanitize.d.ts +82 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +157 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/security.d.ts +19 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +83 -0
- package/dist/security.js.map +1 -0
- package/dist/trigger.d.ts +21 -1
- package/dist/trigger.d.ts.map +1 -1
- package/dist/trigger.js +4 -0
- package/dist/trigger.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hygiene for server-supplied strings.
|
|
3
|
+
*
|
|
4
|
+
* `job_key` and `execution_id` arrive from the Croniq server and are echoed
|
|
5
|
+
* into logs and telemetry. The threat actor is a malicious or compromised
|
|
6
|
+
* server — but not only: in a multi-tenant deployment anyone who can name a
|
|
7
|
+
* job key in the Croniqfile controls a string that round-trips to every
|
|
8
|
+
* runner unchanged. A value carrying CRLF forges log records; one carrying
|
|
9
|
+
* ANSI escapes repaints the operator's terminal.
|
|
10
|
+
*
|
|
11
|
+
* Two layers defend against that:
|
|
12
|
+
*
|
|
13
|
+
* 1. {@link assertSafeAssignmentIdentifiers} rejects an assignment whose
|
|
14
|
+
* identifiers fall outside the shape Croniq itself defines, so hostile
|
|
15
|
+
* values never enter the SDK.
|
|
16
|
+
* 2. {@link escapeControlChars} escapes anything a terminal would interpret,
|
|
17
|
+
* applied wherever this SDK renders text itself (see `logger.ts`).
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Maximum accepted `job_key` length, counted in Unicode scalar values.
|
|
21
|
+
*
|
|
22
|
+
* The server stores job keys in an unbounded `TEXT` column
|
|
23
|
+
* (`crates/croniq-store/src/migrations/001_initial.sql`), so this bound is the
|
|
24
|
+
* SDK's own. 256 is far above any plausible `namespace:name:variant` while
|
|
25
|
+
* still bounding what a single log line can be made to hold.
|
|
26
|
+
*/
|
|
27
|
+
export declare const MAX_JOB_KEY_LENGTH = 256;
|
|
28
|
+
/**
|
|
29
|
+
* Maximum accepted `execution_id` length. The server always emits a v4 UUID
|
|
30
|
+
* (36 characters); 64 leaves room for the shorter opaque ids used by mock
|
|
31
|
+
* servers and the conformance suite.
|
|
32
|
+
*/
|
|
33
|
+
export declare const MAX_EXECUTION_ID_LENGTH = 64;
|
|
34
|
+
/**
|
|
35
|
+
* Escape every character a terminal interprets rather than prints: the C0
|
|
36
|
+
* range (including ESC, `0x1B`, which introduces every ANSI sequence), DEL,
|
|
37
|
+
* and the C1 range.
|
|
38
|
+
*
|
|
39
|
+
* This mirrors what Go's `slog` handlers do for attribute values, and is
|
|
40
|
+
* applied here because this SDK's console logger writes the message itself.
|
|
41
|
+
* Field maps do not need it — they are rendered with `JSON.stringify`, which
|
|
42
|
+
* already escapes these.
|
|
43
|
+
*/
|
|
44
|
+
export declare function escapeControlChars(value: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Render a rejected value for a diagnostic: escaped so it cannot forge a
|
|
47
|
+
* record, and truncated so an over-long value cannot flood the log either.
|
|
48
|
+
*/
|
|
49
|
+
export declare function previewForLog(value: unknown, maxLength?: number): string;
|
|
50
|
+
/**
|
|
51
|
+
* True when `value` is a job key this runner is willing to act on: non-empty,
|
|
52
|
+
* within {@link MAX_JOB_KEY_LENGTH} scalar values, and free of control
|
|
53
|
+
* characters. Iteration is over scalar values (`for…of`), not UTF-16 code
|
|
54
|
+
* units, so an astral character counts once and a surrogate pair is never
|
|
55
|
+
* inspected half at a time.
|
|
56
|
+
*/
|
|
57
|
+
export declare function isSafeJobKey(value: unknown): value is string;
|
|
58
|
+
/** True when `value` is an execution id this runner is willing to act on. */
|
|
59
|
+
export declare function isSafeExecutionId(value: unknown): value is string;
|
|
60
|
+
/** The identifier that makes a work assignment unacceptable. */
|
|
61
|
+
export type RejectedField = 'execution_id' | 'job_key';
|
|
62
|
+
/**
|
|
63
|
+
* Names the identifier that makes a work assignment unacceptable, or
|
|
64
|
+
* `undefined` when both pass. Only the field name is returned — the offending
|
|
65
|
+
* value is reported separately, escaped, so the diagnostic cannot itself become
|
|
66
|
+
* the injection vector.
|
|
67
|
+
*
|
|
68
|
+
* The two outcomes are handled differently by the caller, and the order here
|
|
69
|
+
* is what makes that possible. An unsafe `execution_id` leaves nothing to
|
|
70
|
+
* address the server with, so the assignment is dropped silently. An unsafe
|
|
71
|
+
* `job_key` with a *valid* `execution_id` can still be acked as a failure, so
|
|
72
|
+
* the operator gets a dead-lettered execution naming the problem instead of a
|
|
73
|
+
* silent requeue loop.
|
|
74
|
+
*/
|
|
75
|
+
export declare function rejectAssignmentReason(executionId: unknown, jobKey: unknown): RejectedField | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* The `error` string acked for an assignment rejected on `job_key`. Names the
|
|
78
|
+
* field and shows the offending value escaped, so the dead-letter row explains
|
|
79
|
+
* itself without carrying a live payload.
|
|
80
|
+
*/
|
|
81
|
+
export declare function rejectionAckError(field: RejectedField, value: unknown): string;
|
|
82
|
+
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAkC1C;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAcxD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,SAAM,GAAG,MAAM,CASrE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAQ5D;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAOjE;AAED,gEAAgE;AAChE,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,SAAS,CAAC;AAEvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,OAAO,GACd,aAAa,GAAG,SAAS,CAI3B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAE9E"}
|
package/dist/sanitize.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hygiene for server-supplied strings.
|
|
3
|
+
*
|
|
4
|
+
* `job_key` and `execution_id` arrive from the Croniq server and are echoed
|
|
5
|
+
* into logs and telemetry. The threat actor is a malicious or compromised
|
|
6
|
+
* server — but not only: in a multi-tenant deployment anyone who can name a
|
|
7
|
+
* job key in the Croniqfile controls a string that round-trips to every
|
|
8
|
+
* runner unchanged. A value carrying CRLF forges log records; one carrying
|
|
9
|
+
* ANSI escapes repaints the operator's terminal.
|
|
10
|
+
*
|
|
11
|
+
* Two layers defend against that:
|
|
12
|
+
*
|
|
13
|
+
* 1. {@link assertSafeAssignmentIdentifiers} rejects an assignment whose
|
|
14
|
+
* identifiers fall outside the shape Croniq itself defines, so hostile
|
|
15
|
+
* values never enter the SDK.
|
|
16
|
+
* 2. {@link escapeControlChars} escapes anything a terminal would interpret,
|
|
17
|
+
* applied wherever this SDK renders text itself (see `logger.ts`).
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Maximum accepted `job_key` length, counted in Unicode scalar values.
|
|
21
|
+
*
|
|
22
|
+
* The server stores job keys in an unbounded `TEXT` column
|
|
23
|
+
* (`crates/croniq-store/src/migrations/001_initial.sql`), so this bound is the
|
|
24
|
+
* SDK's own. 256 is far above any plausible `namespace:name:variant` while
|
|
25
|
+
* still bounding what a single log line can be made to hold.
|
|
26
|
+
*/
|
|
27
|
+
export const MAX_JOB_KEY_LENGTH = 256;
|
|
28
|
+
/**
|
|
29
|
+
* Maximum accepted `execution_id` length. The server always emits a v4 UUID
|
|
30
|
+
* (36 characters); 64 leaves room for the shorter opaque ids used by mock
|
|
31
|
+
* servers and the conformance suite.
|
|
32
|
+
*/
|
|
33
|
+
export const MAX_EXECUTION_ID_LENGTH = 64;
|
|
34
|
+
/**
|
|
35
|
+
* Whether `codePoint` is one a terminal interprets rather than prints: the C0
|
|
36
|
+
* range (`U+0000`–`U+001F`, covering NUL, CR, LF and the ESC that introduces
|
|
37
|
+
* every ANSI sequence), DEL (`U+007F`), and the C1 range
|
|
38
|
+
* (`U+0080`–`U+009F`).
|
|
39
|
+
*
|
|
40
|
+
* This is the rule for `job_key`, and it is a *denylist* on purpose. An
|
|
41
|
+
* allowlist — say, the character set `Lexer::is_ident_char` accepts for an
|
|
42
|
+
* unquoted key in `crates/croniq-config/src/lexer.rs` — would reject keys a
|
|
43
|
+
* legitimate server can issue: `parse_job_key` (`parser.rs:687-717`) also
|
|
44
|
+
* accepts a `QuotedString` and then enforces only the "two or three
|
|
45
|
+
* colon-separated parts" rule, so `job "billing:monthly invoice" { … }` is
|
|
46
|
+
* legal DSL today, and `POST /v1/jobs` constrains the key not at all. Dropping
|
|
47
|
+
* such an assignment would strand a valid configuration.
|
|
48
|
+
*
|
|
49
|
+
* Rejecting the control classes instead blocks precisely the log-forgery and
|
|
50
|
+
* ANSI-injection payloads without touching anything legitimate. An interior
|
|
51
|
+
* space is accepted; so is any other printable scalar value, in any script.
|
|
52
|
+
*/
|
|
53
|
+
function isControlScalar(codePoint) {
|
|
54
|
+
return codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Accepted `execution_id` shape. The server generates these as v4 UUIDs
|
|
58
|
+
* (`Uuid::new_v4()`), which is a strict subset of this pattern; the pattern is
|
|
59
|
+
* kept slightly wider so opaque ids from mock servers and older builds still
|
|
60
|
+
* round-trip. What it excludes is what matters: control characters, ESC,
|
|
61
|
+
* whitespace, and anything else a terminal or log parser reacts to.
|
|
62
|
+
*/
|
|
63
|
+
const EXECUTION_ID_PATTERN = /^[A-Za-z0-9._:-]+$/;
|
|
64
|
+
/**
|
|
65
|
+
* Escape every character a terminal interprets rather than prints: the C0
|
|
66
|
+
* range (including ESC, `0x1B`, which introduces every ANSI sequence), DEL,
|
|
67
|
+
* and the C1 range.
|
|
68
|
+
*
|
|
69
|
+
* This mirrors what Go's `slog` handlers do for attribute values, and is
|
|
70
|
+
* applied here because this SDK's console logger writes the message itself.
|
|
71
|
+
* Field maps do not need it — they are rendered with `JSON.stringify`, which
|
|
72
|
+
* already escapes these.
|
|
73
|
+
*/
|
|
74
|
+
export function escapeControlChars(value) {
|
|
75
|
+
// eslint-disable-next-line no-control-regex
|
|
76
|
+
return value.replace(/[\u0000-\u001F\u007F-\u009F]/g, (ch) => {
|
|
77
|
+
switch (ch) {
|
|
78
|
+
case '\n':
|
|
79
|
+
return '\\n';
|
|
80
|
+
case '\r':
|
|
81
|
+
return '\\r';
|
|
82
|
+
case '\t':
|
|
83
|
+
return '\\t';
|
|
84
|
+
default:
|
|
85
|
+
return `\\u${ch.charCodeAt(0).toString(16).padStart(4, '0')}`;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Render a rejected value for a diagnostic: escaped so it cannot forge a
|
|
91
|
+
* record, and truncated so an over-long value cannot flood the log either.
|
|
92
|
+
*/
|
|
93
|
+
export function previewForLog(value, maxLength = 120) {
|
|
94
|
+
const text = typeof value === 'string' ? value : String(value);
|
|
95
|
+
// Slice by scalar values, not UTF-16 code units, so truncation cannot leave
|
|
96
|
+
// a lone surrogate behind.
|
|
97
|
+
const scalars = [...text];
|
|
98
|
+
const clipped = scalars.length > maxLength
|
|
99
|
+
? `${scalars.slice(0, maxLength).join('')}…`
|
|
100
|
+
: text;
|
|
101
|
+
return escapeControlChars(clipped);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* True when `value` is a job key this runner is willing to act on: non-empty,
|
|
105
|
+
* within {@link MAX_JOB_KEY_LENGTH} scalar values, and free of control
|
|
106
|
+
* characters. Iteration is over scalar values (`for…of`), not UTF-16 code
|
|
107
|
+
* units, so an astral character counts once and a surrogate pair is never
|
|
108
|
+
* inspected half at a time.
|
|
109
|
+
*/
|
|
110
|
+
export function isSafeJobKey(value) {
|
|
111
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
112
|
+
return false;
|
|
113
|
+
let scalars = 0;
|
|
114
|
+
for (const ch of value) {
|
|
115
|
+
if (++scalars > MAX_JOB_KEY_LENGTH)
|
|
116
|
+
return false;
|
|
117
|
+
if (isControlScalar(ch.codePointAt(0)))
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
/** True when `value` is an execution id this runner is willing to act on. */
|
|
123
|
+
export function isSafeExecutionId(value) {
|
|
124
|
+
return (typeof value === 'string' &&
|
|
125
|
+
value.length > 0 &&
|
|
126
|
+
value.length <= MAX_EXECUTION_ID_LENGTH &&
|
|
127
|
+
EXECUTION_ID_PATTERN.test(value));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Names the identifier that makes a work assignment unacceptable, or
|
|
131
|
+
* `undefined` when both pass. Only the field name is returned — the offending
|
|
132
|
+
* value is reported separately, escaped, so the diagnostic cannot itself become
|
|
133
|
+
* the injection vector.
|
|
134
|
+
*
|
|
135
|
+
* The two outcomes are handled differently by the caller, and the order here
|
|
136
|
+
* is what makes that possible. An unsafe `execution_id` leaves nothing to
|
|
137
|
+
* address the server with, so the assignment is dropped silently. An unsafe
|
|
138
|
+
* `job_key` with a *valid* `execution_id` can still be acked as a failure, so
|
|
139
|
+
* the operator gets a dead-lettered execution naming the problem instead of a
|
|
140
|
+
* silent requeue loop.
|
|
141
|
+
*/
|
|
142
|
+
export function rejectAssignmentReason(executionId, jobKey) {
|
|
143
|
+
if (!isSafeExecutionId(executionId))
|
|
144
|
+
return 'execution_id';
|
|
145
|
+
if (!isSafeJobKey(jobKey))
|
|
146
|
+
return 'job_key';
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The `error` string acked for an assignment rejected on `job_key`. Names the
|
|
151
|
+
* field and shows the offending value escaped, so the dead-letter row explains
|
|
152
|
+
* itself without carrying a live payload.
|
|
153
|
+
*/
|
|
154
|
+
export function rejectionAckError(field, value) {
|
|
155
|
+
return `rejected by runner: unsafe ${field} ${previewForLog(value)}`;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Logger } from './logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* `true` for the loopback hosts the SDK considers safe over cleartext HTTP:
|
|
4
|
+
* `localhost`, anything in `127.0.0.0/8`, and IPv6 `::1` (in the bracketed
|
|
5
|
+
* `[::1]` form the WHATWG URL parser produces).
|
|
6
|
+
*/
|
|
7
|
+
export declare function isLoopbackHostname(hostname: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Throws a {@link TypeError} when `serverUrl` is a non-loopback `http://` URL
|
|
10
|
+
* and `allowInsecureHttp` is not set. When the opt-in IS set for such a URL,
|
|
11
|
+
* emits exactly one loud warning naming the risk.
|
|
12
|
+
*
|
|
13
|
+
* @param serverUrl Configured base URL (already known to be parseable).
|
|
14
|
+
* @param allowInsecureHttp Caller's explicit opt-in to cleartext HTTP.
|
|
15
|
+
* @param optionPath Dotted option path, used to make the error actionable.
|
|
16
|
+
* @param logger Sink for the opt-in warning.
|
|
17
|
+
*/
|
|
18
|
+
export declare function assertSecureServerUrl(serverUrl: string, allowInsecureHttp: boolean, optionPath: string, logger: Logger): void;
|
|
19
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,OAAO,EAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,IAAI,CA+BN"}
|
package/dist/security.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Transport-security checks applied to the configured base URL.
|
|
2
|
+
//
|
|
3
|
+
// Both the runner and the producer-side trigger client attach the credential
|
|
4
|
+
// as an `Authorization` header on every request. Over `http://` that key
|
|
5
|
+
// travels in cleartext — and undici honours `HTTP_PROXY` by default, so it may
|
|
6
|
+
// traverse an intermediary in the clear as well.
|
|
7
|
+
//
|
|
8
|
+
// The rule (identical in the .NET, Java, Python and Go SDKs): `https://` is
|
|
9
|
+
// always fine, `http://` is fine for a loopback host — that is the
|
|
10
|
+
// `http://localhost:4000` quickstart path — and `http://` against any other
|
|
11
|
+
// host is refused unless the caller explicitly opts in with
|
|
12
|
+
// `allowInsecureHttp: true`. Enforcement happens at options-resolution /
|
|
13
|
+
// construction time so a misconfiguration fails fast rather than on first poll.
|
|
14
|
+
//
|
|
15
|
+
// Kept regex-free on purpose, matching `url.ts`: CodeQL's "polynomial regex"
|
|
16
|
+
// heuristic flags even linear patterns over library-controlled input.
|
|
17
|
+
/**
|
|
18
|
+
* `true` for the loopback hosts the SDK considers safe over cleartext HTTP:
|
|
19
|
+
* `localhost`, anything in `127.0.0.0/8`, and IPv6 `::1` (in the bracketed
|
|
20
|
+
* `[::1]` form the WHATWG URL parser produces).
|
|
21
|
+
*/
|
|
22
|
+
export function isLoopbackHostname(hostname) {
|
|
23
|
+
const host = hostname.toLowerCase();
|
|
24
|
+
if (host === 'localhost')
|
|
25
|
+
return true;
|
|
26
|
+
if (host.startsWith('[') && host.endsWith(']')) {
|
|
27
|
+
return host.slice(1, -1) === '::1';
|
|
28
|
+
}
|
|
29
|
+
if (host === '::1')
|
|
30
|
+
return true;
|
|
31
|
+
return isIpv4Loopback(host);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Throws a {@link TypeError} when `serverUrl` is a non-loopback `http://` URL
|
|
35
|
+
* and `allowInsecureHttp` is not set. When the opt-in IS set for such a URL,
|
|
36
|
+
* emits exactly one loud warning naming the risk.
|
|
37
|
+
*
|
|
38
|
+
* @param serverUrl Configured base URL (already known to be parseable).
|
|
39
|
+
* @param allowInsecureHttp Caller's explicit opt-in to cleartext HTTP.
|
|
40
|
+
* @param optionPath Dotted option path, used to make the error actionable.
|
|
41
|
+
* @param logger Sink for the opt-in warning.
|
|
42
|
+
*/
|
|
43
|
+
export function assertSecureServerUrl(serverUrl, allowInsecureHttp, optionPath, logger) {
|
|
44
|
+
const parsed = new URL(serverUrl);
|
|
45
|
+
const protocol = parsed.protocol.toLowerCase();
|
|
46
|
+
if (protocol === 'https:')
|
|
47
|
+
return;
|
|
48
|
+
if (protocol !== 'http:') {
|
|
49
|
+
throw new TypeError(`${optionPath} "${serverUrl}" has unsupported scheme "${parsed.protocol}": ` +
|
|
50
|
+
'use https:// (or http:// for a loopback host)');
|
|
51
|
+
}
|
|
52
|
+
if (isLoopbackHostname(parsed.hostname))
|
|
53
|
+
return;
|
|
54
|
+
if (!allowInsecureHttp) {
|
|
55
|
+
throw new TypeError(`${optionPath} "${serverUrl}" uses cleartext http:// with the non-loopback host ` +
|
|
56
|
+
`"${parsed.hostname}": the API key would be sent in the clear on every request, ` +
|
|
57
|
+
'and through any configured HTTP proxy. Use https://, or set ' +
|
|
58
|
+
'allowInsecureHttp: true to accept that risk explicitly.');
|
|
59
|
+
}
|
|
60
|
+
logger.warn(`SECURITY: Croniq is configured against the cleartext URL "${serverUrl}" with ` +
|
|
61
|
+
'allowInsecureHttp: true. The API key is transmitted in cleartext on every request ' +
|
|
62
|
+
'and is readable by anyone on the network path (including HTTP proxies). ' +
|
|
63
|
+
'Use https:// in production.', { server_url: serverUrl });
|
|
64
|
+
}
|
|
65
|
+
/** `true` for a dotted-quad IPv4 literal inside `127.0.0.0/8`. */
|
|
66
|
+
function isIpv4Loopback(host) {
|
|
67
|
+
const parts = host.split('.');
|
|
68
|
+
if (parts.length !== 4)
|
|
69
|
+
return false;
|
|
70
|
+
for (const part of parts) {
|
|
71
|
+
if (part.length === 0 || part.length > 3)
|
|
72
|
+
return false;
|
|
73
|
+
for (let i = 0; i < part.length; i++) {
|
|
74
|
+
const code = part.charCodeAt(i);
|
|
75
|
+
if (code < 48 /* '0' */ || code > 57 /* '9' */)
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if (Number(part) > 255)
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return Number(parts[0]) === 127;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,EAAE;AACF,6EAA6E;AAC7E,yEAAyE;AACzE,+EAA+E;AAC/E,iDAAiD;AACjD,EAAE;AACF,4EAA4E;AAC5E,mEAAmE;AACnE,4EAA4E;AAC5E,4DAA4D;AAC5D,yEAAyE;AACzE,gFAAgF;AAChF,EAAE;AACF,6EAA6E;AAC7E,sEAAsE;AAItE;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC;IACrC,CAAC;IACD,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CACnC,SAAiB,EACjB,iBAA0B,EAC1B,UAAkB,EAClB,MAAc;IAEd,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAE/C,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO;IAElC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,SAAS,CACjB,GAAG,UAAU,KAAK,SAAS,6BAA6B,MAAM,CAAC,QAAQ,KAAK;YAC1E,+CAA+C,CAClD,CAAC;IACJ,CAAC;IAED,IAAI,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO;IAEhD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CACjB,GAAG,UAAU,KAAK,SAAS,sDAAsD;YAC/E,IAAI,MAAM,CAAC,QAAQ,8DAA8D;YACjF,8DAA8D;YAC9D,yDAAyD,CAC5D,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,IAAI,CACT,6DAA6D,SAAS,SAAS;QAC7E,oFAAoF;QACpF,0EAA0E;QAC1E,6BAA6B,EAC/B,EAAE,UAAU,EAAE,SAAS,EAAE,CAC1B,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,IAAI,GAAG,EAAE,CAAC,SAAS,IAAI,IAAI,GAAG,EAAE,CAAC,SAAS;gBAAE,OAAO,KAAK,CAAC;QAC/D,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG;YAAE,OAAO,KAAK,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;AAClC,CAAC"}
|
package/dist/trigger.d.ts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import { HttpError } from './client.js';
|
|
2
|
+
import type { Logger } from './logger.js';
|
|
2
3
|
/** Options for {@link CroniqTriggerClient} / {@link createTriggerClient}. */
|
|
3
4
|
export interface CroniqTriggerClientOptions {
|
|
4
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Base URL of the Croniq server, e.g. `http://localhost:4000`.
|
|
7
|
+
*
|
|
8
|
+
* `https://` is required unless the host is loopback (`localhost`,
|
|
9
|
+
* `127.0.0.0/8`, `::1`) — the trigger credential rides along on every request
|
|
10
|
+
* and would otherwise travel in cleartext. See {@link allowInsecureHttp}.
|
|
11
|
+
*/
|
|
5
12
|
serverUrl: string;
|
|
13
|
+
/**
|
|
14
|
+
* Opt in to a cleartext `http://` {@link serverUrl} on a non-loopback host.
|
|
15
|
+
*
|
|
16
|
+
* Off by default: without it the constructor throws. With it, the client
|
|
17
|
+
* still emits one loud warning — the credential then travels in cleartext on
|
|
18
|
+
* every trigger call. Default `false`.
|
|
19
|
+
*/
|
|
20
|
+
allowInsecureHttp?: boolean | undefined;
|
|
6
21
|
/**
|
|
7
22
|
* API key for `Authorization: ApiKey {key}`. Takes precedence over
|
|
8
23
|
* {@link bearerToken} when both are set. Needs the `jobs:trigger` (or
|
|
@@ -15,6 +30,11 @@ export interface CroniqTriggerClientOptions {
|
|
|
15
30
|
requestTimeoutMs?: number | undefined;
|
|
16
31
|
/** Custom `fetch` implementation. Defaults to the global `fetch`. */
|
|
17
32
|
fetchImpl?: typeof fetch | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Sink for SDK-level diagnostics (currently the insecure-transport warning).
|
|
35
|
+
* Defaults to a console logger that emits warn/error only.
|
|
36
|
+
*/
|
|
37
|
+
logger?: Logger | undefined;
|
|
18
38
|
}
|
|
19
39
|
/** Optional arguments for a single {@link CroniqTriggerClient.trigger} call. */
|
|
20
40
|
export interface TriggerParams {
|
package/dist/trigger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../src/trigger.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../src/trigger.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAM1C,6EAA6E;AAC7E,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAExC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEtC,qEAAqE;IACrE,SAAS,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;IAErC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,uDAAuD;IACvD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IAEf;;;;;OAKG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;aAI7B,YAAY,CAAC,EAAE,MAAM;gBAFrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACI,YAAY,CAAC,EAAE,MAAM,YAAA;CAKxC;AAKD;;;;;;GAMG;AACH,qBAAa,mBAAmB;;gBAOlB,IAAI,EAAE,0BAA0B;IAwB5C;;;;;;;;;OASG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;CAoElF;AAED,oDAAoD;AACpD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,mBAAmB,CAEzF"}
|
package/dist/trigger.js
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
import { HttpError } from './client.js';
|
|
10
10
|
import { AbortError } from './deferred.js';
|
|
11
11
|
import { composeSignals, isAbortLikeError } from './http.js';
|
|
12
|
+
import { consoleLogger } from './logger.js';
|
|
13
|
+
import { assertSecureServerUrl } from './security.js';
|
|
12
14
|
import { trimTrailingSlashes } from './url.js';
|
|
13
15
|
/**
|
|
14
16
|
* Thrown when `POST /v1/trigger` is rejected with `429 Too Many Requests`
|
|
@@ -51,6 +53,8 @@ export class CroniqTriggerClient {
|
|
|
51
53
|
catch {
|
|
52
54
|
throw new TypeError(`CroniqTriggerClientOptions.serverUrl is not a valid URL: ${opts.serverUrl}`);
|
|
53
55
|
}
|
|
56
|
+
// Fail fast on a cleartext base URL that would leak the credential (#440).
|
|
57
|
+
assertSecureServerUrl(opts.serverUrl, opts.allowInsecureHttp ?? false, 'CroniqTriggerClientOptions.serverUrl', opts.logger ?? consoleLogger('warn'));
|
|
54
58
|
this.#baseUrl = trimTrailingSlashes(opts.serverUrl);
|
|
55
59
|
this.#apiKey = opts.apiKey;
|
|
56
60
|
this.#bearerToken = opts.bearerToken;
|
package/dist/trigger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger.js","sourceRoot":"","sources":["../src/trigger.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,+EAA+E;AAC/E,uEAAuE;AACvE,0EAA0E;AAC1E,+EAA+E;AAC/E,wEAAwE;AACxE,8CAA8C;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"trigger.js","sourceRoot":"","sources":["../src/trigger.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED