@aborruso/ckan-mcp-server 0.4.119 → 0.4.120
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/LOG.md +51 -0
- package/dist/index.js +8 -3
- package/package.json +1 -1
package/LOG.md
CHANGED
|
@@ -1,7 +1,54 @@
|
|
|
1
1
|
# LOG
|
|
2
2
|
|
|
3
|
+
## 2026-09-05
|
|
4
|
+
|
|
5
|
+
### v0.4.120 - SSRF hardening release + dependency audit
|
|
6
|
+
|
|
7
|
+
Releases PR #531 (env-proxy refusal, multicast/reserved/site-local ranges, see 2026-09-04 entry). Also:
|
|
8
|
+
|
|
9
|
+
- `npm audit fix`: axios 1.13.2 -> 1.20.0 (29 open advisories, including NO_PROXY/SSRF bypasses), follow-redirects -> 1.16.0, wrangler -> 4.129.0, vitest -> 4.1.11. Remaining findings (body-parser, express, qs) need express 5, a major: left for a dedicated change.
|
|
10
|
+
- `src/server.ts` and `src/worker.ts` were still at 0.4.118: the 0.4.119 bump skipped them because CLAUDE.md's release step lists only the three JSON files. Fixed here.
|
|
11
|
+
- Verified: build, worker build, 497 tests, real HTTP e2e (search on dati.gov.it, datastore on Messina, `169.254.169.254` still refused).
|
|
12
|
+
|
|
13
|
+
## 2026-09-04
|
|
14
|
+
|
|
15
|
+
### SSRF guard aligned with datagouv-mcp v1.0.0
|
|
16
|
+
|
|
17
|
+
Compared our `isBlockedIp` and request chain against the SSRF hardening shipped in [datagouv-mcp v1.0.0](https://github.com/datagouv/datagouv-mcp/releases/tag/v1.0.0) (PR #126, external report). Connect-time pinning, redirect re-checks and IPv4-mapped/6to4/NAT64 unwrapping were already in place; their specific vector (fetching producer-supplied URLs from catalog metadata) does not apply here. Two gaps closed:
|
|
18
|
+
|
|
19
|
+
- `proxy: false` on the axios path: with `HTTP_PROXY`/`HTTPS_PROXY` set, axios connected to the proxy and the SSRF-safe lookup validated only the proxy's IP, not the target's.
|
|
20
|
+
- `isBlockedIp` now also rejects 224.0.0.0/4 (multicast), 240.0.0.0/4 (reserved), ff00::/8 (IPv6 multicast) and fec0::/10 (site-local). Running their 37 test cases against our function surfaced exactly these.
|
|
21
|
+
|
|
22
|
+
## 2026-08-31
|
|
23
|
+
|
|
24
|
+
### Support #4682889 answered: the Advisory Database queue reaches back to June 2026
|
|
25
|
+
|
|
26
|
+
Second reply from Tempy (25 August, seen on the portal - the notification was in the inbox but the question was already answered before I looked): the advisory curation team confirmed that publication of repository advisories to the Global Advisory Database **is queued**, reviewed manually, and that "the advisory publication queue stretches back to June 2026", with work under way to reduce it.
|
|
27
|
+
|
|
28
|
+
So nothing is wrong with the records. The pattern we measured fits the explanation exactly: the only two advisories in the global database are the oldest ones (March and May), and CVE-2026-61612 (June) sits right at the edge of the backlog. Nothing on our side accelerates this, and there is no action left - the ticket auto-closed after seven days and is best left closed.
|
|
29
|
+
|
|
30
|
+
Worth keeping: **Dependabot alerts are driven from the advisory in the database, not from the CVE assignment** (Support, 24 August). The thirteen CVEs this repository now holds are a public reference, not downstream protection - that arrives only when the advisory clears the queue.
|
|
31
|
+
|
|
32
|
+
## 2026-08-24
|
|
33
|
+
|
|
34
|
+
### Support #4682889: GitHub answers about CVEs, the question was about advisories
|
|
35
|
+
|
|
36
|
+
First reply from GitHub Support (Tempy). It attributes the delay to an industry-wide surge in CVE publication and records being processed in order of arrival - which answers a question the ticket did not ask. The useful part is a statement that undercuts that very explanation:
|
|
37
|
+
|
|
38
|
+
> The associated advisory in the GitHub Advisory Database is published independently of the CVE record, and Dependabot alerts are driven from the advisory - not the CVE assignment.
|
|
39
|
+
|
|
40
|
+
If alerts are driven from the advisory, the CVE backlog cannot explain twelve published advisories being absent from the database. Replied restating the scope, with a new data point: `GHSA-x32r`, published 2026-08-20, is at its third working day and still not in the database either - so this is not confined to the older records.
|
|
41
|
+
|
|
42
|
+
State unchanged: 14 published advisories, 2 in the global database, 13 carrying a CVE. Linked from the reply: "Inside the Advisory Database and what happens when vulnerability volume breaks records", which suggests the bottleneck is database curation rather than CVE issuance. If that is the answer, "queued, and the queue is long" would be enough - and is worth asking for explicitly.
|
|
43
|
+
|
|
3
44
|
## 2026-08-20
|
|
4
45
|
|
|
46
|
+
### CVEs issued for the four narrowed advisories
|
|
47
|
+
|
|
48
|
+
The 2026-08-15 narrowing round came back green: `GHSA-vqff` -> CVE-2026-76894, `GHSA-c499` -> CVE-2026-76895, `GHSA-3369` -> CVE-2026-76896, `GHSA-v3j5` -> CVE-2026-76897. Arguing dependency for `GHSA-c499` (one missing neutralization pass produces both the injection and the spoofing) worked as well as splitting did for the others - no advisory had to be re-published as a new one. Every published advisory now carries a CVE except `GHSA-x32r`, requested today.
|
|
49
|
+
|
|
50
|
+
`SECURITY.md` updated. The propagation gap is unchanged and remains the subject of ticket #4682889: a CVE is necessary but not sufficient, and the global database still lists two of fourteen.
|
|
51
|
+
|
|
5
52
|
### v0.4.119 - classify IPv6 by value, not by prefix string (GHSA-x32r-mh7g-q2rf)
|
|
6
53
|
|
|
7
54
|
`0xRomSec` reported that `isBlockedIp` misses the IPv6 ranges that embed an IPv4 address: NAT64 (`64:ff9b::/96`, `64:ff9b:1::/48`), 6to4 (`2002::/16`) and IPv4-compatible (`::/96`). Verified against the real function - all eight cases in the report return `false`. `64:ff9b::a9fe:a9fe` is 169.254.169.254 written in IPv6, and the function is the single decision point for both the literal guard and the DNS-resolution guard, so the gap applied to both halves.
|
|
@@ -12,6 +59,10 @@ The DNS half needed no change: `createSsrfSafeLookup` already passes `all: true`
|
|
|
12
59
|
|
|
13
60
|
Tests: the eight advisory cases, four non-canonical spellings of the same address, four unparseable literals, `198.18.0.0/15` boundaries, plus three guard-level regressions that exercise the actual bypass chain (literal guard, `assertHostnameResolvesSafe`, connection-time lookup) rather than the classifier alone. 495 passing. Both build targets checked - `http.ts` is shared with the Workers bundle.
|
|
14
61
|
|
|
62
|
+
Released the full round: npm 0.4.119 (CI, provenance), GitHub release with dxt/skill assets, Cloudflare deployed and verified in prod (`http://[64:ff9b::a9fe:a9fe]` rejected, normal search intact), MCP Registry 0.4.119 `isLatest=true`.
|
|
63
|
+
|
|
64
|
+
API note, same class as the missing comments endpoint: **there is no `POST .../security-advisories/{ghsa}/publish`** - 404, and the OpenAPI description lists only `get`, `patch`, `cve` and `forks` for that path. Publishing an advisory is UI-only. `PATCH` (description, `patched_versions`) and `POST .../cve` do work from the API.
|
|
65
|
+
|
|
15
66
|
## 2026-08-20
|
|
16
67
|
|
|
17
68
|
### CVE-2026-76811/76812/76813 issued; advisory table added to SECURITY.md
|
package/dist/index.js
CHANGED
|
@@ -704,7 +704,9 @@ function isBlockedIp(ip) {
|
|
|
704
704
|
w[0] === 8194 || // 2002::/16 6to4
|
|
705
705
|
w[0] === 8193 && w[1] === 0 || // 2001::/32 Teredo
|
|
706
706
|
(w[0] & 65024) === 64512 || // fc00::/7 unique local
|
|
707
|
-
(w[0] & 65472) === 65152
|
|
707
|
+
(w[0] & 65472) === 65152 || // fe80::/10 link-local
|
|
708
|
+
(w[0] & 65472) === 65216 || // fec0::/10 site-local (deprecated)
|
|
709
|
+
(w[0] & 65280) === 65280;
|
|
708
710
|
}
|
|
709
711
|
const m = v.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
|
|
710
712
|
if (!m) return false;
|
|
@@ -718,7 +720,7 @@ function isBlockedIp(ip) {
|
|
|
718
720
|
o1 === 172 && o2 >= 16 && o2 <= 31 || // 172.16.0.0/12 private
|
|
719
721
|
o1 === 192 && o2 === 168 || // 192.168.0.0/16 private
|
|
720
722
|
o1 === 198 && (o2 === 18 || o2 === 19) || // 198.18.0.0/15 benchmarking
|
|
721
|
-
o1
|
|
723
|
+
o1 >= 224;
|
|
722
724
|
}
|
|
723
725
|
function validateServerUrl(serverUrl) {
|
|
724
726
|
let parsed;
|
|
@@ -949,6 +951,9 @@ async function makeCkanRequest(serverUrl, action, params = {}, opts = {}) {
|
|
|
949
951
|
timeout: 3e4,
|
|
950
952
|
responseType: "arraybuffer",
|
|
951
953
|
maxRedirects: 5,
|
|
954
|
+
// Never route through HTTP_PROXY/HTTPS_PROXY: a proxy would connect to the
|
|
955
|
+
// target itself, bypassing the SSRF-safe lookup pinned in the agents below.
|
|
956
|
+
proxy: false,
|
|
952
957
|
maxContentLength: MAX_RESPONSE_BYTES,
|
|
953
958
|
maxBodyLength: MAX_RESPONSE_BYTES,
|
|
954
959
|
...safeAgents ? { httpAgent: safeAgents.httpAgent, httpsAgent: safeAgents.httpsAgent } : {},
|
|
@@ -5795,7 +5800,7 @@ var registerAllPrompts = (server) => {
|
|
|
5795
5800
|
function createServer() {
|
|
5796
5801
|
return new McpServer({
|
|
5797
5802
|
name: "ckan-mcp-server",
|
|
5798
|
-
version: "0.4.
|
|
5803
|
+
version: "0.4.120"
|
|
5799
5804
|
});
|
|
5800
5805
|
}
|
|
5801
5806
|
function registerAll(server) {
|