@sema-agent/core 7.33.2 → 7.33.3
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 +9 -0
- package/dist/core/secret-env.js +57 -3
- package/package.json +1 -1
- package/wire-changes/core@7.33.3.json +43 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 7.33.3 — 2026-09-26
|
|
2
|
+
|
|
3
|
+
### Security fix — a credential written into a URL is read as a MODEL could read it: `user:secret/part@host` trips the git-family userinfo screen on KEY and VALUE (#1140; 7.33.2 follow-up; behavior; +0 exports, +0 wire keys) (@server)
|
|
4
|
+
|
|
5
|
+
- **Before.** 7.33.2's userinfo screen read the authority the way git and curl do — it ends at the first `/`, `?` or `#` — so `url.https://alice:secret/part@git.example/.insteadOf` (a password with an unescaped separator) had no userinfo: the KEY cleared its exemption screen, the VALUE row did not fire, and the whole git group reached the host subprocess (server 7.103.0 merge review). 7.32.1 had withheld the group because every KEY fell to the shape rule — a regression relative to the shipped chain.
|
|
6
|
+
- **Now.** One single-pass scanner shared by the KEY exemption and the VALUE credential row: after any `://` (any slash run) the segment up to the first `@` is a userinfo when it has no `/` `?` `#` (RFC reading; a user alone counts, KL-1129b) OR it has a `:` before its first `/` `?` `#` (`user:secret/…@`). A path `@` with no colon before it (`https://git.example/@scope/pkg`) still clears; a URL nested in a path is read on its own; scp forms (`host:/repo@v2.git`, `git@host:path`) never trip. No regex, no backtracking: linear on `://`, `:` and `/` runs.
|
|
7
|
+
- **Who is hurt / compensation.** `https://host:8443/api/@scope/pkg` (a port and a path `@`) is over-dropped and breaks its git group — fail-closed on purpose, KL-1129b; write such a URL without the port or through the repository's config.
|
|
8
|
+
- Pins: `test/backlog1129-git-config-key-family.test.ts` (7.33.3 block: the host-reported KEY / VALUE / `%2F` forms, path-`@`, port over-drop, query colon, nested and second URL, empty userinfo, 4 × 256 KiB linearity).
|
|
9
|
+
|
|
1
10
|
# Changelog
|
|
2
11
|
|
|
3
12
|
## 7.33.2 — 2026-09-26
|
package/dist/core/secret-env.js
CHANGED
|
@@ -15,7 +15,61 @@ const NON_SECRET_ENV_EXACT_NAMES = new Set([
|
|
|
15
15
|
"MAX_BATCH_PREFILL_TOKENS", "MAX_WAITING_TOKENS", "MAX_TOP_N_TOKENS", "RATE_LIMIT_TOKENS",
|
|
16
16
|
"PROMPT_TOKENS", "CONTEXT_TOKENS",
|
|
17
17
|
]);
|
|
18
|
-
|
|
18
|
+
function carriesUrlUserinfo(value) {
|
|
19
|
+
let open = -1;
|
|
20
|
+
let colon = -1;
|
|
21
|
+
let sep = -1;
|
|
22
|
+
let bracket = false;
|
|
23
|
+
let armed = false;
|
|
24
|
+
const isSchemeChar = (ch) => (ch >= 0x61 && ch <= 0x7a) || (ch >= 0x41 && ch <= 0x5a) || (ch >= 0x30 && ch <= 0x39) || ch === 0x2b || ch === 0x2e || ch === 0x2d;
|
|
25
|
+
const qualifies = (at) => open !== -1 && at > open && (sep === -1 || (colon !== -1 && colon < sep));
|
|
26
|
+
for (let i = 0; i < value.length; i++) {
|
|
27
|
+
const c = value.charCodeAt(i);
|
|
28
|
+
if (c === 0x3a && value.charCodeAt(i + 1) === 0x2f && value.charCodeAt(i + 2) === 0x2f && i > 0 && isSchemeChar(value.charCodeAt(i - 1))) {
|
|
29
|
+
if (open !== -1) {
|
|
30
|
+
if (colon === -1 && !bracket)
|
|
31
|
+
colon = i;
|
|
32
|
+
if (sep === -1)
|
|
33
|
+
sep = i + 1;
|
|
34
|
+
if (colon !== -1 && colon < sep)
|
|
35
|
+
armed = true;
|
|
36
|
+
}
|
|
37
|
+
i += 2;
|
|
38
|
+
while (value.charCodeAt(i + 1) === 0x2f)
|
|
39
|
+
i++;
|
|
40
|
+
open = i + 1;
|
|
41
|
+
colon = -1;
|
|
42
|
+
sep = -1;
|
|
43
|
+
bracket = value.charCodeAt(open) === 0x5b;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (open === -1)
|
|
47
|
+
continue;
|
|
48
|
+
if (c === 0x40) {
|
|
49
|
+
if (armed || qualifies(i))
|
|
50
|
+
return true;
|
|
51
|
+
open = -1;
|
|
52
|
+
armed = false;
|
|
53
|
+
bracket = false;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (bracket) {
|
|
57
|
+
if (c === 0x5d)
|
|
58
|
+
bracket = false;
|
|
59
|
+
else if (c === 0x2f || c === 0x3f || c === 0x23) {
|
|
60
|
+
bracket = false;
|
|
61
|
+
if (sep === -1)
|
|
62
|
+
sep = i;
|
|
63
|
+
}
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (colon === -1 && c === 0x3a)
|
|
67
|
+
colon = i;
|
|
68
|
+
if (sep === -1 && (c === 0x2f || c === 0x3f || c === 0x23))
|
|
69
|
+
sep = i;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
19
73
|
const HEADER_LINE_BREAK_RE = /\r\n|\r|\n/;
|
|
20
74
|
const AUTHORIZATION_HEADER_NAME_RE = /^[ \t]*(?:(?:proxy-)?authorization|cookie)[ \t]*:/i;
|
|
21
75
|
const HEADER_CONTENT_RE = /[^ \t\f\v]/;
|
|
@@ -36,13 +90,13 @@ function carriesAuthorizationHeader(value) {
|
|
|
36
90
|
const GIT_PROXY_CONFIG_KEY_RE = /^(?:http(?:\..+)?|remote\..+)\.proxy$/is;
|
|
37
91
|
const PROXY_AUTHORITY_USERINFO_RE = /^(?:[a-z][a-z0-9+.-]*:\/*)?[^/?#@]+@/i;
|
|
38
92
|
const NON_SECRET_ENV_INDEXED_FAMILIES = [
|
|
39
|
-
{ stem: "GIT_CONFIG_KEY", valueClears: (value) => !
|
|
93
|
+
{ stem: "GIT_CONFIG_KEY", valueClears: (value) => !carriesUrlUserinfo(value) },
|
|
40
94
|
];
|
|
41
95
|
const SECRET_ENV_INDEXED_FAMILIES = [
|
|
42
96
|
{
|
|
43
97
|
stem: "GIT_CONFIG_VALUE",
|
|
44
98
|
credentialWhen: (value, group) => {
|
|
45
|
-
if (carriesAuthorizationHeader(value) ||
|
|
99
|
+
if (carriesAuthorizationHeader(value) || carriesUrlUserinfo(value))
|
|
46
100
|
return true;
|
|
47
101
|
const key = group.sibling("GIT_CONFIG_KEY");
|
|
48
102
|
return key !== undefined && GIT_PROXY_CONFIG_KEY_RE.test(key) && PROXY_AUTHORITY_USERINFO_RE.test(value);
|
package/package.json
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repo": "core",
|
|
3
|
+
"version": "7.33.3",
|
|
4
|
+
"from": "aa8e4a621a350bcadeff763fdec25d97ae96370f",
|
|
5
|
+
"to": "v7.33.3",
|
|
6
|
+
"added": [],
|
|
7
|
+
"removed": [],
|
|
8
|
+
"changed": [],
|
|
9
|
+
"narrowed": [],
|
|
10
|
+
"closedSetMembers": [],
|
|
11
|
+
"closedSetsUnreadable": [],
|
|
12
|
+
"typeKeys": [],
|
|
13
|
+
"typeKeysUnreadableArms": [],
|
|
14
|
+
"typeKeysFlattenedCount": 217,
|
|
15
|
+
"declarationMoves": [],
|
|
16
|
+
"mintMoves": [],
|
|
17
|
+
"criteriaObserves": [
|
|
18
|
+
{
|
|
19
|
+
"kind": "typeMember",
|
|
20
|
+
"name": "SecretEnvFinding.key",
|
|
21
|
+
"assertions": [
|
|
22
|
+
"G1.a"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"kind": "typeMember",
|
|
27
|
+
"name": "SecretEnvFinding.kind",
|
|
28
|
+
"assertions": [
|
|
29
|
+
"G1.a",
|
|
30
|
+
"G1.b"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"consumersHint": {
|
|
35
|
+
"cli": [],
|
|
36
|
+
"server": [],
|
|
37
|
+
"sdk": [],
|
|
38
|
+
"note": "scanned cli@4e593722 server@bac45dd2 sdk@4031f42 — a name listed is MENTIONED there today, which is evidence of consumption, not proof of it"
|
|
39
|
+
},
|
|
40
|
+
"breakingCount": 0,
|
|
41
|
+
"breakingItems": [],
|
|
42
|
+
"toResolvedAt": "c5da6d6b48d9ad047bb04fea9b494aaa1f87ec2d"
|
|
43
|
+
}
|