mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 14:15:56 +00:00
fix(hardening): count executable sync fs call sites
This commit is contained in:
1 parent
cefb564948
commit
d21b5c44ee
4 files changed
+186
-58
No files matched your search
@@ -31,9 +31,9 @@ Baseline captured: `2026-02-12`.
|
|||||||
|
|
||||||
| Metric | Baseline |
|
| Metric | Baseline |
|
||||||
|---|---:|
|
|---|---:|
|
||||||
| Sync fs occurrences (all) | 841 |
|
| Sync fs occurrences (all) | 835 |
|
||||||
| Sync fs files affected (all) | 100 |
|
| Sync fs files affected (all) | 100 |
|
||||||
| Sync fs occurrences (runtime hotpaths) | 730 |
|
| Sync fs occurrences (runtime hotpaths) | 724 |
|
||||||
| Sync fs files affected (runtime hotpaths) | 89 |
|
| Sync fs files affected (runtime hotpaths) | 89 |
|
||||||
| Legacy shim markers | 131 |
|
| Legacy shim markers | 131 |
|
||||||
| Legacy shim files affected | 56 |
|
| Legacy shim files affected | 56 |
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"scope": "src/**/*.{ts,tsx,js,jsx,mjs,cjs}",
|
"scope": "src/**/*.{ts,tsx,js,jsx,mjs,cjs}",
|
||||||
"syncFs": {
|
"syncFs": {
|
||||||
"totalOccurrences": 841,
|
"totalOccurrences": 835,
|
||||||
"filesAffected": 100,
|
"filesAffected": 100,
|
||||||
"hotpathOccurrences": 730,
|
"hotpathOccurrences": 724,
|
||||||
"hotpathFilesAffected": 89,
|
"hotpathFilesAffected": 89,
|
||||||
"topHotpathFiles": [
|
"topHotpathFiles": [
|
||||||
{
|
{
|
||||||
@@ -44,24 +44,6 @@
|
|||||||
],
|
],
|
||||||
"markers": []
|
"markers": []
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "src/utils/claude-dir-installer.ts",
|
|
||||||
"count": 23,
|
|
||||||
"calls": [
|
|
||||||
"copyFileSync",
|
|
||||||
"cpSync",
|
|
||||||
"existsSync",
|
|
||||||
"lstatSync",
|
|
||||||
"mkdirSync",
|
|
||||||
"readdirSync",
|
|
||||||
"renameSync",
|
|
||||||
"rmSync",
|
|
||||||
"statSync",
|
|
||||||
"unlinkSync",
|
|
||||||
"writeFileSync"
|
|
||||||
],
|
|
||||||
"markers": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "src/utils/shell-completion.ts",
|
"file": "src/utils/shell-completion.ts",
|
||||||
"count": 23,
|
"count": 23,
|
||||||
@@ -89,6 +71,24 @@
|
|||||||
],
|
],
|
||||||
"markers": []
|
"markers": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"file": "src/utils/claude-dir-installer.ts",
|
||||||
|
"count": 21,
|
||||||
|
"calls": [
|
||||||
|
"copyFileSync",
|
||||||
|
"cpSync",
|
||||||
|
"existsSync",
|
||||||
|
"lstatSync",
|
||||||
|
"mkdirSync",
|
||||||
|
"readdirSync",
|
||||||
|
"renameSync",
|
||||||
|
"rmSync",
|
||||||
|
"statSync",
|
||||||
|
"unlinkSync",
|
||||||
|
"writeFileSync"
|
||||||
|
],
|
||||||
|
"markers": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"file": "src/cliproxy/binary/version-cache.ts",
|
"file": "src/cliproxy/binary/version-cache.ts",
|
||||||
"count": 20,
|
"count": 20,
|
||||||
@@ -218,24 +218,6 @@
|
|||||||
],
|
],
|
||||||
"markers": []
|
"markers": []
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "src/utils/claude-dir-installer.ts",
|
|
||||||
"count": 23,
|
|
||||||
"calls": [
|
|
||||||
"copyFileSync",
|
|
||||||
"cpSync",
|
|
||||||
"existsSync",
|
|
||||||
"lstatSync",
|
|
||||||
"mkdirSync",
|
|
||||||
"readdirSync",
|
|
||||||
"renameSync",
|
|
||||||
"rmSync",
|
|
||||||
"statSync",
|
|
||||||
"unlinkSync",
|
|
||||||
"writeFileSync"
|
|
||||||
],
|
|
||||||
"markers": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "src/utils/shell-completion.ts",
|
"file": "src/utils/shell-completion.ts",
|
||||||
"count": 23,
|
"count": 23,
|
||||||
@@ -263,6 +245,24 @@
|
|||||||
],
|
],
|
||||||
"markers": []
|
"markers": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"file": "src/utils/claude-dir-installer.ts",
|
||||||
|
"count": 21,
|
||||||
|
"calls": [
|
||||||
|
"copyFileSync",
|
||||||
|
"cpSync",
|
||||||
|
"existsSync",
|
||||||
|
"lstatSync",
|
||||||
|
"mkdirSync",
|
||||||
|
"readdirSync",
|
||||||
|
"renameSync",
|
||||||
|
"rmSync",
|
||||||
|
"statSync",
|
||||||
|
"unlinkSync",
|
||||||
|
"writeFileSync"
|
||||||
|
],
|
||||||
|
"markers": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"file": "src/cliproxy/binary/version-cache.ts",
|
"file": "src/cliproxy/binary/version-cache.ts",
|
||||||
"count": 20,
|
"count": 20,
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ Scope: `src/**/*.{ts,tsx,js,jsx,mjs,cjs}`
|
|||||||
|
|
||||||
| Metric | Value |
|
| Metric | Value |
|
||||||
|---|---:|
|
|---|---:|
|
||||||
| Sync fs occurrences (all) | 841 |
|
| Sync fs occurrences (all) | 835 |
|
||||||
| Sync fs files affected (all) | 100 |
|
| Sync fs files affected (all) | 100 |
|
||||||
| Sync fs occurrences (runtime hotpaths) | 730 |
|
| Sync fs occurrences (runtime hotpaths) | 724 |
|
||||||
| Sync fs files affected (runtime hotpaths) | 89 |
|
| Sync fs files affected (runtime hotpaths) | 89 |
|
||||||
| Legacy shim markers | 131 |
|
| Legacy shim markers | 131 |
|
||||||
| Legacy shim files affected | 56 |
|
| Legacy shim files affected | 56 |
|
||||||
@@ -19,9 +19,9 @@ Scope: `src/**/*.{ts,tsx,js,jsx,mjs,cjs}`
|
|||||||
|---|---:|---|
|
|---|---:|---|
|
||||||
| `src/management/shared-manager.ts` | 60 | copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync |
|
| `src/management/shared-manager.ts` | 60 | copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync |
|
||||||
| `src/utils/claude-symlink-manager.ts` | 27 | copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, renameSync, rmSync, statSync, symlinkSync, unlinkSync |
|
| `src/utils/claude-symlink-manager.ts` | 27 | copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, renameSync, rmSync, statSync, symlinkSync, unlinkSync |
|
||||||
| `src/utils/claude-dir-installer.ts` | 23 | copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync |
|
|
||||||
| `src/utils/shell-completion.ts` | 23 | appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, statSync |
|
| `src/utils/shell-completion.ts` | 23 | appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, statSync |
|
||||||
| `src/web-server/routes/settings-routes.ts` | 23 | copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync |
|
| `src/web-server/routes/settings-routes.ts` | 23 | copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync |
|
||||||
|
| `src/utils/claude-dir-installer.ts` | 21 | copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync |
|
||||||
| `src/cliproxy/binary/version-cache.ts` | 20 | existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync |
|
| `src/cliproxy/binary/version-cache.ts` | 20 | existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync |
|
||||||
| `src/management/recovery-manager.ts` | 20 | copyFileSync, existsSync, mkdirSync, renameSync, writeFileSync |
|
| `src/management/recovery-manager.ts` | 20 | copyFileSync, existsSync, mkdirSync, renameSync, writeFileSync |
|
||||||
| `src/web-server/routes/cliproxy-stats-routes.ts` | 20 | closeSync, existsSync, fstatSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, renameSync, statSync, writeFileSync |
|
| `src/web-server/routes/cliproxy-stats-routes.ts` | 20 | closeSync, existsSync, fstatSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, renameSync, statSync, writeFileSync |
|
||||||
|
|||||||
+143
-15
@@ -60,9 +60,10 @@ const SYNC_CALL_NAMES = [
|
|||||||
'writeSync',
|
'writeSync',
|
||||||
'writevSync',
|
'writevSync',
|
||||||
];
|
];
|
||||||
|
const SYNC_CALL_CAPTURE_REGEX = new RegExp(
|
||||||
const SYNC_CALL_LINE_REGEX = new RegExp(`\\b(?:fs\\.)?(?:${SYNC_CALL_NAMES.join('|')})\\b`);
|
`(?:\\bfs(?:\\s*\\?\\.)?\\s*\\.\\s*|(?<![\\w$.]))(${SYNC_CALL_NAMES.join('|')})\\s*\\(`,
|
||||||
const SYNC_CALL_CAPTURE_REGEX = new RegExp(`\\b(?:fs\\.)?(${SYNC_CALL_NAMES.join('|')})\\b`, 'g');
|
'g'
|
||||||
|
);
|
||||||
const LEGACY_MARKER_REGEX =
|
const LEGACY_MARKER_REGEX =
|
||||||
/(?:\blegacy\b|\bshim\b|backward compatibility|backwards compatibility|compatibility layer|deprecated.*re-export|re-export.*compatibility)/i;
|
/(?:\blegacy\b|\bshim\b|backward compatibility|backwards compatibility|compatibility layer|deprecated.*re-export|re-export.*compatibility)/i;
|
||||||
|
|
||||||
@@ -123,6 +124,142 @@ function summarize(items, limit = 10) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stripComments(sourceText) {
|
||||||
|
let output = '';
|
||||||
|
let index = 0;
|
||||||
|
let inLineComment = false;
|
||||||
|
let inBlockComment = false;
|
||||||
|
let inSingleQuote = false;
|
||||||
|
let inDoubleQuote = false;
|
||||||
|
let inTemplateLiteral = false;
|
||||||
|
|
||||||
|
while (index < sourceText.length) {
|
||||||
|
const current = sourceText[index];
|
||||||
|
const next = sourceText[index + 1];
|
||||||
|
|
||||||
|
if (inLineComment) {
|
||||||
|
if (current === '\n' || current === '\r') {
|
||||||
|
inLineComment = false;
|
||||||
|
output += current;
|
||||||
|
} else {
|
||||||
|
output += ' ';
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inBlockComment) {
|
||||||
|
if (current === '*' && next === '/') {
|
||||||
|
output += ' ';
|
||||||
|
index += 2;
|
||||||
|
inBlockComment = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output += current === '\n' || current === '\r' ? current : ' ';
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inSingleQuote) {
|
||||||
|
output += current;
|
||||||
|
if (current === '\\') {
|
||||||
|
output += next ?? '';
|
||||||
|
index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current === "'") {
|
||||||
|
inSingleQuote = false;
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inDoubleQuote) {
|
||||||
|
output += current;
|
||||||
|
if (current === '\\') {
|
||||||
|
output += next ?? '';
|
||||||
|
index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current === '"') {
|
||||||
|
inDoubleQuote = false;
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inTemplateLiteral) {
|
||||||
|
output += current;
|
||||||
|
if (current === '\\') {
|
||||||
|
output += next ?? '';
|
||||||
|
index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current === '`') {
|
||||||
|
inTemplateLiteral = false;
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current === '/' && next === '/') {
|
||||||
|
output += ' ';
|
||||||
|
index += 2;
|
||||||
|
inLineComment = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current === '/' && next === '*') {
|
||||||
|
output += ' ';
|
||||||
|
index += 2;
|
||||||
|
inBlockComment = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current === "'") {
|
||||||
|
inSingleQuote = true;
|
||||||
|
output += current;
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current === '"') {
|
||||||
|
inDoubleQuote = true;
|
||||||
|
output += current;
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current === '`') {
|
||||||
|
inTemplateLiteral = true;
|
||||||
|
output += current;
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output += current;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectSyncCallSites(sourceText) {
|
||||||
|
const sanitizedSource = stripComments(sourceText);
|
||||||
|
const captureRegex = new RegExp(SYNC_CALL_CAPTURE_REGEX.source, SYNC_CALL_CAPTURE_REGEX.flags);
|
||||||
|
const calls = [];
|
||||||
|
|
||||||
|
for (const match of sanitizedSource.matchAll(captureRegex)) {
|
||||||
|
calls.push(match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
count: calls.length,
|
||||||
|
calls,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function buildReport() {
|
function buildReport() {
|
||||||
const files = walkFiles(SRC_DIR);
|
const files = walkFiles(SRC_DIR);
|
||||||
const syncEntries = [];
|
const syncEntries = [];
|
||||||
@@ -130,22 +267,13 @@ function buildReport() {
|
|||||||
|
|
||||||
for (const fullPath of files) {
|
for (const fullPath of files) {
|
||||||
const file = relativePath(fullPath);
|
const file = relativePath(fullPath);
|
||||||
const lines = fs.readFileSync(fullPath, 'utf8').split(/\r?\n/);
|
const sourceText = fs.readFileSync(fullPath, 'utf8');
|
||||||
|
const lines = sourceText.split(/\r?\n/);
|
||||||
let syncCount = 0;
|
const { count: syncCount, calls: syncCalls } = collectSyncCallSites(sourceText);
|
||||||
const syncCalls = [];
|
|
||||||
let legacyCount = 0;
|
let legacyCount = 0;
|
||||||
const legacyMarkers = [];
|
const legacyMarkers = [];
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
if (SYNC_CALL_LINE_REGEX.test(line)) {
|
|
||||||
const matches = [...line.matchAll(SYNC_CALL_CAPTURE_REGEX)];
|
|
||||||
syncCount += matches.length;
|
|
||||||
for (const match of matches) {
|
|
||||||
syncCalls.push(match[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LEGACY_MARKER_REGEX.test(line)) {
|
if (LEGACY_MARKER_REGEX.test(line)) {
|
||||||
legacyCount += 1;
|
legacyCount += 1;
|
||||||
const normalized = line.trim();
|
const normalized = line.trim();
|
||||||
|
|||||||
Reference in new issue
Block a user