@jini-ai/mcp 0.4.2 → 0.4.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/README.md +1 -0
- package/dist/agent-install/chrome-devtools.d.ts +4 -0
- package/dist/agent-install/chrome-devtools.js +7 -0
- package/dist/agent-install/index.d.ts +1 -0
- package/dist/agent-install/index.js +1 -0
- package/dist/bin/serve.js +6 -2
- package/dist/federation/bootstrap.d.ts +18 -0
- package/dist/federation/bootstrap.js +4 -4
- package/dist/federation/presets.d.ts +16 -17
- package/dist/federation/presets.js +35 -28
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/resources/site-guide-resource.d.ts +15 -0
- package/dist/server/resources/site-guide-resource.js +25 -0
- package/package.json +5 -5
- package/dist/core/oauth.d.ts +0 -274
- package/dist/core/oauth.js +0 -667
- package/dist/core/secure-write.d.ts +0 -17
- package/dist/core/secure-write.js +0 -72
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module @jini-ai/mcp/core/secure-write
|
|
3
|
-
* Shared atomic, owner-only-permission (0600) secret-file writer used by
|
|
4
|
-
* every secret-bearing on-disk store in this package: the server config
|
|
5
|
-
* store (env vars / `Authorization` headers), the OAuth dynamic-client-
|
|
6
|
-
* registration cache (`clientSecret`), and the OAuth token store (bearer /
|
|
7
|
-
* refresh tokens, confidential-client secrets). CR-006 / SEC-RB-002.
|
|
8
|
-
*
|
|
9
|
-
* The previous pattern in each of those stores wrote the temp file with
|
|
10
|
-
* default permissions and either never restricted it (config, OAuth client
|
|
11
|
-
* cache) or `chmod(0600)`'d it *after* the atomic rename and silently
|
|
12
|
-
* continued when the chmod failed (tokens) — both leave a window where the
|
|
13
|
-
* file exists world/group-readable, and the latter makes the "protection"
|
|
14
|
-
* advisory rather than enforced. This writer instead:
|
|
15
|
-
*
|
|
16
|
-
* 1. Creates the temp file *exclusively* (`wx`) with mode 0600 supplied to
|
|
17
|
-
* the same `open()`/`writeFile()` call that creates it — POSIX applies
|
|
18
|
-
* the requested mode atomically at creation time, so there is no
|
|
19
|
-
* window where the file exists with a broader mode. This repo already
|
|
20
|
-
* relies on `writeFile`'s `mode` option alone for a secret file with no
|
|
21
|
-
* separate chmod step (see `packages/agent-runtime/src/prompt-file.ts`);
|
|
22
|
-
* this module follows that same precedent rather than inventing a new one.
|
|
23
|
-
* 2. On POSIX platforms, verifies the on-disk mode actually landed as
|
|
24
|
-
* owner-only before renaming into place, and fails closed — removing
|
|
25
|
-
* the temp file and throwing — if it did not (e.g. an unusual umask or
|
|
26
|
-
* a filesystem that doesn't honor `mode`).
|
|
27
|
-
* 3. Skips that verification on `win32`: Windows has no POSIX permission-
|
|
28
|
-
* bit model (`mode` there only toggles the read-only attribute), so
|
|
29
|
-
* there is nothing meaningful to enforce or fail closed on — matching
|
|
30
|
-
* this repo's only other cross-platform file-mode precedent, which
|
|
31
|
-
* also does not branch on Windows.
|
|
32
|
-
*
|
|
33
|
-
* Part of the MCP `core` kernel; not part of the package's public barrel —
|
|
34
|
-
* imported directly by sibling `core/*.ts` files.
|
|
35
|
-
*/
|
|
36
|
-
import { mkdir, rename, rm, stat, writeFile } from 'node:fs/promises';
|
|
37
|
-
import { randomBytes } from 'node:crypto';
|
|
38
|
-
import path from 'node:path';
|
|
39
|
-
const SECRET_FILE_MODE = 0o600;
|
|
40
|
-
/**
|
|
41
|
-
* Atomically write `contents` to `finalPath` via a same-directory temp file
|
|
42
|
-
* created exclusively with mode 0600. On POSIX platforms, verifies no
|
|
43
|
-
* group/other permission bit made it onto disk before renaming into place;
|
|
44
|
-
* throws (after removing the temp file) if verification fails or the write
|
|
45
|
-
* itself fails, so a caller never observes a partially-written or
|
|
46
|
-
* insufficiently-restricted secret file.
|
|
47
|
-
* @param finalPath Absolute path the secret file should end up at.
|
|
48
|
-
* @param contents UTF-8 text to write.
|
|
49
|
-
* @param options `platform` override for tests; defaults to `process.platform`.
|
|
50
|
-
*/
|
|
51
|
-
export async function writeSecretFileAtomic(finalPath, contents, options = {}) {
|
|
52
|
-
const platform = options.platform ?? process.platform;
|
|
53
|
-
await mkdir(path.dirname(finalPath), { recursive: true });
|
|
54
|
-
const tmp = `${finalPath}.${randomBytes(4).toString('hex')}.tmp`;
|
|
55
|
-
try {
|
|
56
|
-
await writeFile(tmp, contents, { encoding: 'utf8', mode: SECRET_FILE_MODE, flag: 'wx' });
|
|
57
|
-
if (platform !== 'win32') {
|
|
58
|
-
const info = await stat(tmp);
|
|
59
|
-
const bits = info.mode & 0o777;
|
|
60
|
-
if ((bits & 0o077) !== 0) {
|
|
61
|
-
throw new Error(`refusing to persist secret-bearing file with non-owner-only permissions ` +
|
|
62
|
-
`(mode 0${bits.toString(8)}): ${finalPath}`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
await rename(tmp, finalPath);
|
|
66
|
-
}
|
|
67
|
-
catch (err) {
|
|
68
|
-
await rm(tmp, { force: true }).catch(() => undefined);
|
|
69
|
-
throw err;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
//# sourceMappingURL=secure-write.js.map
|