slopbrick 0.34.6 → 0.34.8
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/engine/worker.cjs +20 -11
- package/dist/engine/worker.js +20 -11
- package/dist/index.cjs +24 -15
- package/dist/index.js +24 -15
- package/package.json +1 -1
package/dist/engine/worker.cjs
CHANGED
|
@@ -34575,6 +34575,7 @@ var PRINTF_FAMILY_REGEX = /\b(?:printf|fprintf|sprintf|snprintf)\s*\(/g;
|
|
|
34575
34575
|
var COUT_LITERAL_REGEX = /std\s*::\s*(?:cout|cerr|clog)\s*<<\s*"[^"]*"/g;
|
|
34576
34576
|
var STD_COUT_BARE_REGEX = /std\s*::\s*(?:cout|cerr|clog)\s*<<\s*'[^']*'/g;
|
|
34577
34577
|
var THRESHOLD_DEFAULT = 1;
|
|
34578
|
+
var TEST_FILE_REGEX = /(?:\/tests?\/|_test\.cc|_test\.cpp|Test\.cc|Test\.cpp|Tests\.cc|Tests\.cpp|_unittest\.cc|_unittest\.cpp)/;
|
|
34578
34579
|
var cppPrintfDebugRule = createRule({
|
|
34579
34580
|
id: "cpp/printf-debug",
|
|
34580
34581
|
category: "typo",
|
|
@@ -34589,6 +34590,7 @@ var cppPrintfDebugRule = createRule({
|
|
|
34589
34590
|
const source = facts.v2?._source;
|
|
34590
34591
|
if (!source) return issues;
|
|
34591
34592
|
if (!/\.(cpp|cc|cxx|h|hpp|hh|hxx|H)$/i.test(facts.filePath)) return issues;
|
|
34593
|
+
if (TEST_FILE_REGEX.test(facts.filePath)) return issues;
|
|
34592
34594
|
const printfCount = (source.match(PRINTF_FAMILY_REGEX) ?? []).length;
|
|
34593
34595
|
let viaPrintf = false;
|
|
34594
34596
|
if (printfCount > context.threshold) {
|
|
@@ -34605,7 +34607,7 @@ var cppPrintfDebugRule = createRule({
|
|
|
34605
34607
|
message: viaPrintf ? `${printfCount} printf-family calls \u2014 use spdlog / glog / AbslLog` : "std::cout/cerr/clog with a string literal \u2014 use spdlog / glog / AbslLog",
|
|
34606
34608
|
line: 1,
|
|
34607
34609
|
column: 1,
|
|
34608
|
-
advice: "Replace with `spdlog::info(...)`, `LOG(INFO) << ...` (glog), or `ABSL_LOG(INFO) << ...` (Abseil). All of these are level-aware and have a configurable sink, and they route to stderr by default. `printf` / `std::cout` have no levels, no redaction, no sink routing, and can't be silenced in release builds. AI agents reach for these because their training data has countless C++ textbook examples with them. Reference: cpp/printf-debug v0.
|
|
34610
|
+
advice: "Replace with `spdlog::info(...)`, `LOG(INFO) << ...` (glog), or `ABSL_LOG(INFO) << ...` (Abseil). All of these are level-aware and have a configurable sink, and they route to stderr by default. `printf` / `std::cout` have no levels, no redaction, no sink routing, and can't be silenced in release builds. AI agents reach for these because their training data has countless C++ textbook examples with them. Reference: cpp/printf-debug v0.34.7 (refined to skip test files for higher precision)."
|
|
34609
34611
|
});
|
|
34610
34612
|
return issues;
|
|
34611
34613
|
}
|
|
@@ -37583,7 +37585,7 @@ var kotlinObjectSingletonMisuseRule = createRule({
|
|
|
37583
37585
|
// src/rules/kotlin/println-as-log.ts
|
|
37584
37586
|
var PRINTLN_REGEX = /\bprintln\s*\(/g;
|
|
37585
37587
|
var REAL_LOGGING_IMPORT_REGEX2 = /\bimport\s+(?:android\.util\.Log|org\.slf4j\.|io\.github\.oshai\.kotlinlogging|kotlin\.logging|co\.touchlab\.kermit|com\.github\.ajalt\.timber|org\.apache\.logging\.log4j)/;
|
|
37586
|
-
var
|
|
37588
|
+
var TEST_FILE_REGEX2 = /(?:\/src\/test\/|\/test\/|\/Tests\/|\/Test\.kt|\/Tests\.kt|Tests\.kt$|Test\.kt$)/;
|
|
37587
37589
|
var kotlinPrintlnAsLogRule = createRule({
|
|
37588
37590
|
id: "kotlin/println-as-log",
|
|
37589
37591
|
category: "logic",
|
|
@@ -37598,7 +37600,7 @@ var kotlinPrintlnAsLogRule = createRule({
|
|
|
37598
37600
|
const source = facts.v2?._source;
|
|
37599
37601
|
if (!source) return issues;
|
|
37600
37602
|
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37601
|
-
if (
|
|
37603
|
+
if (TEST_FILE_REGEX2.test(facts.filePath)) return issues;
|
|
37602
37604
|
if (REAL_LOGGING_IMPORT_REGEX2.test(source)) return issues;
|
|
37603
37605
|
let m;
|
|
37604
37606
|
PRINTLN_REGEX.lastIndex = 0;
|
|
@@ -37699,9 +37701,9 @@ var kotlinRunBlockingMisuseRule = createRule({
|
|
|
37699
37701
|
});
|
|
37700
37702
|
|
|
37701
37703
|
// src/rules/kotlin/sql-string-concat.ts
|
|
37702
|
-
var SQL_KEYWORD_REGEX2 = /\b(
|
|
37704
|
+
var SQL_KEYWORD_REGEX2 = /\b(SELECT|INSERT\s+INTO|UPDATE|DELETE\s+FROM|CREATE\s+TABLE|DROP\s+TABLE|ALTER\s+TABLE)\b/i;
|
|
37703
37705
|
var UNSAFE_REGEX2 = /(?:\+|\$\{)/;
|
|
37704
|
-
var SAFE_REGEX2 = /(?:PreparedStatement|setParameter|setString|setInt|setLong|bind|:name
|
|
37706
|
+
var SAFE_REGEX2 = /(?:PreparedStatement|setParameter|setString|setInt|setLong|bind|:name|:\?|\?)/;
|
|
37705
37707
|
var kotlinSqlStringConcatRule = createRule({
|
|
37706
37708
|
id: "kotlin/sql-string-concat",
|
|
37707
37709
|
category: "security",
|
|
@@ -37719,7 +37721,14 @@ var kotlinSqlStringConcatRule = createRule({
|
|
|
37719
37721
|
const lines = source.split("\n");
|
|
37720
37722
|
for (let i = 0; i < lines.length; i++) {
|
|
37721
37723
|
const line = lines[i];
|
|
37722
|
-
|
|
37724
|
+
const keywordMatch = SQL_KEYWORD_REGEX2.exec(line);
|
|
37725
|
+
if (!keywordMatch) continue;
|
|
37726
|
+
const keywordIdx = keywordMatch.index;
|
|
37727
|
+
let j = keywordIdx - 1;
|
|
37728
|
+
while (j >= 0 && /\s/.test(line[j])) j--;
|
|
37729
|
+
if (j < 0) continue;
|
|
37730
|
+
const prevChar = line[j];
|
|
37731
|
+
if (prevChar !== '"' && prevChar !== "'" && prevChar !== "=") continue;
|
|
37723
37732
|
if (!UNSAFE_REGEX2.test(line)) continue;
|
|
37724
37733
|
if (SAFE_REGEX2.test(line)) continue;
|
|
37725
37734
|
issues.push({
|
|
@@ -37730,7 +37739,7 @@ var kotlinSqlStringConcatRule = createRule({
|
|
|
37730
37739
|
message: `SQL query built via string concat/template at line ${i + 1}`,
|
|
37731
37740
|
line: i + 1,
|
|
37732
37741
|
column: 1,
|
|
37733
|
-
advice: 'Use a PreparedStatement (JDBC), setParameter() (Exposed), or an ORM (Room, jOOQ). String concatenation or template interpolation into a SQL query is the canonical SQL-injection pattern \u2014 even "trusted" inputs (signed JWT, internal config) can be influenced by an attacker. Reference: kotlin/sql-string-concat v0.
|
|
37742
|
+
advice: 'Use a PreparedStatement (JDBC), setParameter() (Exposed), or an ORM (Room, jOOQ). String concatenation or template interpolation into a SQL query is the canonical SQL-injection pattern \u2014 even "trusted" inputs (signed JWT, internal config) can be influenced by an attacker. Reference: kotlin/sql-string-concat v0.34.8 (refined: require SQL keyword to start a string literal; fixed SAFE_REGEX bug).'
|
|
37734
37743
|
});
|
|
37735
37744
|
}
|
|
37736
37745
|
return issues;
|
|
@@ -40635,7 +40644,7 @@ var swiftImplicitlyUnwrappedOptionalRule = createRule({
|
|
|
40635
40644
|
// src/rules/swift/print-debug.ts
|
|
40636
40645
|
var PRINT_REGEX = /\bprint\s*\(/g;
|
|
40637
40646
|
var DEFAULT_THRESHOLD2 = 1;
|
|
40638
|
-
var
|
|
40647
|
+
var TEST_FILE_REGEX3 = /(?:\/Tests\/|\/Tests\.swift|\/Test\.swift|Tests\.swift$|Test\.swift$)/;
|
|
40639
40648
|
var swiftPrintDebugRule = createRule({
|
|
40640
40649
|
id: "swift/print-debug",
|
|
40641
40650
|
category: "typo",
|
|
@@ -40650,7 +40659,7 @@ var swiftPrintDebugRule = createRule({
|
|
|
40650
40659
|
const source = facts.v2?._source;
|
|
40651
40660
|
if (!source) return issues;
|
|
40652
40661
|
if (!/\.swift$/i.test(facts.filePath)) return issues;
|
|
40653
|
-
if (
|
|
40662
|
+
if (TEST_FILE_REGEX3.test(facts.filePath)) return issues;
|
|
40654
40663
|
const matches = [];
|
|
40655
40664
|
let m;
|
|
40656
40665
|
PRINT_REGEX.lastIndex = 0;
|
|
@@ -45538,7 +45547,7 @@ var signal_strength_default = {
|
|
|
45538
45547
|
precision: 0.0556,
|
|
45539
45548
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
45540
45549
|
verdict: "DORMANT",
|
|
45541
|
-
_calibrationNote:
|
|
45550
|
+
_calibrationNote: 'v0.34.8: REFINED \u2014 rule now requires the SQL keyword to be the start of a string literal (preceded by `"`, `\'`, or `=`), and fixed a bug in the SAFE_REGEX (the `:??` was malformed, should be `:?`). Per-file unique v9 Kotlin calibration (2698 neg, 213 pos): 1 TP file, 17 FP files, ratio=0.75 (DORMANT). 18 total fires. The refinement is expected to push precision from 5.6% to 25%+ by removing lines where SELECT/INSERT appears in string values (e.g. `val msg = "Selected 1 row: \\$count"`). Also fixed the bug where `:??` in SAFE_REGEX didn\'t match Java/Kotlin named parameters (`:id`). The full v9 re-calibration is part of the broader v0.34.8/v0.34.9 pipeline. INSUFFICIENT_DATA: pos arm 213 files (below 10k floor).',
|
|
45542
45551
|
aiSpecific: false,
|
|
45543
45552
|
_v9Verdict: "DORMANT",
|
|
45544
45553
|
_v9Lift: 0.75,
|
|
@@ -45882,7 +45891,7 @@ var signal_strength_default = {
|
|
|
45882
45891
|
precision: 0.4407,
|
|
45883
45892
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
45884
45893
|
verdict: "OK",
|
|
45885
|
-
_calibrationNote: "v0.
|
|
45894
|
+
_calibrationNote: "v0.34.7: REFINED \u2014 rule now skips test files (gtest, catch2, doctest conventions: *_test.cpp, *_test.cc, /tests/ dir, *Test.cpp, *Test.cc, *_unittest.cpp). Per-file unique v9 C++ calibration (5107 neg, 1655 pos): 156 TP files, 198 FP files, ratio=2.43 (OK, fourth positive-signal in v9 history). precision=44.07% (below 50% USEFUL threshold); verdict=OK. The refinement is expected to push precision from 44% to 50%+ by removing gtest test output fires (which were a significant portion of FPs in the v0.33.0 measurement). The full v9 re-calibration is part of the broader v0.34.5/v0.34.7 pipeline; see v0.34.1's Four-language validation section. Same direction as kotlin/println-as-log (1.84), java/system-out-println (1.73 refined, 3.29 unrefined), swift/print-debug (1.13). INSUFFICIENT_DATA: pos arm 1655 files (below 10k floor).",
|
|
45886
45895
|
aiSpecific: true,
|
|
45887
45896
|
_v7Verdict: "DORMANT",
|
|
45888
45897
|
_v7Lift: 1,
|
package/dist/engine/worker.js
CHANGED
|
@@ -34546,6 +34546,7 @@ var PRINTF_FAMILY_REGEX = /\b(?:printf|fprintf|sprintf|snprintf)\s*\(/g;
|
|
|
34546
34546
|
var COUT_LITERAL_REGEX = /std\s*::\s*(?:cout|cerr|clog)\s*<<\s*"[^"]*"/g;
|
|
34547
34547
|
var STD_COUT_BARE_REGEX = /std\s*::\s*(?:cout|cerr|clog)\s*<<\s*'[^']*'/g;
|
|
34548
34548
|
var THRESHOLD_DEFAULT = 1;
|
|
34549
|
+
var TEST_FILE_REGEX = /(?:\/tests?\/|_test\.cc|_test\.cpp|Test\.cc|Test\.cpp|Tests\.cc|Tests\.cpp|_unittest\.cc|_unittest\.cpp)/;
|
|
34549
34550
|
var cppPrintfDebugRule = createRule({
|
|
34550
34551
|
id: "cpp/printf-debug",
|
|
34551
34552
|
category: "typo",
|
|
@@ -34560,6 +34561,7 @@ var cppPrintfDebugRule = createRule({
|
|
|
34560
34561
|
const source = facts.v2?._source;
|
|
34561
34562
|
if (!source) return issues;
|
|
34562
34563
|
if (!/\.(cpp|cc|cxx|h|hpp|hh|hxx|H)$/i.test(facts.filePath)) return issues;
|
|
34564
|
+
if (TEST_FILE_REGEX.test(facts.filePath)) return issues;
|
|
34563
34565
|
const printfCount = (source.match(PRINTF_FAMILY_REGEX) ?? []).length;
|
|
34564
34566
|
let viaPrintf = false;
|
|
34565
34567
|
if (printfCount > context.threshold) {
|
|
@@ -34576,7 +34578,7 @@ var cppPrintfDebugRule = createRule({
|
|
|
34576
34578
|
message: viaPrintf ? `${printfCount} printf-family calls \u2014 use spdlog / glog / AbslLog` : "std::cout/cerr/clog with a string literal \u2014 use spdlog / glog / AbslLog",
|
|
34577
34579
|
line: 1,
|
|
34578
34580
|
column: 1,
|
|
34579
|
-
advice: "Replace with `spdlog::info(...)`, `LOG(INFO) << ...` (glog), or `ABSL_LOG(INFO) << ...` (Abseil). All of these are level-aware and have a configurable sink, and they route to stderr by default. `printf` / `std::cout` have no levels, no redaction, no sink routing, and can't be silenced in release builds. AI agents reach for these because their training data has countless C++ textbook examples with them. Reference: cpp/printf-debug v0.
|
|
34581
|
+
advice: "Replace with `spdlog::info(...)`, `LOG(INFO) << ...` (glog), or `ABSL_LOG(INFO) << ...` (Abseil). All of these are level-aware and have a configurable sink, and they route to stderr by default. `printf` / `std::cout` have no levels, no redaction, no sink routing, and can't be silenced in release builds. AI agents reach for these because their training data has countless C++ textbook examples with them. Reference: cpp/printf-debug v0.34.7 (refined to skip test files for higher precision)."
|
|
34580
34582
|
});
|
|
34581
34583
|
return issues;
|
|
34582
34584
|
}
|
|
@@ -37554,7 +37556,7 @@ var kotlinObjectSingletonMisuseRule = createRule({
|
|
|
37554
37556
|
// src/rules/kotlin/println-as-log.ts
|
|
37555
37557
|
var PRINTLN_REGEX = /\bprintln\s*\(/g;
|
|
37556
37558
|
var REAL_LOGGING_IMPORT_REGEX2 = /\bimport\s+(?:android\.util\.Log|org\.slf4j\.|io\.github\.oshai\.kotlinlogging|kotlin\.logging|co\.touchlab\.kermit|com\.github\.ajalt\.timber|org\.apache\.logging\.log4j)/;
|
|
37557
|
-
var
|
|
37559
|
+
var TEST_FILE_REGEX2 = /(?:\/src\/test\/|\/test\/|\/Tests\/|\/Test\.kt|\/Tests\.kt|Tests\.kt$|Test\.kt$)/;
|
|
37558
37560
|
var kotlinPrintlnAsLogRule = createRule({
|
|
37559
37561
|
id: "kotlin/println-as-log",
|
|
37560
37562
|
category: "logic",
|
|
@@ -37569,7 +37571,7 @@ var kotlinPrintlnAsLogRule = createRule({
|
|
|
37569
37571
|
const source = facts.v2?._source;
|
|
37570
37572
|
if (!source) return issues;
|
|
37571
37573
|
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37572
|
-
if (
|
|
37574
|
+
if (TEST_FILE_REGEX2.test(facts.filePath)) return issues;
|
|
37573
37575
|
if (REAL_LOGGING_IMPORT_REGEX2.test(source)) return issues;
|
|
37574
37576
|
let m;
|
|
37575
37577
|
PRINTLN_REGEX.lastIndex = 0;
|
|
@@ -37670,9 +37672,9 @@ var kotlinRunBlockingMisuseRule = createRule({
|
|
|
37670
37672
|
});
|
|
37671
37673
|
|
|
37672
37674
|
// src/rules/kotlin/sql-string-concat.ts
|
|
37673
|
-
var SQL_KEYWORD_REGEX2 = /\b(
|
|
37675
|
+
var SQL_KEYWORD_REGEX2 = /\b(SELECT|INSERT\s+INTO|UPDATE|DELETE\s+FROM|CREATE\s+TABLE|DROP\s+TABLE|ALTER\s+TABLE)\b/i;
|
|
37674
37676
|
var UNSAFE_REGEX2 = /(?:\+|\$\{)/;
|
|
37675
|
-
var SAFE_REGEX2 = /(?:PreparedStatement|setParameter|setString|setInt|setLong|bind|:name
|
|
37677
|
+
var SAFE_REGEX2 = /(?:PreparedStatement|setParameter|setString|setInt|setLong|bind|:name|:\?|\?)/;
|
|
37676
37678
|
var kotlinSqlStringConcatRule = createRule({
|
|
37677
37679
|
id: "kotlin/sql-string-concat",
|
|
37678
37680
|
category: "security",
|
|
@@ -37690,7 +37692,14 @@ var kotlinSqlStringConcatRule = createRule({
|
|
|
37690
37692
|
const lines = source.split("\n");
|
|
37691
37693
|
for (let i = 0; i < lines.length; i++) {
|
|
37692
37694
|
const line = lines[i];
|
|
37693
|
-
|
|
37695
|
+
const keywordMatch = SQL_KEYWORD_REGEX2.exec(line);
|
|
37696
|
+
if (!keywordMatch) continue;
|
|
37697
|
+
const keywordIdx = keywordMatch.index;
|
|
37698
|
+
let j = keywordIdx - 1;
|
|
37699
|
+
while (j >= 0 && /\s/.test(line[j])) j--;
|
|
37700
|
+
if (j < 0) continue;
|
|
37701
|
+
const prevChar = line[j];
|
|
37702
|
+
if (prevChar !== '"' && prevChar !== "'" && prevChar !== "=") continue;
|
|
37694
37703
|
if (!UNSAFE_REGEX2.test(line)) continue;
|
|
37695
37704
|
if (SAFE_REGEX2.test(line)) continue;
|
|
37696
37705
|
issues.push({
|
|
@@ -37701,7 +37710,7 @@ var kotlinSqlStringConcatRule = createRule({
|
|
|
37701
37710
|
message: `SQL query built via string concat/template at line ${i + 1}`,
|
|
37702
37711
|
line: i + 1,
|
|
37703
37712
|
column: 1,
|
|
37704
|
-
advice: 'Use a PreparedStatement (JDBC), setParameter() (Exposed), or an ORM (Room, jOOQ). String concatenation or template interpolation into a SQL query is the canonical SQL-injection pattern \u2014 even "trusted" inputs (signed JWT, internal config) can be influenced by an attacker. Reference: kotlin/sql-string-concat v0.
|
|
37713
|
+
advice: 'Use a PreparedStatement (JDBC), setParameter() (Exposed), or an ORM (Room, jOOQ). String concatenation or template interpolation into a SQL query is the canonical SQL-injection pattern \u2014 even "trusted" inputs (signed JWT, internal config) can be influenced by an attacker. Reference: kotlin/sql-string-concat v0.34.8 (refined: require SQL keyword to start a string literal; fixed SAFE_REGEX bug).'
|
|
37705
37714
|
});
|
|
37706
37715
|
}
|
|
37707
37716
|
return issues;
|
|
@@ -40606,7 +40615,7 @@ var swiftImplicitlyUnwrappedOptionalRule = createRule({
|
|
|
40606
40615
|
// src/rules/swift/print-debug.ts
|
|
40607
40616
|
var PRINT_REGEX = /\bprint\s*\(/g;
|
|
40608
40617
|
var DEFAULT_THRESHOLD2 = 1;
|
|
40609
|
-
var
|
|
40618
|
+
var TEST_FILE_REGEX3 = /(?:\/Tests\/|\/Tests\.swift|\/Test\.swift|Tests\.swift$|Test\.swift$)/;
|
|
40610
40619
|
var swiftPrintDebugRule = createRule({
|
|
40611
40620
|
id: "swift/print-debug",
|
|
40612
40621
|
category: "typo",
|
|
@@ -40621,7 +40630,7 @@ var swiftPrintDebugRule = createRule({
|
|
|
40621
40630
|
const source = facts.v2?._source;
|
|
40622
40631
|
if (!source) return issues;
|
|
40623
40632
|
if (!/\.swift$/i.test(facts.filePath)) return issues;
|
|
40624
|
-
if (
|
|
40633
|
+
if (TEST_FILE_REGEX3.test(facts.filePath)) return issues;
|
|
40625
40634
|
const matches = [];
|
|
40626
40635
|
let m;
|
|
40627
40636
|
PRINT_REGEX.lastIndex = 0;
|
|
@@ -45509,7 +45518,7 @@ var signal_strength_default = {
|
|
|
45509
45518
|
precision: 0.0556,
|
|
45510
45519
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
45511
45520
|
verdict: "DORMANT",
|
|
45512
|
-
_calibrationNote:
|
|
45521
|
+
_calibrationNote: 'v0.34.8: REFINED \u2014 rule now requires the SQL keyword to be the start of a string literal (preceded by `"`, `\'`, or `=`), and fixed a bug in the SAFE_REGEX (the `:??` was malformed, should be `:?`). Per-file unique v9 Kotlin calibration (2698 neg, 213 pos): 1 TP file, 17 FP files, ratio=0.75 (DORMANT). 18 total fires. The refinement is expected to push precision from 5.6% to 25%+ by removing lines where SELECT/INSERT appears in string values (e.g. `val msg = "Selected 1 row: \\$count"`). Also fixed the bug where `:??` in SAFE_REGEX didn\'t match Java/Kotlin named parameters (`:id`). The full v9 re-calibration is part of the broader v0.34.8/v0.34.9 pipeline. INSUFFICIENT_DATA: pos arm 213 files (below 10k floor).',
|
|
45513
45522
|
aiSpecific: false,
|
|
45514
45523
|
_v9Verdict: "DORMANT",
|
|
45515
45524
|
_v9Lift: 0.75,
|
|
@@ -45853,7 +45862,7 @@ var signal_strength_default = {
|
|
|
45853
45862
|
precision: 0.4407,
|
|
45854
45863
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
45855
45864
|
verdict: "OK",
|
|
45856
|
-
_calibrationNote: "v0.
|
|
45865
|
+
_calibrationNote: "v0.34.7: REFINED \u2014 rule now skips test files (gtest, catch2, doctest conventions: *_test.cpp, *_test.cc, /tests/ dir, *Test.cpp, *Test.cc, *_unittest.cpp). Per-file unique v9 C++ calibration (5107 neg, 1655 pos): 156 TP files, 198 FP files, ratio=2.43 (OK, fourth positive-signal in v9 history). precision=44.07% (below 50% USEFUL threshold); verdict=OK. The refinement is expected to push precision from 44% to 50%+ by removing gtest test output fires (which were a significant portion of FPs in the v0.33.0 measurement). The full v9 re-calibration is part of the broader v0.34.5/v0.34.7 pipeline; see v0.34.1's Four-language validation section. Same direction as kotlin/println-as-log (1.84), java/system-out-println (1.73 refined, 3.29 unrefined), swift/print-debug (1.13). INSUFFICIENT_DATA: pos arm 1655 files (below 10k floor).",
|
|
45857
45866
|
aiSpecific: true,
|
|
45858
45867
|
_v7Verdict: "DORMANT",
|
|
45859
45868
|
_v7Lift: 1,
|
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ var VERSION;
|
|
|
36
36
|
var init_header = __esm({
|
|
37
37
|
"src/types/_header.ts"() {
|
|
38
38
|
"use strict";
|
|
39
|
-
VERSION = "0.34.
|
|
39
|
+
VERSION = "0.34.8";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -27810,7 +27810,7 @@ var init_magic_numbers = __esm({
|
|
|
27810
27810
|
});
|
|
27811
27811
|
|
|
27812
27812
|
// src/rules/cpp/printf-debug.ts
|
|
27813
|
-
var PRINTF_FAMILY_REGEX, COUT_LITERAL_REGEX, STD_COUT_BARE_REGEX, THRESHOLD_DEFAULT, cppPrintfDebugRule;
|
|
27813
|
+
var PRINTF_FAMILY_REGEX, COUT_LITERAL_REGEX, STD_COUT_BARE_REGEX, THRESHOLD_DEFAULT, TEST_FILE_REGEX, cppPrintfDebugRule;
|
|
27814
27814
|
var init_printf_debug = __esm({
|
|
27815
27815
|
"src/rules/cpp/printf-debug.ts"() {
|
|
27816
27816
|
"use strict";
|
|
@@ -27819,6 +27819,7 @@ var init_printf_debug = __esm({
|
|
|
27819
27819
|
COUT_LITERAL_REGEX = /std\s*::\s*(?:cout|cerr|clog)\s*<<\s*"[^"]*"/g;
|
|
27820
27820
|
STD_COUT_BARE_REGEX = /std\s*::\s*(?:cout|cerr|clog)\s*<<\s*'[^']*'/g;
|
|
27821
27821
|
THRESHOLD_DEFAULT = 1;
|
|
27822
|
+
TEST_FILE_REGEX = /(?:\/tests?\/|_test\.cc|_test\.cpp|Test\.cc|Test\.cpp|Tests\.cc|Tests\.cpp|_unittest\.cc|_unittest\.cpp)/;
|
|
27822
27823
|
cppPrintfDebugRule = createRule({
|
|
27823
27824
|
id: "cpp/printf-debug",
|
|
27824
27825
|
category: "typo",
|
|
@@ -27833,6 +27834,7 @@ var init_printf_debug = __esm({
|
|
|
27833
27834
|
const source = facts.v2?._source;
|
|
27834
27835
|
if (!source) return issues;
|
|
27835
27836
|
if (!/\.(cpp|cc|cxx|h|hpp|hh|hxx|H)$/i.test(facts.filePath)) return issues;
|
|
27837
|
+
if (TEST_FILE_REGEX.test(facts.filePath)) return issues;
|
|
27836
27838
|
const printfCount = (source.match(PRINTF_FAMILY_REGEX) ?? []).length;
|
|
27837
27839
|
let viaPrintf = false;
|
|
27838
27840
|
if (printfCount > context.threshold) {
|
|
@@ -27849,7 +27851,7 @@ var init_printf_debug = __esm({
|
|
|
27849
27851
|
message: viaPrintf ? `${printfCount} printf-family calls \u2014 use spdlog / glog / AbslLog` : "std::cout/cerr/clog with a string literal \u2014 use spdlog / glog / AbslLog",
|
|
27850
27852
|
line: 1,
|
|
27851
27853
|
column: 1,
|
|
27852
|
-
advice: "Replace with `spdlog::info(...)`, `LOG(INFO) << ...` (glog), or `ABSL_LOG(INFO) << ...` (Abseil). All of these are level-aware and have a configurable sink, and they route to stderr by default. `printf` / `std::cout` have no levels, no redaction, no sink routing, and can't be silenced in release builds. AI agents reach for these because their training data has countless C++ textbook examples with them. Reference: cpp/printf-debug v0.
|
|
27854
|
+
advice: "Replace with `spdlog::info(...)`, `LOG(INFO) << ...` (glog), or `ABSL_LOG(INFO) << ...` (Abseil). All of these are level-aware and have a configurable sink, and they route to stderr by default. `printf` / `std::cout` have no levels, no redaction, no sink routing, and can't be silenced in release builds. AI agents reach for these because their training data has countless C++ textbook examples with them. Reference: cpp/printf-debug v0.34.7 (refined to skip test files for higher precision)."
|
|
27853
27855
|
});
|
|
27854
27856
|
return issues;
|
|
27855
27857
|
}
|
|
@@ -31295,14 +31297,14 @@ var init_object_singleton_misuse = __esm({
|
|
|
31295
31297
|
});
|
|
31296
31298
|
|
|
31297
31299
|
// src/rules/kotlin/println-as-log.ts
|
|
31298
|
-
var PRINTLN_REGEX, REAL_LOGGING_IMPORT_REGEX2,
|
|
31300
|
+
var PRINTLN_REGEX, REAL_LOGGING_IMPORT_REGEX2, TEST_FILE_REGEX2, kotlinPrintlnAsLogRule;
|
|
31299
31301
|
var init_println_as_log = __esm({
|
|
31300
31302
|
"src/rules/kotlin/println-as-log.ts"() {
|
|
31301
31303
|
"use strict";
|
|
31302
31304
|
init_rule();
|
|
31303
31305
|
PRINTLN_REGEX = /\bprintln\s*\(/g;
|
|
31304
31306
|
REAL_LOGGING_IMPORT_REGEX2 = /\bimport\s+(?:android\.util\.Log|org\.slf4j\.|io\.github\.oshai\.kotlinlogging|kotlin\.logging|co\.touchlab\.kermit|com\.github\.ajalt\.timber|org\.apache\.logging\.log4j)/;
|
|
31305
|
-
|
|
31307
|
+
TEST_FILE_REGEX2 = /(?:\/src\/test\/|\/test\/|\/Tests\/|\/Test\.kt|\/Tests\.kt|Tests\.kt$|Test\.kt$)/;
|
|
31306
31308
|
kotlinPrintlnAsLogRule = createRule({
|
|
31307
31309
|
id: "kotlin/println-as-log",
|
|
31308
31310
|
category: "logic",
|
|
@@ -31317,7 +31319,7 @@ var init_println_as_log = __esm({
|
|
|
31317
31319
|
const source = facts.v2?._source;
|
|
31318
31320
|
if (!source) return issues;
|
|
31319
31321
|
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
31320
|
-
if (
|
|
31322
|
+
if (TEST_FILE_REGEX2.test(facts.filePath)) return issues;
|
|
31321
31323
|
if (REAL_LOGGING_IMPORT_REGEX2.test(source)) return issues;
|
|
31322
31324
|
let m;
|
|
31323
31325
|
PRINTLN_REGEX.lastIndex = 0;
|
|
@@ -31439,9 +31441,9 @@ var init_sql_string_concat2 = __esm({
|
|
|
31439
31441
|
"src/rules/kotlin/sql-string-concat.ts"() {
|
|
31440
31442
|
"use strict";
|
|
31441
31443
|
init_rule();
|
|
31442
|
-
SQL_KEYWORD_REGEX2 = /\b(
|
|
31444
|
+
SQL_KEYWORD_REGEX2 = /\b(SELECT|INSERT\s+INTO|UPDATE|DELETE\s+FROM|CREATE\s+TABLE|DROP\s+TABLE|ALTER\s+TABLE)\b/i;
|
|
31443
31445
|
UNSAFE_REGEX2 = /(?:\+|\$\{)/;
|
|
31444
|
-
SAFE_REGEX2 = /(?:PreparedStatement|setParameter|setString|setInt|setLong|bind|:name
|
|
31446
|
+
SAFE_REGEX2 = /(?:PreparedStatement|setParameter|setString|setInt|setLong|bind|:name|:\?|\?)/;
|
|
31445
31447
|
kotlinSqlStringConcatRule = createRule({
|
|
31446
31448
|
id: "kotlin/sql-string-concat",
|
|
31447
31449
|
category: "security",
|
|
@@ -31459,7 +31461,14 @@ var init_sql_string_concat2 = __esm({
|
|
|
31459
31461
|
const lines = source.split("\n");
|
|
31460
31462
|
for (let i = 0; i < lines.length; i++) {
|
|
31461
31463
|
const line = lines[i];
|
|
31462
|
-
|
|
31464
|
+
const keywordMatch = SQL_KEYWORD_REGEX2.exec(line);
|
|
31465
|
+
if (!keywordMatch) continue;
|
|
31466
|
+
const keywordIdx = keywordMatch.index;
|
|
31467
|
+
let j = keywordIdx - 1;
|
|
31468
|
+
while (j >= 0 && /\s/.test(line[j])) j--;
|
|
31469
|
+
if (j < 0) continue;
|
|
31470
|
+
const prevChar = line[j];
|
|
31471
|
+
if (prevChar !== '"' && prevChar !== "'" && prevChar !== "=") continue;
|
|
31463
31472
|
if (!UNSAFE_REGEX2.test(line)) continue;
|
|
31464
31473
|
if (SAFE_REGEX2.test(line)) continue;
|
|
31465
31474
|
issues.push({
|
|
@@ -31470,7 +31479,7 @@ var init_sql_string_concat2 = __esm({
|
|
|
31470
31479
|
message: `SQL query built via string concat/template at line ${i + 1}`,
|
|
31471
31480
|
line: i + 1,
|
|
31472
31481
|
column: 1,
|
|
31473
|
-
advice: 'Use a PreparedStatement (JDBC), setParameter() (Exposed), or an ORM (Room, jOOQ). String concatenation or template interpolation into a SQL query is the canonical SQL-injection pattern \u2014 even "trusted" inputs (signed JWT, internal config) can be influenced by an attacker. Reference: kotlin/sql-string-concat v0.
|
|
31482
|
+
advice: 'Use a PreparedStatement (JDBC), setParameter() (Exposed), or an ORM (Room, jOOQ). String concatenation or template interpolation into a SQL query is the canonical SQL-injection pattern \u2014 even "trusted" inputs (signed JWT, internal config) can be influenced by an attacker. Reference: kotlin/sql-string-concat v0.34.8 (refined: require SQL keyword to start a string literal; fixed SAFE_REGEX bug).'
|
|
31474
31483
|
});
|
|
31475
31484
|
}
|
|
31476
31485
|
return issues;
|
|
@@ -41176,14 +41185,14 @@ var init_implicitly_unwrapped_optional = __esm({
|
|
|
41176
41185
|
});
|
|
41177
41186
|
|
|
41178
41187
|
// src/rules/swift/print-debug.ts
|
|
41179
|
-
var PRINT_REGEX, DEFAULT_THRESHOLD2,
|
|
41188
|
+
var PRINT_REGEX, DEFAULT_THRESHOLD2, TEST_FILE_REGEX3, swiftPrintDebugRule;
|
|
41180
41189
|
var init_print_debug = __esm({
|
|
41181
41190
|
"src/rules/swift/print-debug.ts"() {
|
|
41182
41191
|
"use strict";
|
|
41183
41192
|
init_rule();
|
|
41184
41193
|
PRINT_REGEX = /\bprint\s*\(/g;
|
|
41185
41194
|
DEFAULT_THRESHOLD2 = 1;
|
|
41186
|
-
|
|
41195
|
+
TEST_FILE_REGEX3 = /(?:\/Tests\/|\/Tests\.swift|\/Test\.swift|Tests\.swift$|Test\.swift$)/;
|
|
41187
41196
|
swiftPrintDebugRule = createRule({
|
|
41188
41197
|
id: "swift/print-debug",
|
|
41189
41198
|
category: "typo",
|
|
@@ -41198,7 +41207,7 @@ var init_print_debug = __esm({
|
|
|
41198
41207
|
const source = facts.v2?._source;
|
|
41199
41208
|
if (!source) return issues;
|
|
41200
41209
|
if (!/\.swift$/i.test(facts.filePath)) return issues;
|
|
41201
|
-
if (
|
|
41210
|
+
if (TEST_FILE_REGEX3.test(facts.filePath)) return issues;
|
|
41202
41211
|
const matches = [];
|
|
41203
41212
|
let m;
|
|
41204
41213
|
PRINT_REGEX.lastIndex = 0;
|
|
@@ -51625,7 +51634,7 @@ var init_signal_strength = __esm({
|
|
|
51625
51634
|
precision: 0.0556,
|
|
51626
51635
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
51627
51636
|
verdict: "DORMANT",
|
|
51628
|
-
_calibrationNote:
|
|
51637
|
+
_calibrationNote: 'v0.34.8: REFINED \u2014 rule now requires the SQL keyword to be the start of a string literal (preceded by `"`, `\'`, or `=`), and fixed a bug in the SAFE_REGEX (the `:??` was malformed, should be `:?`). Per-file unique v9 Kotlin calibration (2698 neg, 213 pos): 1 TP file, 17 FP files, ratio=0.75 (DORMANT). 18 total fires. The refinement is expected to push precision from 5.6% to 25%+ by removing lines where SELECT/INSERT appears in string values (e.g. `val msg = "Selected 1 row: \\$count"`). Also fixed the bug where `:??` in SAFE_REGEX didn\'t match Java/Kotlin named parameters (`:id`). The full v9 re-calibration is part of the broader v0.34.8/v0.34.9 pipeline. INSUFFICIENT_DATA: pos arm 213 files (below 10k floor).',
|
|
51629
51638
|
aiSpecific: false,
|
|
51630
51639
|
_v9Verdict: "DORMANT",
|
|
51631
51640
|
_v9Lift: 0.75,
|
|
@@ -51969,7 +51978,7 @@ var init_signal_strength = __esm({
|
|
|
51969
51978
|
precision: 0.4407,
|
|
51970
51979
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
51971
51980
|
verdict: "OK",
|
|
51972
|
-
_calibrationNote: "v0.
|
|
51981
|
+
_calibrationNote: "v0.34.7: REFINED \u2014 rule now skips test files (gtest, catch2, doctest conventions: *_test.cpp, *_test.cc, /tests/ dir, *Test.cpp, *Test.cc, *_unittest.cpp). Per-file unique v9 C++ calibration (5107 neg, 1655 pos): 156 TP files, 198 FP files, ratio=2.43 (OK, fourth positive-signal in v9 history). precision=44.07% (below 50% USEFUL threshold); verdict=OK. The refinement is expected to push precision from 44% to 50%+ by removing gtest test output fires (which were a significant portion of FPs in the v0.33.0 measurement). The full v9 re-calibration is part of the broader v0.34.5/v0.34.7 pipeline; see v0.34.1's Four-language validation section. Same direction as kotlin/println-as-log (1.84), java/system-out-println (1.73 refined, 3.29 unrefined), swift/print-debug (1.13). INSUFFICIENT_DATA: pos arm 1655 files (below 10k floor).",
|
|
51973
51982
|
aiSpecific: true,
|
|
51974
51983
|
_v7Verdict: "DORMANT",
|
|
51975
51984
|
_v7Lift: 1,
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ var VERSION;
|
|
|
19
19
|
var init_header = __esm({
|
|
20
20
|
"src/types/_header.ts"() {
|
|
21
21
|
"use strict";
|
|
22
|
-
VERSION = "0.34.
|
|
22
|
+
VERSION = "0.34.8";
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
|
|
@@ -27792,7 +27792,7 @@ var init_magic_numbers = __esm({
|
|
|
27792
27792
|
});
|
|
27793
27793
|
|
|
27794
27794
|
// src/rules/cpp/printf-debug.ts
|
|
27795
|
-
var PRINTF_FAMILY_REGEX, COUT_LITERAL_REGEX, STD_COUT_BARE_REGEX, THRESHOLD_DEFAULT, cppPrintfDebugRule;
|
|
27795
|
+
var PRINTF_FAMILY_REGEX, COUT_LITERAL_REGEX, STD_COUT_BARE_REGEX, THRESHOLD_DEFAULT, TEST_FILE_REGEX, cppPrintfDebugRule;
|
|
27796
27796
|
var init_printf_debug = __esm({
|
|
27797
27797
|
"src/rules/cpp/printf-debug.ts"() {
|
|
27798
27798
|
"use strict";
|
|
@@ -27801,6 +27801,7 @@ var init_printf_debug = __esm({
|
|
|
27801
27801
|
COUT_LITERAL_REGEX = /std\s*::\s*(?:cout|cerr|clog)\s*<<\s*"[^"]*"/g;
|
|
27802
27802
|
STD_COUT_BARE_REGEX = /std\s*::\s*(?:cout|cerr|clog)\s*<<\s*'[^']*'/g;
|
|
27803
27803
|
THRESHOLD_DEFAULT = 1;
|
|
27804
|
+
TEST_FILE_REGEX = /(?:\/tests?\/|_test\.cc|_test\.cpp|Test\.cc|Test\.cpp|Tests\.cc|Tests\.cpp|_unittest\.cc|_unittest\.cpp)/;
|
|
27804
27805
|
cppPrintfDebugRule = createRule({
|
|
27805
27806
|
id: "cpp/printf-debug",
|
|
27806
27807
|
category: "typo",
|
|
@@ -27815,6 +27816,7 @@ var init_printf_debug = __esm({
|
|
|
27815
27816
|
const source = facts.v2?._source;
|
|
27816
27817
|
if (!source) return issues;
|
|
27817
27818
|
if (!/\.(cpp|cc|cxx|h|hpp|hh|hxx|H)$/i.test(facts.filePath)) return issues;
|
|
27819
|
+
if (TEST_FILE_REGEX.test(facts.filePath)) return issues;
|
|
27818
27820
|
const printfCount = (source.match(PRINTF_FAMILY_REGEX) ?? []).length;
|
|
27819
27821
|
let viaPrintf = false;
|
|
27820
27822
|
if (printfCount > context.threshold) {
|
|
@@ -27831,7 +27833,7 @@ var init_printf_debug = __esm({
|
|
|
27831
27833
|
message: viaPrintf ? `${printfCount} printf-family calls \u2014 use spdlog / glog / AbslLog` : "std::cout/cerr/clog with a string literal \u2014 use spdlog / glog / AbslLog",
|
|
27832
27834
|
line: 1,
|
|
27833
27835
|
column: 1,
|
|
27834
|
-
advice: "Replace with `spdlog::info(...)`, `LOG(INFO) << ...` (glog), or `ABSL_LOG(INFO) << ...` (Abseil). All of these are level-aware and have a configurable sink, and they route to stderr by default. `printf` / `std::cout` have no levels, no redaction, no sink routing, and can't be silenced in release builds. AI agents reach for these because their training data has countless C++ textbook examples with them. Reference: cpp/printf-debug v0.
|
|
27836
|
+
advice: "Replace with `spdlog::info(...)`, `LOG(INFO) << ...` (glog), or `ABSL_LOG(INFO) << ...` (Abseil). All of these are level-aware and have a configurable sink, and they route to stderr by default. `printf` / `std::cout` have no levels, no redaction, no sink routing, and can't be silenced in release builds. AI agents reach for these because their training data has countless C++ textbook examples with them. Reference: cpp/printf-debug v0.34.7 (refined to skip test files for higher precision)."
|
|
27835
27837
|
});
|
|
27836
27838
|
return issues;
|
|
27837
27839
|
}
|
|
@@ -31276,14 +31278,14 @@ var init_object_singleton_misuse = __esm({
|
|
|
31276
31278
|
});
|
|
31277
31279
|
|
|
31278
31280
|
// src/rules/kotlin/println-as-log.ts
|
|
31279
|
-
var PRINTLN_REGEX, REAL_LOGGING_IMPORT_REGEX2,
|
|
31281
|
+
var PRINTLN_REGEX, REAL_LOGGING_IMPORT_REGEX2, TEST_FILE_REGEX2, kotlinPrintlnAsLogRule;
|
|
31280
31282
|
var init_println_as_log = __esm({
|
|
31281
31283
|
"src/rules/kotlin/println-as-log.ts"() {
|
|
31282
31284
|
"use strict";
|
|
31283
31285
|
init_rule();
|
|
31284
31286
|
PRINTLN_REGEX = /\bprintln\s*\(/g;
|
|
31285
31287
|
REAL_LOGGING_IMPORT_REGEX2 = /\bimport\s+(?:android\.util\.Log|org\.slf4j\.|io\.github\.oshai\.kotlinlogging|kotlin\.logging|co\.touchlab\.kermit|com\.github\.ajalt\.timber|org\.apache\.logging\.log4j)/;
|
|
31286
|
-
|
|
31288
|
+
TEST_FILE_REGEX2 = /(?:\/src\/test\/|\/test\/|\/Tests\/|\/Test\.kt|\/Tests\.kt|Tests\.kt$|Test\.kt$)/;
|
|
31287
31289
|
kotlinPrintlnAsLogRule = createRule({
|
|
31288
31290
|
id: "kotlin/println-as-log",
|
|
31289
31291
|
category: "logic",
|
|
@@ -31298,7 +31300,7 @@ var init_println_as_log = __esm({
|
|
|
31298
31300
|
const source = facts.v2?._source;
|
|
31299
31301
|
if (!source) return issues;
|
|
31300
31302
|
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
31301
|
-
if (
|
|
31303
|
+
if (TEST_FILE_REGEX2.test(facts.filePath)) return issues;
|
|
31302
31304
|
if (REAL_LOGGING_IMPORT_REGEX2.test(source)) return issues;
|
|
31303
31305
|
let m;
|
|
31304
31306
|
PRINTLN_REGEX.lastIndex = 0;
|
|
@@ -31420,9 +31422,9 @@ var init_sql_string_concat2 = __esm({
|
|
|
31420
31422
|
"src/rules/kotlin/sql-string-concat.ts"() {
|
|
31421
31423
|
"use strict";
|
|
31422
31424
|
init_rule();
|
|
31423
|
-
SQL_KEYWORD_REGEX2 = /\b(
|
|
31425
|
+
SQL_KEYWORD_REGEX2 = /\b(SELECT|INSERT\s+INTO|UPDATE|DELETE\s+FROM|CREATE\s+TABLE|DROP\s+TABLE|ALTER\s+TABLE)\b/i;
|
|
31424
31426
|
UNSAFE_REGEX2 = /(?:\+|\$\{)/;
|
|
31425
|
-
SAFE_REGEX2 = /(?:PreparedStatement|setParameter|setString|setInt|setLong|bind|:name
|
|
31427
|
+
SAFE_REGEX2 = /(?:PreparedStatement|setParameter|setString|setInt|setLong|bind|:name|:\?|\?)/;
|
|
31426
31428
|
kotlinSqlStringConcatRule = createRule({
|
|
31427
31429
|
id: "kotlin/sql-string-concat",
|
|
31428
31430
|
category: "security",
|
|
@@ -31440,7 +31442,14 @@ var init_sql_string_concat2 = __esm({
|
|
|
31440
31442
|
const lines = source.split("\n");
|
|
31441
31443
|
for (let i = 0; i < lines.length; i++) {
|
|
31442
31444
|
const line = lines[i];
|
|
31443
|
-
|
|
31445
|
+
const keywordMatch = SQL_KEYWORD_REGEX2.exec(line);
|
|
31446
|
+
if (!keywordMatch) continue;
|
|
31447
|
+
const keywordIdx = keywordMatch.index;
|
|
31448
|
+
let j = keywordIdx - 1;
|
|
31449
|
+
while (j >= 0 && /\s/.test(line[j])) j--;
|
|
31450
|
+
if (j < 0) continue;
|
|
31451
|
+
const prevChar = line[j];
|
|
31452
|
+
if (prevChar !== '"' && prevChar !== "'" && prevChar !== "=") continue;
|
|
31444
31453
|
if (!UNSAFE_REGEX2.test(line)) continue;
|
|
31445
31454
|
if (SAFE_REGEX2.test(line)) continue;
|
|
31446
31455
|
issues.push({
|
|
@@ -31451,7 +31460,7 @@ var init_sql_string_concat2 = __esm({
|
|
|
31451
31460
|
message: `SQL query built via string concat/template at line ${i + 1}`,
|
|
31452
31461
|
line: i + 1,
|
|
31453
31462
|
column: 1,
|
|
31454
|
-
advice: 'Use a PreparedStatement (JDBC), setParameter() (Exposed), or an ORM (Room, jOOQ). String concatenation or template interpolation into a SQL query is the canonical SQL-injection pattern \u2014 even "trusted" inputs (signed JWT, internal config) can be influenced by an attacker. Reference: kotlin/sql-string-concat v0.
|
|
31463
|
+
advice: 'Use a PreparedStatement (JDBC), setParameter() (Exposed), or an ORM (Room, jOOQ). String concatenation or template interpolation into a SQL query is the canonical SQL-injection pattern \u2014 even "trusted" inputs (signed JWT, internal config) can be influenced by an attacker. Reference: kotlin/sql-string-concat v0.34.8 (refined: require SQL keyword to start a string literal; fixed SAFE_REGEX bug).'
|
|
31455
31464
|
});
|
|
31456
31465
|
}
|
|
31457
31466
|
return issues;
|
|
@@ -41157,14 +41166,14 @@ var init_implicitly_unwrapped_optional = __esm({
|
|
|
41157
41166
|
});
|
|
41158
41167
|
|
|
41159
41168
|
// src/rules/swift/print-debug.ts
|
|
41160
|
-
var PRINT_REGEX, DEFAULT_THRESHOLD2,
|
|
41169
|
+
var PRINT_REGEX, DEFAULT_THRESHOLD2, TEST_FILE_REGEX3, swiftPrintDebugRule;
|
|
41161
41170
|
var init_print_debug = __esm({
|
|
41162
41171
|
"src/rules/swift/print-debug.ts"() {
|
|
41163
41172
|
"use strict";
|
|
41164
41173
|
init_rule();
|
|
41165
41174
|
PRINT_REGEX = /\bprint\s*\(/g;
|
|
41166
41175
|
DEFAULT_THRESHOLD2 = 1;
|
|
41167
|
-
|
|
41176
|
+
TEST_FILE_REGEX3 = /(?:\/Tests\/|\/Tests\.swift|\/Test\.swift|Tests\.swift$|Test\.swift$)/;
|
|
41168
41177
|
swiftPrintDebugRule = createRule({
|
|
41169
41178
|
id: "swift/print-debug",
|
|
41170
41179
|
category: "typo",
|
|
@@ -41179,7 +41188,7 @@ var init_print_debug = __esm({
|
|
|
41179
41188
|
const source = facts.v2?._source;
|
|
41180
41189
|
if (!source) return issues;
|
|
41181
41190
|
if (!/\.swift$/i.test(facts.filePath)) return issues;
|
|
41182
|
-
if (
|
|
41191
|
+
if (TEST_FILE_REGEX3.test(facts.filePath)) return issues;
|
|
41183
41192
|
const matches = [];
|
|
41184
41193
|
let m;
|
|
41185
41194
|
PRINT_REGEX.lastIndex = 0;
|
|
@@ -51603,7 +51612,7 @@ var init_signal_strength = __esm({
|
|
|
51603
51612
|
precision: 0.0556,
|
|
51604
51613
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
51605
51614
|
verdict: "DORMANT",
|
|
51606
|
-
_calibrationNote:
|
|
51615
|
+
_calibrationNote: 'v0.34.8: REFINED \u2014 rule now requires the SQL keyword to be the start of a string literal (preceded by `"`, `\'`, or `=`), and fixed a bug in the SAFE_REGEX (the `:??` was malformed, should be `:?`). Per-file unique v9 Kotlin calibration (2698 neg, 213 pos): 1 TP file, 17 FP files, ratio=0.75 (DORMANT). 18 total fires. The refinement is expected to push precision from 5.6% to 25%+ by removing lines where SELECT/INSERT appears in string values (e.g. `val msg = "Selected 1 row: \\$count"`). Also fixed the bug where `:??` in SAFE_REGEX didn\'t match Java/Kotlin named parameters (`:id`). The full v9 re-calibration is part of the broader v0.34.8/v0.34.9 pipeline. INSUFFICIENT_DATA: pos arm 213 files (below 10k floor).',
|
|
51607
51616
|
aiSpecific: false,
|
|
51608
51617
|
_v9Verdict: "DORMANT",
|
|
51609
51618
|
_v9Lift: 0.75,
|
|
@@ -51947,7 +51956,7 @@ var init_signal_strength = __esm({
|
|
|
51947
51956
|
precision: 0.4407,
|
|
51948
51957
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
51949
51958
|
verdict: "OK",
|
|
51950
|
-
_calibrationNote: "v0.
|
|
51959
|
+
_calibrationNote: "v0.34.7: REFINED \u2014 rule now skips test files (gtest, catch2, doctest conventions: *_test.cpp, *_test.cc, /tests/ dir, *Test.cpp, *Test.cc, *_unittest.cpp). Per-file unique v9 C++ calibration (5107 neg, 1655 pos): 156 TP files, 198 FP files, ratio=2.43 (OK, fourth positive-signal in v9 history). precision=44.07% (below 50% USEFUL threshold); verdict=OK. The refinement is expected to push precision from 44% to 50%+ by removing gtest test output fires (which were a significant portion of FPs in the v0.33.0 measurement). The full v9 re-calibration is part of the broader v0.34.5/v0.34.7 pipeline; see v0.34.1's Four-language validation section. Same direction as kotlin/println-as-log (1.84), java/system-out-println (1.73 refined, 3.29 unrefined), swift/print-debug (1.13). INSUFFICIENT_DATA: pos arm 1655 files (below 10k floor).",
|
|
51951
51960
|
aiSpecific: true,
|
|
51952
51961
|
_v7Verdict: "DORMANT",
|
|
51953
51962
|
_v7Lift: 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slopbrick",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.8",
|
|
4
4
|
"description": "Discovered, modeled, and governed repository structure. SlopBrick scans source code, classifies it against 95+ rules in 15 categories, computes 4 scores (aiSlopScore: lower=cleaner, engineeringHygiene, security, repositoryHealth composite), and persists the structure for AI agents and CI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|