@synkro-sh/cli 1.6.100 → 1.7.0
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/dist/bootstrap.js +51 -13
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -1050,16 +1050,18 @@ export function log(msg: string): void {
|
|
|
1050
1050
|
// \u2500\u2500\u2500 JWT Management \u2500\u2500\u2500
|
|
1051
1051
|
|
|
1052
1052
|
export function loadJwt(): string | null {
|
|
1053
|
-
//
|
|
1054
|
-
// accepted
|
|
1055
|
-
// cli/*), so
|
|
1056
|
-
//
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1053
|
+
// Prefer the long-lived (1yr) Synkro MCP token in BOTH cloud and local mode.
|
|
1054
|
+
// It's org+user scoped and accepted across the hook surface (grade/submit,
|
|
1055
|
+
// cwe-rules, hook/*, cli/*), so a single 'synkro login' keeps grading + CWE
|
|
1056
|
+
// detection alive for a year with NO refresh. The alternative \u2014 the ~5-min
|
|
1057
|
+
// WorkOS access_token \u2014 rides a rotating refresh chain that dies with the
|
|
1058
|
+
// WorkOS session (invalid_grant "session has already ended"), which silently
|
|
1059
|
+
// disabled CWE findings while editGuard/cveScan (which don't need this token)
|
|
1060
|
+
// kept working. jwtIsExpired sees a year of runway, so we never hit refreshJwt.
|
|
1061
|
+
try {
|
|
1062
|
+
const mcp = readFileSync(MCP_JWT_PATH, 'utf-8').trim();
|
|
1063
|
+
if (mcp) return mcp;
|
|
1064
|
+
} catch { /* no mcp token on disk \u2014 fall back to the login token below */ }
|
|
1063
1065
|
try {
|
|
1064
1066
|
if (!existsSync(CREDS_PATH)) return null;
|
|
1065
1067
|
const creds = JSON.parse(readFileSync(CREDS_PATH, 'utf-8'));
|
|
@@ -5126,7 +5128,9 @@ async function main() {
|
|
|
5126
5128
|
const findings = Array.isArray(cweResp?.findings) ? cweResp.findings : [];
|
|
5127
5129
|
if (cweResp?.action === 'deny' && findings.length > 0) {
|
|
5128
5130
|
const activeCweIds = findings
|
|
5129
|
-
|
|
5131
|
+
// CWE is a separate, always-ask grader — a detected weakness is ALWAYS
|
|
5132
|
+
// surfaced regardless of the rule's stored mode (fix/blocking/ask).
|
|
5133
|
+
// Only path exemptions suppress it (matches the local-route branch).
|
|
5130
5134
|
.map((f: any) => f.cwe)
|
|
5131
5135
|
.filter((id: string) => !exemptedCwes.has(id.toUpperCase()));
|
|
5132
5136
|
|
|
@@ -5297,6 +5301,40 @@ async function main() {
|
|
|
5297
5301
|
let anyFailed = false;
|
|
5298
5302
|
|
|
5299
5303
|
for (const gradeResp of gradeResponses) {
|
|
5304
|
+
// The CWE grader emits findings, but its wrapper VARIES per call:
|
|
5305
|
+
// {"findings":[...]} | <findings>[...]</findings> | a bare [...] array.
|
|
5306
|
+
// Extract findings from any of them. Without this, parseVerdict sees no
|
|
5307
|
+
// <synkro-verdict> wrapper and defaults to ok:true, silently dropping every
|
|
5308
|
+
// detected CWE (a format mismatch). The <synkro-verdict> XML path below is
|
|
5309
|
+
// the fallback for the legacy format.
|
|
5310
|
+
let jsonFindings: any[] | null = null;
|
|
5311
|
+
try {
|
|
5312
|
+
const tagM = gradeResp.match(/<findings>([\s\S]*?)<\/findings>/);
|
|
5313
|
+
const src = tagM ? tagM[1] : gradeResp;
|
|
5314
|
+
const objM = src.match(/\{[\s\S]*"findings"[\s\S]*\}/);
|
|
5315
|
+
const arrM = src.match(/\[[\s\S]*\]/);
|
|
5316
|
+
if (objM) { const p = JSON.parse(objM[0]); if (Array.isArray(p.findings)) jsonFindings = p.findings; }
|
|
5317
|
+
if (!jsonFindings && arrM) { const p = JSON.parse(arrM[0]); if (Array.isArray(p)) jsonFindings = p; }
|
|
5318
|
+
} catch { /* not parseable JSON — fall through to XML parsing */ }
|
|
5319
|
+
if (jsonFindings) {
|
|
5320
|
+
if (jsonFindings.length > 0) {
|
|
5321
|
+
anyFailed = true;
|
|
5322
|
+
for (const f of jsonFindings.slice(0, 8)) {
|
|
5323
|
+
const id = String(f.cwe || f.rule_id || '').trim().replace(/^cwe-/i, 'CWE-');
|
|
5324
|
+
// Validate the shape (CWE-<number>) before using it as an object key —
|
|
5325
|
+
// the grade response is model output, so reject anything that isn't a
|
|
5326
|
+
// real CWE id (also blocks __proto__/constructor key injection).
|
|
5327
|
+
if (!/^CWE-\d+$/.test(id)) continue;
|
|
5328
|
+
if (!cweIds.includes(id)) cweIds.push(id);
|
|
5329
|
+
if (f.detail && !fixes[id]) fixes[id] = String(f.detail);
|
|
5330
|
+
if (f.code_snippet && !snippets[id]) snippets[id] = String(f.code_snippet);
|
|
5331
|
+
if (!mergedReason && (f.summary || f.detail)) mergedReason = String(f.summary || f.detail);
|
|
5332
|
+
if (!mergedSeverity && f.severity) mergedSeverity = String(f.severity);
|
|
5333
|
+
if (!mergedCategory && f.category) mergedCategory = String(f.category);
|
|
5334
|
+
}
|
|
5335
|
+
}
|
|
5336
|
+
continue;
|
|
5337
|
+
}
|
|
5300
5338
|
const v = parseVerdict(gradeResp);
|
|
5301
5339
|
if (!v.ok) {
|
|
5302
5340
|
anyFailed = true;
|
|
@@ -11412,7 +11450,7 @@ function writeConfigEnv(opts) {
|
|
|
11412
11450
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
11413
11451
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
11414
11452
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
11415
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.
|
|
11453
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.7.0")}`
|
|
11416
11454
|
];
|
|
11417
11455
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
11418
11456
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -15475,7 +15513,7 @@ var args = process.argv.slice(2);
|
|
|
15475
15513
|
var cmd = args[0] || "";
|
|
15476
15514
|
var subArgs = args.slice(1);
|
|
15477
15515
|
function printVersion() {
|
|
15478
|
-
console.log("1.
|
|
15516
|
+
console.log("1.7.0");
|
|
15479
15517
|
}
|
|
15480
15518
|
function printHelp2() {
|
|
15481
15519
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|