cf-memory-mcp 3.9.5 → 3.9.6
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/bin/cf-memory-mcp.js +26 -6
- package/package.json +1 -1
package/bin/cf-memory-mcp.js
CHANGED
|
@@ -1808,11 +1808,27 @@ class CFMemoryMCP {
|
|
|
1808
1808
|
// files because path.resolve treats absolute file_paths as-is and
|
|
1809
1809
|
// doesn't enforce ancestry. This is a security finding from codex
|
|
1810
1810
|
// review; fix before reading anything off disk.
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
//
|
|
1814
|
-
//
|
|
1815
|
-
//
|
|
1811
|
+
//
|
|
1812
|
+
// Also dereference symlinks via fs.realpathSync — without this,
|
|
1813
|
+
// an attacker could create a symlink inside the project root
|
|
1814
|
+
// pointing at /etc/passwd and the relative-path check would
|
|
1815
|
+
// still pass (the symlink itself is in-root). realpath gives
|
|
1816
|
+
// the underlying target which we then check the same way.
|
|
1817
|
+
const normalizedRoot = (() => {
|
|
1818
|
+
try { return fs.realpathSync(path.resolve(projectRoot)); }
|
|
1819
|
+
catch (_) { return path.resolve(projectRoot); }
|
|
1820
|
+
})();
|
|
1821
|
+
const candidateFull = path.resolve(normalizedRoot, filePath);
|
|
1822
|
+
let resolvedFull;
|
|
1823
|
+
try {
|
|
1824
|
+
resolvedFull = fs.realpathSync(candidateFull);
|
|
1825
|
+
} catch (_) {
|
|
1826
|
+
return false; // doesn't exist or unreadable
|
|
1827
|
+
}
|
|
1828
|
+
// Path must be strictly under the (real) project root. `relative`
|
|
1829
|
+
// returns an empty string for the root itself and a `..`-prefixed
|
|
1830
|
+
// string for anything outside. Use the realpath of both sides so
|
|
1831
|
+
// symlinks can't smuggle the target out of the root.
|
|
1816
1832
|
const relative = path.relative(normalizedRoot, resolvedFull);
|
|
1817
1833
|
if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
1818
1834
|
_mcpTrace('GFC_LOCAL_REJECT_ESCAPE', `${filePath} -> ${resolvedFull} escapes root ${normalizedRoot}`);
|
|
@@ -1856,7 +1872,11 @@ class CFMemoryMCP {
|
|
|
1856
1872
|
const language = extToLang[ext] || null;
|
|
1857
1873
|
|
|
1858
1874
|
const payload = {
|
|
1859
|
-
|
|
1875
|
+
// Use normalizedRoot (the realpath'd root) to match resolvedFull
|
|
1876
|
+
// (also realpath'd). Using the original projectRoot here gave
|
|
1877
|
+
// weird relative paths on macOS where /tmp is a symlink to
|
|
1878
|
+
// /private/tmp.
|
|
1879
|
+
file_path: path.relative(normalizedRoot, resolvedFull) || path.basename(resolvedFull),
|
|
1860
1880
|
language,
|
|
1861
1881
|
total_lines: totalLines,
|
|
1862
1882
|
size_bytes: stat.size,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cf-memory-mcp",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.6",
|
|
4
4
|
"description": "Cloudflare-hosted MCP server for code indexing, retrieval, and assistant memory with a direct remote MCP endpoint and local stdio bridge.",
|
|
5
5
|
"main": "bin/cf-memory-mcp.js",
|
|
6
6
|
"bin": {
|