seaworthycode 1.1.2 → 1.1.4
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 +30 -26
- package/dist/index.js.map +1 -1
- package/package.json +14 -12
- package/rules/external/configuration/insecure-cookie-flags.test.yaml +114 -0
- package/rules/external/configuration/insecure-cookie-flags.yaml +77 -0
- package/rules/external/configuration/missing-ssl-verification.test.yaml +130 -0
- package/rules/external/configuration/missing-ssl-verification.yaml +123 -0
- package/rules/external/data-exposure/debug-artifacts.test.yaml +143 -0
- package/rules/external/data-exposure/debug-artifacts.yaml +57 -0
- package/rules/external/data-exposure/hardcoded-ip.test.yaml +131 -0
- package/rules/external/data-exposure/hardcoded-ip.yaml +67 -0
- package/rules/external/data-exposure/localstorage-sensitive-data.test.yaml +58 -0
- package/rules/external/data-exposure/localstorage-sensitive-data.yaml +60 -0
- package/rules/external/dependencies/deprecated-functions.test.yaml +92 -0
- package/rules/external/dependencies/deprecated-functions.yaml +66 -0
- package/rules/external/ops/hardcoded-port.test.yaml +141 -0
- package/rules/external/ops/hardcoded-port.yaml +91 -0
- package/rules/external/ops/insecure-file-permissions.test.yaml +111 -0
- package/rules/external/ops/insecure-file-permissions.yaml +91 -0
- package/rules/external/resilience/missing-memory-limit.test.yaml +54 -0
- package/rules/external/resilience/missing-memory-limit.yaml +59 -0
- package/rules/external/resilience/missing-timeout-config.test.yaml +179 -0
- package/rules/external/resilience/missing-timeout-config.yaml +124 -0
- package/rules/external/security/broken-crypto-algorithm.test.yaml +104 -0
- package/rules/external/security/broken-crypto-algorithm.yaml +79 -0
- package/rules/external/security/http-method-override.test.yaml +40 -0
- package/rules/external/security/http-method-override.yaml +35 -0
- package/rules/external/security/http-no-tls.test.yaml +115 -0
- package/rules/external/security/http-no-tls.yaml +59 -0
- package/rules/external/security/path-traversal.test.yaml +188 -0
- package/rules/external/security/path-traversal.yaml +210 -0
- package/rules/external/security/unsafe-innerhtml.test.yaml +72 -0
- package/rules/external/security/unsafe-innerhtml.yaml +46 -0
- package/rules/external/security/untrusted-deserialization.test.yaml +79 -0
- package/rules/external/security/untrusted-deserialization.yaml +48 -0
- package/rules/external/security/weak-encryption-mode.test.yaml +126 -0
- package/rules/external/security/weak-encryption-mode.yaml +104 -0
- package/rules/external/security/weak-hash-algorithm.test.yaml +121 -0
- package/rules/external/security/weak-hash-algorithm.yaml +87 -0
- package/rules/external/security/xxe-parsing.test.yaml +76 -0
- package/rules/external/security/xxe-parsing.yaml +63 -0
- package/rules/internal/security/dangerous-eval.test.yaml +126 -0
- package/rules/internal/security/dangerous-eval.yaml +134 -0
- package/rules/internal/security/no-document-write.test.yaml +33 -0
- package/rules/internal/security/no-document-write.yaml +40 -0
- package/rules/internal/taint/MATRIX.md +16 -0
- package/rules/internal/taint/bash.test.yaml +84 -0
- package/rules/internal/taint/bash.yaml +166 -0
- package/rules/internal/taint/dvwa.test.yaml +217 -0
- package/rules/internal/taint/go.test.yaml +207 -0
- package/rules/internal/taint/go.yaml +325 -0
- package/rules/internal/taint/java.test.yaml +158 -0
- package/rules/internal/taint/java.yaml +318 -0
- package/rules/internal/taint/javascript.test.yaml +374 -0
- package/rules/internal/taint/javascript.yaml +439 -0
- package/rules/internal/taint/php.test.yaml +134 -0
- package/rules/internal/taint/php.yaml +331 -0
- package/rules/internal/taint/python.test.yaml +427 -0
- package/rules/internal/taint/python.yaml +636 -0
- package/rules/internal/taint/ruby.test.yaml +148 -0
- package/rules/internal/taint/ruby.yaml +233 -0
- package/rules/internal/taint/rust.test.yaml +585 -0
- package/rules/internal/taint/rust.yaml +483 -0
- package/rules/internal/taint/tsx.test.yaml +140 -0
- package/rules/internal/taint/tsx.yaml +51 -0
- package/rules/internal/taint/typescript.test.yaml +393 -0
- package/rules/internal/taint/typescript.yaml +660 -0
- package/wasm/tree-sitter-sql.wasm +0 -0
package/dist/index.js
CHANGED
|
@@ -515,7 +515,9 @@ function sortFindings(findings) {
|
|
|
515
515
|
const fileA = a.file ?? "";
|
|
516
516
|
const fileB = b.file ?? "";
|
|
517
517
|
if (fileA !== fileB) return fileA.localeCompare(fileB);
|
|
518
|
-
|
|
518
|
+
const lineDiff = (a.line ?? 0) - (b.line ?? 0);
|
|
519
|
+
if (lineDiff !== 0) return lineDiff;
|
|
520
|
+
return a.checkId.localeCompare(b.checkId);
|
|
519
521
|
});
|
|
520
522
|
}
|
|
521
523
|
function dedupeDegradedFindings(findings) {
|
|
@@ -1559,36 +1561,36 @@ var ScanRunner = class {
|
|
|
1559
1561
|
astCache: /* @__PURE__ */ new Map()
|
|
1560
1562
|
};
|
|
1561
1563
|
const results = [];
|
|
1562
|
-
const
|
|
1563
|
-
const inFlight = /* @__PURE__ */ new Map();
|
|
1564
|
-
const findingsPerCategory = /* @__PURE__ */ new Map();
|
|
1565
|
-
for (const check2 of checks) {
|
|
1566
|
-
inFlight.set(check2.category, (inFlight.get(check2.category) ?? 0) + 1);
|
|
1567
|
-
}
|
|
1564
|
+
const checkResults = /* @__PURE__ */ new Map();
|
|
1568
1565
|
await runWithConcurrency(
|
|
1569
1566
|
checks,
|
|
1570
1567
|
async (check2) => {
|
|
1571
1568
|
try {
|
|
1572
1569
|
const findings2 = await check2.run(ctx);
|
|
1573
|
-
|
|
1574
|
-
if (options.onCategoryComplete) {
|
|
1575
|
-
findingsPerCategory.set(check2.category, (findingsPerCategory.get(check2.category) ?? 0) + findings2.length);
|
|
1576
|
-
}
|
|
1570
|
+
checkResults.set(check2.id, findings2);
|
|
1577
1571
|
} catch (err) {
|
|
1578
1572
|
console.error(`Check "${check2.id}" failed: ${String(err)}`);
|
|
1579
|
-
} finally {
|
|
1580
|
-
if (options.onCategoryComplete) {
|
|
1581
|
-
const remaining = (inFlight.get(check2.category) ?? 1) - 1;
|
|
1582
|
-
inFlight.set(check2.category, remaining);
|
|
1583
|
-
if (remaining === 0) {
|
|
1584
|
-
options.onCategoryComplete(check2.category, findingsPerCategory.get(check2.category) ?? 0);
|
|
1585
|
-
}
|
|
1586
|
-
}
|
|
1587
1573
|
}
|
|
1588
1574
|
},
|
|
1589
1575
|
concurrency
|
|
1590
1576
|
);
|
|
1591
|
-
|
|
1577
|
+
for (const check2 of checks) {
|
|
1578
|
+
results.push(...checkResults.get(check2.id) ?? []);
|
|
1579
|
+
}
|
|
1580
|
+
if (options.onCategoryComplete) {
|
|
1581
|
+
const findingsPerCategory = /* @__PURE__ */ new Map();
|
|
1582
|
+
for (const check2 of checks) {
|
|
1583
|
+
const count = (checkResults.get(check2.id) ?? []).length;
|
|
1584
|
+
findingsPerCategory.set(check2.category, (findingsPerCategory.get(check2.category) ?? 0) + count);
|
|
1585
|
+
}
|
|
1586
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1587
|
+
for (const check2 of checks) {
|
|
1588
|
+
if (!seen.has(check2.category)) {
|
|
1589
|
+
seen.add(check2.category);
|
|
1590
|
+
options.onCategoryComplete(check2.category, findingsPerCategory.get(check2.category) ?? 0);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1592
1594
|
if (ctx.astCache) {
|
|
1593
1595
|
for (const promise of ctx.astCache.values()) {
|
|
1594
1596
|
try {
|
|
@@ -10234,7 +10236,7 @@ registry.register({
|
|
|
10234
10236
|
});
|
|
10235
10237
|
var CHECK_ID40 = "security.weak-email-validation";
|
|
10236
10238
|
var REMEDIATION34 = getCopy("remediation.security.weak-email-validation");
|
|
10237
|
-
var WEAK_EMAIL_REGEX_LINE = /\/\^[
|
|
10239
|
+
var WEAK_EMAIL_REGEX_LINE = /\/\^[^/]*@[^/]*\\\.[^/]{0,4}\$\/[gimsuy]*/g;
|
|
10238
10240
|
var LOOSE_REGEX_CLASS = /\[\^?\\?s@\]\+@\[\^?\\?s@\]\+\\\.\[\^?\\?s@\]\+/g;
|
|
10239
10241
|
var EMAIL_CONTEXT = /email|e-?mail|validateEmail|isEmail|checkEmail|verifyEmail|deliverable/is;
|
|
10240
10242
|
function lineAndColumn15(content, index) {
|
|
@@ -10290,7 +10292,7 @@ registry.register({
|
|
|
10290
10292
|
var CHECK_ID41 = "security.idempotency-key-leak";
|
|
10291
10293
|
var REMEDIATION35 = getCopy("remediation.security.idempotency-key-leak");
|
|
10292
10294
|
var IDEMPOTENCY_CONTEXT = /idempotency[_-]?key|idempotency[_-]?token/i;
|
|
10293
|
-
var TEMPLATE_LITERAL_INTERPOLATION =
|
|
10295
|
+
var TEMPLATE_LITERAL_INTERPOLATION = new RegExp("`[^`]*\\$\\{[^}]+\\}[^`]*`", "g");
|
|
10294
10296
|
var STRUCTURED_ID_PATTERN = /(?:lic(?:ense|ence)|sub(?:scription)?|order|cust(?:omer)?|user|tx|pay(?:ment)?|inv(?:oice)?)[-/]/i;
|
|
10295
10297
|
function lineAndColumn16(content, index) {
|
|
10296
10298
|
const prefix = content.slice(0, index);
|
|
@@ -15169,6 +15171,7 @@ var copy3 = {
|
|
|
15169
15171
|
"cli.sarif.stdout_conflict": "Flags --sarif-stdout and --json cannot be used together. Use --output to send JSON to a file.",
|
|
15170
15172
|
"cli.error.llmRequired": "LLM API key required for Pro checks. Set it with seaworthy config or the SEAWORTHY_LLM_API_KEY environment variable.",
|
|
15171
15173
|
"cli.warn.llmSkipped": "Pro checks skipped: no LLM API key configured. Set it with seaworthy config or the SEAWORTHY_LLM_API_KEY environment variable to enable semantic analysis.",
|
|
15174
|
+
"cli.warn.licenseInvalid": "Your license key is invalid or has been revoked. Running in free tier.\nTo re-enter your key, run: npx seaworthycode setup",
|
|
15172
15175
|
"cli.error.config.missingKey": "Missing config key. Usage: seaworthy config <set|get> <key>",
|
|
15173
15176
|
"cli.error.config.missingValue": "Missing config value. Usage: seaworthy config set <key> <value>",
|
|
15174
15177
|
"cli.error.config.unknownKey": "Unknown config key. Valid keys: licenseKey, llmProvider, llmApiKey, llmModel, llmApiUrl",
|
|
@@ -15600,6 +15603,7 @@ async function runCli(options) {
|
|
|
15600
15603
|
const message = resolveErrorMessage(authResult.code);
|
|
15601
15604
|
return { code: resolveExitCode(authResult.code), error: message };
|
|
15602
15605
|
}
|
|
15606
|
+
console.error(getCopy2("cli.warn.licenseInvalid"));
|
|
15603
15607
|
}
|
|
15604
15608
|
const auth = authResult.ok ? authResult.value : { tier: "free", token: "", licensedTo: "free tier" };
|
|
15605
15609
|
const allowedTiers = {
|
|
@@ -15764,6 +15768,10 @@ cli.help(() => {
|
|
|
15764
15768
|
$ npx seaworthycode ./my-project --sarif report.sarif
|
|
15765
15769
|
$ npx seaworthycode --provider kimi ./my-project`
|
|
15766
15770
|
},
|
|
15771
|
+
{
|
|
15772
|
+
title: "Commands",
|
|
15773
|
+
body: ` npx seaworthycode setup Interactive setup for license key and LLM provider`
|
|
15774
|
+
},
|
|
15767
15775
|
{
|
|
15768
15776
|
title: "Options",
|
|
15769
15777
|
body: ` --json Output JSON to stdout
|
|
@@ -15779,10 +15787,6 @@ cli.help(() => {
|
|
|
15779
15787
|
--show-ids Show check IDs alongside names
|
|
15780
15788
|
--debug Enable debug logging`
|
|
15781
15789
|
},
|
|
15782
|
-
{
|
|
15783
|
-
title: "Commands",
|
|
15784
|
-
body: ` seaworthy setup Interactive first-run setup`
|
|
15785
|
-
},
|
|
15786
15790
|
{
|
|
15787
15791
|
title: "Configuration",
|
|
15788
15792
|
body: ` ~/.seaworthy/config # license key, LLM provider, API key, model, url`
|