blun-king-cli 9.1.571 → 9.1.572
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
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 9.1.572
|
|
4
|
+
|
|
5
|
+
- Research evidence rejects source URLs containing recognized credential parameter
|
|
6
|
+
names in queries or parameter-shaped fragments, including nested names and
|
|
7
|
+
fragment routes. Rejection applies to failed sources as well as usable sources.
|
|
8
|
+
- Previously saved reports with these URLs are withheld during recall with the
|
|
9
|
+
existing `partial` / `report-invalid` result. Original snapshots are not modified
|
|
10
|
+
or deleted, and source addresses are never silently stripped or rewritten.
|
|
11
|
+
- Ordinary documentation queries and anchors retain their exact bytes. This is
|
|
12
|
+
a credential-name boundary, not general secret detection or a history cleanup.
|
|
13
|
+
|
|
14
|
+
|
|
3
15
|
## 9.1.571
|
|
4
16
|
|
|
5
17
|
- Bind Telegram queue ranges to their owning session. A new session no longer automatically consumes work left pending by an older session; resuming a known session restores only its own pending ranges.
|
package/package.json
CHANGED
|
@@ -80,3 +80,25 @@ unread global corpus. `limited:true` also flags result-count or output truncatio
|
|
|
80
80
|
continuation is for the read budget, not pagination of every lexical hit. Narrow
|
|
81
81
|
the query when necessary. Unavailable or partial results must remain visible as
|
|
82
82
|
limitations; they do not prevent ordinary authorized research.
|
|
83
|
+
|
|
84
|
+
## Source URL Credential Boundary
|
|
85
|
+
|
|
86
|
+
All source statuses reject URL userinfo and recognized credential parameter names
|
|
87
|
+
in queries and parameter-shaped fragments, including fragment routes. Names are
|
|
88
|
+
decoded with URLSearchParams, compared case-insensitively, and checked within
|
|
89
|
+
bracket/dot nesting. Examples include access_token, refresh_token, api_key,
|
|
90
|
+
client_secret, authorization, session_id and signed-URL credential/signature fields.
|
|
91
|
+
|
|
92
|
+
The source address is never silently stripped or rewritten. Normal queries such
|
|
93
|
+
as `q=access_token`, bare `key` / `code` parameters, and ordinary documentation
|
|
94
|
+
anchors are not classified as credentials. This is not a general secret detector:
|
|
95
|
+
custom keys, opaque path values, nested encoded URLs and report text still require
|
|
96
|
+
the explicit review described above. Passing validation does not prove public
|
|
97
|
+
reachability, permission to share, or absence of secrets.
|
|
98
|
+
|
|
99
|
+
New invalid reports return `saved:false` / `report-invalid` before collection
|
|
100
|
+
creation. Reading an older invalid report withholds that snapshot and reports
|
|
101
|
+
`partial` / `report-invalid`, while leaving its original bytes on disk. Other valid
|
|
102
|
+
snapshots may still be returned. This is not automatic cleanup or credential
|
|
103
|
+
revocation. Do not remove history or rewrite URLs to make validation pass.
|
|
104
|
+
|
|
@@ -5,6 +5,25 @@ const ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,99}$/;
|
|
|
5
5
|
const HASH = /^[a-f0-9]{64}$/;
|
|
6
6
|
const STATES = new Set(['usable', 'failed', 'challenge', 'irrelevant', 'stale']);
|
|
7
7
|
const VERDICTS = new Set(['supported', 'unsupported', 'uncertain']);
|
|
8
|
+
const CREDENTIAL_PARAMETER = /^(?:(?:access|refresh|id|oauth)[_-]?token|token|api[_-]?key|client[_-]?secret|password|passwd|authorization|bearer|jwt|session[_-]?(?:id|token)|secret|signature|sig|x-(?:amz|goog)-(?:signature|credential|security-token))$/i;
|
|
9
|
+
function validateSourceUrl(value) {
|
|
10
|
+
let url;
|
|
11
|
+
try { url = new URL(value); } catch { assert.fail('source URL'); }
|
|
12
|
+
assert(['http:', 'https:'].includes(url.protocol) && !url.username && !url.password, 'source URL');
|
|
13
|
+
const parameters = [url.searchParams];
|
|
14
|
+
// OAuth-style fragments can hold credentials; ordinary documentation anchors stay intact.
|
|
15
|
+
const fragment = url.hash.slice(1);
|
|
16
|
+
if (fragment.includes('=')) {
|
|
17
|
+
parameters.push(new URLSearchParams(fragment));
|
|
18
|
+
const queryStart = fragment.indexOf('?');
|
|
19
|
+
if (queryStart !== -1) parameters.push(new URLSearchParams(fragment.slice(queryStart + 1)));
|
|
20
|
+
}
|
|
21
|
+
for (const params of parameters) {
|
|
22
|
+
for (const key of params.keys()) {
|
|
23
|
+
assert(!key.split(/[\[\].]+/).some(part => CREDENTIAL_PARAMETER.test(part)), 'source URL');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
8
27
|
function boundedArray(value, maximum, label) {
|
|
9
28
|
assert(Array.isArray(value) && value.length <= maximum, label);
|
|
10
29
|
return value;
|
|
@@ -38,8 +57,7 @@ function score(report) {
|
|
|
38
57
|
const sourceMap = new Map();
|
|
39
58
|
const sourceCounts = Object.fromEntries([...STATES].map(status => [status, 0]));
|
|
40
59
|
for (const source of sources) {
|
|
41
|
-
|
|
42
|
-
assert(['http:', 'https:'].includes(url.protocol) && !url.username && !url.password, 'source URL');
|
|
60
|
+
validateSourceUrl(source.url);
|
|
43
61
|
assert(STATES.has(source.status), 'source status');
|
|
44
62
|
assert(source.retrievedAt === null || timestamp(source.retrievedAt), 'source time');
|
|
45
63
|
assert(source.contentSha256 === null || HASH.test(source.contentSha256), 'source hash');
|