@runa-ai/runa-cli 0.5.33 → 0.5.35
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/index.js
CHANGED
|
@@ -925,7 +925,7 @@ var CLI_VERSION, HAS_ADMIN_COMMAND;
|
|
|
925
925
|
var init_version = __esm({
|
|
926
926
|
"src/version.ts"() {
|
|
927
927
|
init_esm_shims();
|
|
928
|
-
CLI_VERSION = "0.5.
|
|
928
|
+
CLI_VERSION = "0.5.35";
|
|
929
929
|
HAS_ADMIN_COMMAND = false;
|
|
930
930
|
}
|
|
931
931
|
});
|
|
@@ -1722,7 +1722,8 @@ function checkBase64ForSecrets(base64String) {
|
|
|
1722
1722
|
const decoded = Buffer.from(base64String, "base64").toString("utf-8");
|
|
1723
1723
|
for (const indicator of BASE64_SECRET_INDICATORS) {
|
|
1724
1724
|
if (decoded.startsWith(indicator)) {
|
|
1725
|
-
|
|
1725
|
+
const secretType = getSecretTypeFromIndicator(indicator);
|
|
1726
|
+
return { found: true, secretType };
|
|
1726
1727
|
}
|
|
1727
1728
|
}
|
|
1728
1729
|
return { found: false };
|
|
@@ -1730,6 +1731,18 @@ function checkBase64ForSecrets(base64String) {
|
|
|
1730
1731
|
return { found: false };
|
|
1731
1732
|
}
|
|
1732
1733
|
}
|
|
1734
|
+
function getSecretTypeFromIndicator(indicator) {
|
|
1735
|
+
const indicatorMap = {
|
|
1736
|
+
"sk-": "OpenAI/Stripe API key",
|
|
1737
|
+
ghp_: "GitHub Personal Access Token",
|
|
1738
|
+
gho_: "GitHub OAuth Token",
|
|
1739
|
+
AKIA: "AWS Access Key",
|
|
1740
|
+
eyJ: "JWT Token",
|
|
1741
|
+
vercel_: "Vercel Token",
|
|
1742
|
+
sbp_: "Supabase Token"
|
|
1743
|
+
};
|
|
1744
|
+
return indicatorMap[indicator] ?? "Unknown secret type";
|
|
1745
|
+
}
|
|
1733
1746
|
function isCommentLine(line) {
|
|
1734
1747
|
const trimmed = line.trim();
|
|
1735
1748
|
return trimmed.startsWith("//") || trimmed.startsWith("#") || trimmed.startsWith("*") || trimmed.startsWith("/*") || trimmed.startsWith("<!--") || trimmed.startsWith("--");
|
|
@@ -1982,7 +1995,7 @@ function scanLineForSecrets(line, lineNumber, filePath) {
|
|
|
1982
1995
|
ruleId: "secret/base64-encoded",
|
|
1983
1996
|
severity: "high",
|
|
1984
1997
|
title: "Base64-Encoded Secret",
|
|
1985
|
-
description: `Base64-encoded secret detected.
|
|
1998
|
+
description: `Base64-encoded secret detected. Type: ${result.secretType}`,
|
|
1986
1999
|
location: {
|
|
1987
2000
|
file: filePath,
|
|
1988
2001
|
line: lineNumber,
|
|
@@ -3362,6 +3375,14 @@ var init_json_reporter = __esm({
|
|
|
3362
3375
|
});
|
|
3363
3376
|
|
|
3364
3377
|
// src/internal/vuln-checker/reporters/markdown-reporter.ts
|
|
3378
|
+
function escapeMarkdown(text) {
|
|
3379
|
+
let escaped = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3380
|
+
escaped = escaped.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\*/g, "\\*").replace(/_/g, "\\_").replace(/\{/g, "\\{").replace(/\}/g, "\\}").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/#/g, "\\#").replace(/\+/g, "\\+").replace(/-/g, "\\-").replace(/\./g, "\\.").replace(/!/g, "\\!").replace(/\|/g, "\\|");
|
|
3381
|
+
return escaped;
|
|
3382
|
+
}
|
|
3383
|
+
function sanitizeCodeBlock(text) {
|
|
3384
|
+
return text.replace(/```/g, "\\`\\`\\`");
|
|
3385
|
+
}
|
|
3365
3386
|
function groupByCategory2(findings) {
|
|
3366
3387
|
const byCategory = /* @__PURE__ */ new Map();
|
|
3367
3388
|
for (const finding of findings) {
|
|
@@ -3392,29 +3413,31 @@ function formatMetadata(finding) {
|
|
|
3392
3413
|
}
|
|
3393
3414
|
function formatSnippet(finding) {
|
|
3394
3415
|
if (!finding.snippet) return [];
|
|
3395
|
-
return ["```", finding.snippet.text, "```\n"];
|
|
3416
|
+
return ["```", sanitizeCodeBlock(finding.snippet.text), "```\n"];
|
|
3396
3417
|
}
|
|
3397
3418
|
function formatFix(finding) {
|
|
3398
3419
|
if (!finding.fix) return [];
|
|
3399
|
-
const lines = [`**Fix**: ${finding.fix.description}
|
|
3420
|
+
const lines = [`**Fix**: ${escapeMarkdown(finding.fix.description)}
|
|
3400
3421
|
`];
|
|
3401
3422
|
if (finding.fix.replacement) {
|
|
3402
|
-
lines.push("```", finding.fix.replacement, "```\n");
|
|
3423
|
+
lines.push("```", sanitizeCodeBlock(finding.fix.replacement), "```\n");
|
|
3403
3424
|
}
|
|
3404
3425
|
return lines;
|
|
3405
3426
|
}
|
|
3406
3427
|
function formatFinding2(finding) {
|
|
3407
3428
|
const emoji = SEVERITY_EMOJI[finding.severity];
|
|
3408
3429
|
const location = `${formatFilePath(finding.location.file)}:${finding.location.line}`;
|
|
3430
|
+
const safeTitle = escapeMarkdown(finding.title);
|
|
3431
|
+
const safeDescription = escapeMarkdown(finding.description);
|
|
3409
3432
|
return [
|
|
3410
|
-
`#### ${emoji} ${
|
|
3433
|
+
`#### ${emoji} ${safeTitle}
|
|
3411
3434
|
`,
|
|
3412
3435
|
`- **Severity**: ${finding.severity}`,
|
|
3413
3436
|
`- **Location**: \`${location}\``,
|
|
3414
3437
|
`- **Rule**: \`${finding.ruleId}\``,
|
|
3415
3438
|
...formatMetadata(finding),
|
|
3416
3439
|
`
|
|
3417
|
-
${
|
|
3440
|
+
${safeDescription}
|
|
3418
3441
|
`,
|
|
3419
3442
|
...formatSnippet(finding),
|
|
3420
3443
|
...formatFix(finding),
|
|
@@ -3483,8 +3506,9 @@ var init_markdown_reporter = __esm({
|
|
|
3483
3506
|
lines.push("The following findings were ignored based on configuration:\n");
|
|
3484
3507
|
for (const finding of result.ignoredFindings) {
|
|
3485
3508
|
const emoji = SEVERITY_EMOJI[finding.severity];
|
|
3509
|
+
const safeTitle = escapeMarkdown(finding.title);
|
|
3486
3510
|
lines.push(
|
|
3487
|
-
`- ${emoji} **${
|
|
3511
|
+
`- ${emoji} **${safeTitle}** at \`${finding.location.file}:${finding.location.line}\``
|
|
3488
3512
|
);
|
|
3489
3513
|
}
|
|
3490
3514
|
lines.push("");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-analyzer.d.ts","sourceRoot":"","sources":["../../../../src/internal/vuln-checker/analyzers/secret-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,OAAO,EAAoB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"secret-analyzer.d.ts","sourceRoot":"","sources":["../../../../src/internal/vuln-checker/analyzers/secret-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,OAAO,EAAoB,MAAM,aAAa,CAAC;AA2jClG;;GAEG;AACH,qBAAa,cAAe,YAAW,QAAQ;IAC7C,IAAI,SAAoB;IACxB,UAAU,EAAE,QAAQ,EAAE,CAAc;IAE9B,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;YAkB7C,cAAc;IAY5B,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markdown reporter for human-readable vulnerability reports
|
|
3
|
+
*
|
|
4
|
+
* SECURITY (Issue #543): This reporter sanitizes all user-controlled content
|
|
5
|
+
* to prevent XSS and injection attacks when reports are rendered in web interfaces.
|
|
3
6
|
*/
|
|
4
7
|
import type { Reporter, ScanResult } from '../types.js';
|
|
5
8
|
export declare class MarkdownReporter implements Reporter {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-reporter.d.ts","sourceRoot":"","sources":["../../../../src/internal/vuln-checker/reporters/markdown-reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"markdown-reporter.d.ts","sourceRoot":"","sources":["../../../../src/internal/vuln-checker/reporters/markdown-reporter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAW,QAAQ,EAAE,UAAU,EAAY,MAAM,aAAa,CAAC;AA2K3E,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,IAAI,SAAc;IAElB,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM;CAuDnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runa-ai/runa-cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.35",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "AI-powered DevOps CLI",
|
|
6
6
|
"type": "module",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"xstate": "5.25.0",
|
|
54
54
|
"zod": "4.3.5",
|
|
55
55
|
"@runa-ai/runa": "0.5.33",
|
|
56
|
-
"@runa-ai/runa-xstate-test-plugin": "0.5.
|
|
56
|
+
"@runa-ai/runa-xstate-test-plugin": "0.5.35"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">=20.0.0"
|