tamperward 2.29.6 → 2.29.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/cli/index.js +143 -44
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3478,7 +3478,7 @@ function skipRegexLiteral(line, start) {
|
|
|
3478
3478
|
}
|
|
3479
3479
|
return line.length - 1;
|
|
3480
3480
|
}
|
|
3481
|
-
var CODE, EXT, COMMON, IMPORTS, HASH_COMMENT, DEBUG_ONLY, SLASH_COMMENT, HASH_COMMENT_LANGS, REGEX_KEYWORDS;
|
|
3481
|
+
var CODE, EXT, COMMON, IMPORTS, HASH_COMMENT, DEBUG_ONLY, SLASH_COMMENT, HASH_COMMENT_LANGS, CommentStringMasker, REGEX_KEYWORDS;
|
|
3482
3482
|
var init_files = __esm({
|
|
3483
3483
|
"src/detectors/files.ts"() {
|
|
3484
3484
|
"use strict";
|
|
@@ -3510,6 +3510,90 @@ var init_files = __esm({
|
|
|
3510
3510
|
DEBUG_ONLY = /^(?:console\.\w+\(.*\)\s*;?|debugger\s*;?)$/;
|
|
3511
3511
|
SLASH_COMMENT = /^(?:\/\/|\/\*|\*(?:\s|\/|$))/;
|
|
3512
3512
|
HASH_COMMENT_LANGS = /* @__PURE__ */ new Set(["py", "rb", "php"]);
|
|
3513
|
+
CommentStringMasker = class {
|
|
3514
|
+
constructor(maskStrings = true) {
|
|
3515
|
+
this.maskStrings = maskStrings;
|
|
3516
|
+
}
|
|
3517
|
+
maskStrings;
|
|
3518
|
+
stack = [];
|
|
3519
|
+
mask(line) {
|
|
3520
|
+
const out3 = line.split("");
|
|
3521
|
+
for (const f of this.stack) if (f.kind === "string" || f.kind === "template") f.carried = true;
|
|
3522
|
+
let i = 0;
|
|
3523
|
+
while (i < line.length) {
|
|
3524
|
+
const top = this.stack[this.stack.length - 1];
|
|
3525
|
+
const ch = line[i];
|
|
3526
|
+
const next = line[i + 1];
|
|
3527
|
+
if (top?.kind === "block") {
|
|
3528
|
+
out3[i] = " ";
|
|
3529
|
+
if (ch === "*" && next === "/") {
|
|
3530
|
+
out3[i + 1] = " ";
|
|
3531
|
+
this.stack.pop();
|
|
3532
|
+
i += 2;
|
|
3533
|
+
continue;
|
|
3534
|
+
}
|
|
3535
|
+
i++;
|
|
3536
|
+
continue;
|
|
3537
|
+
}
|
|
3538
|
+
if (top?.kind === "string" || top?.kind === "template") {
|
|
3539
|
+
const blank = this.maskStrings || top.carried;
|
|
3540
|
+
if (ch === "\\") {
|
|
3541
|
+
if (blank) {
|
|
3542
|
+
out3[i] = " ";
|
|
3543
|
+
if (i + 1 < line.length) out3[i + 1] = " ";
|
|
3544
|
+
}
|
|
3545
|
+
i += 2;
|
|
3546
|
+
continue;
|
|
3547
|
+
}
|
|
3548
|
+
if (top.kind === "string" ? ch === top.quote : ch === "`") {
|
|
3549
|
+
this.stack.pop();
|
|
3550
|
+
i++;
|
|
3551
|
+
continue;
|
|
3552
|
+
}
|
|
3553
|
+
if (top.kind === "template" && ch === "$" && next === "{") {
|
|
3554
|
+
this.stack.push({ kind: "subst", depth: 1 });
|
|
3555
|
+
i += 2;
|
|
3556
|
+
continue;
|
|
3557
|
+
}
|
|
3558
|
+
if (blank) out3[i] = " ";
|
|
3559
|
+
i++;
|
|
3560
|
+
continue;
|
|
3561
|
+
}
|
|
3562
|
+
if (ch === "/" && next === "/") {
|
|
3563
|
+
for (let j = i; j < line.length; j++) out3[j] = " ";
|
|
3564
|
+
i = line.length;
|
|
3565
|
+
continue;
|
|
3566
|
+
}
|
|
3567
|
+
if (ch === "/" && next === "*") {
|
|
3568
|
+
out3[i] = " ";
|
|
3569
|
+
out3[i + 1] = " ";
|
|
3570
|
+
this.stack.push({ kind: "block" });
|
|
3571
|
+
i += 2;
|
|
3572
|
+
continue;
|
|
3573
|
+
}
|
|
3574
|
+
if (ch === "`") {
|
|
3575
|
+
this.stack.push({ kind: "template", carried: false });
|
|
3576
|
+
i++;
|
|
3577
|
+
continue;
|
|
3578
|
+
}
|
|
3579
|
+
if (ch === '"' || ch === "'") {
|
|
3580
|
+
this.stack.push({ kind: "string", quote: ch, carried: false });
|
|
3581
|
+
i++;
|
|
3582
|
+
continue;
|
|
3583
|
+
}
|
|
3584
|
+
if (ch === "/" && regexPosition(line.slice(0, i))) {
|
|
3585
|
+
i = skipRegexLiteral(line, i) + 1;
|
|
3586
|
+
continue;
|
|
3587
|
+
}
|
|
3588
|
+
if (top?.kind === "subst") {
|
|
3589
|
+
if (ch === "{") top.depth++;
|
|
3590
|
+
else if (ch === "}" && --top.depth === 0) this.stack.pop();
|
|
3591
|
+
}
|
|
3592
|
+
i++;
|
|
3593
|
+
}
|
|
3594
|
+
return out3.join("");
|
|
3595
|
+
}
|
|
3596
|
+
};
|
|
3513
3597
|
REGEX_KEYWORDS = /* @__PURE__ */ new Set([
|
|
3514
3598
|
"return",
|
|
3515
3599
|
"throw",
|
|
@@ -3885,29 +3969,35 @@ var init_ts_any_cast = __esm({
|
|
|
3885
3969
|
}
|
|
3886
3970
|
const jsdocCast = JS_FILE.test(c.path) ? new RegExp(JSDOC_ANY_CAST.source) : null;
|
|
3887
3971
|
const aliasMap = aliasMapForAddedLines(c);
|
|
3888
|
-
for (const
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3972
|
+
for (const h of c.hunks) {
|
|
3973
|
+
const masker = new CommentStringMasker();
|
|
3974
|
+
for (const l of h.lines) {
|
|
3975
|
+
if (l.type === "del") continue;
|
|
3976
|
+
const code2 = masker.mask(l.content);
|
|
3977
|
+
if (l.type !== "add") continue;
|
|
3978
|
+
if (NARROW_LINE.test(code2) || lineHasRow4Cast(code2, aliasMap) || lineHasLiveDirective(l.content) || jsdocCast && jsdocCast.test(l.content)) {
|
|
3979
|
+
out3.push(
|
|
3980
|
+
makeFinding(inTest ? WARN_RULE : BLOCK_RULE, policy, {
|
|
3981
|
+
file: c.path,
|
|
3982
|
+
line: l.newLine ?? void 0,
|
|
3983
|
+
message: inTest ? "Type-checker escape in a test file (test infrastructure \u2014 flagged, not blocked)." : "Type safety discarded: an explicit cast/suppression was added.",
|
|
3984
|
+
evidence: l.content.trim(),
|
|
3985
|
+
remediation: inTest ? WARN_REMEDIATION : BLOCK_REMEDIATION,
|
|
3986
|
+
defaultSeverity: inTest ? "warn" : "block"
|
|
3987
|
+
})
|
|
3988
|
+
);
|
|
3989
|
+
} else if (BROAD_LINE.test(code2)) {
|
|
3990
|
+
out3.push(
|
|
3991
|
+
makeFinding(WARN_RULE, policy, {
|
|
3992
|
+
file: c.path,
|
|
3993
|
+
line: l.newLine ?? void 0,
|
|
3994
|
+
message: "Type laundered to `any` in a type/generic position.",
|
|
3995
|
+
evidence: l.content.trim(),
|
|
3996
|
+
remediation: WARN_REMEDIATION,
|
|
3997
|
+
defaultSeverity: "warn"
|
|
3998
|
+
})
|
|
3999
|
+
);
|
|
4000
|
+
}
|
|
3911
4001
|
}
|
|
3912
4002
|
}
|
|
3913
4003
|
}
|
|
@@ -4940,23 +5030,30 @@ var init_test_skip = __esm({
|
|
|
4940
5030
|
);
|
|
4941
5031
|
}
|
|
4942
5032
|
}
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
const
|
|
4946
|
-
for (const
|
|
4947
|
-
if (
|
|
4948
|
-
|
|
4949
|
-
if (
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
5033
|
+
const maskJs = lang === "js" || lang == null;
|
|
5034
|
+
for (const h of c.hunks) {
|
|
5035
|
+
const masker = maskJs ? new CommentStringMasker(false) : null;
|
|
5036
|
+
for (const l of h.lines) {
|
|
5037
|
+
if (l.type === "del") continue;
|
|
5038
|
+
const code2 = masker ? masker.mask(l.content) : l.content;
|
|
5039
|
+
if (l.type !== "add") continue;
|
|
5040
|
+
if (l.newLine != null && astHitLines.has(l.newLine)) continue;
|
|
5041
|
+
const comment = isCommentLine(code2.trim(), lang);
|
|
5042
|
+
for (const p of patterns) {
|
|
5043
|
+
if (astAuthoritative && p.astOwned && !(l.newLine != null && unowned.has(l.newLine))) continue;
|
|
5044
|
+
if (comment && !p.comment) continue;
|
|
5045
|
+
if (matchesOutsideString(p, p.comment ? l.content : code2, lang)) {
|
|
5046
|
+
out3.push(
|
|
5047
|
+
makeFinding(RULE4, policy, {
|
|
5048
|
+
file: c.path,
|
|
5049
|
+
line: l.newLine ?? void 0,
|
|
5050
|
+
message: `Test skipped or narrowed: ${p.why}.`,
|
|
5051
|
+
evidence: l.content.trim(),
|
|
5052
|
+
remediation: "Make the test pass rather than skipping it. If it is genuinely obsolete, a human must sign off."
|
|
5053
|
+
})
|
|
5054
|
+
);
|
|
5055
|
+
break;
|
|
5056
|
+
}
|
|
4960
5057
|
}
|
|
4961
5058
|
}
|
|
4962
5059
|
}
|
|
@@ -9914,7 +10011,7 @@ function namesProtectedSnapshot(seg, policy) {
|
|
|
9914
10011
|
}
|
|
9915
10012
|
return null;
|
|
9916
10013
|
}
|
|
9917
|
-
var RULE12, RUNNER3, PM_TEST_SCRIPT, UPDATE_ANY, UPDATE_WITH_RUNNER, INSTA_ACCEPT, UPDATE_EXPECT, REGEN_SCRIPT, MUTATE, snapshotRewrite;
|
|
10014
|
+
var RULE12, RUNNER3, PM_TEST_SCRIPT, UPDATE_ANY, UPDATE_WITH_RUNNER, INSTA_ACCEPT, UPDATE_EXPECT, TAP_SNAPSHOT, REGEN_SCRIPT, MUTATE, snapshotRewrite;
|
|
9918
10015
|
var init_snapshot_rewrite = __esm({
|
|
9919
10016
|
"src/detectors/snapshot-rewrite.ts"() {
|
|
9920
10017
|
"use strict";
|
|
@@ -9922,12 +10019,13 @@ var init_snapshot_rewrite = __esm({
|
|
|
9922
10019
|
init_finding();
|
|
9923
10020
|
init_command();
|
|
9924
10021
|
RULE12 = "snapshot-rewrite";
|
|
9925
|
-
RUNNER3 = /\b(?:jest|vitest|playwright|ava)\b/;
|
|
10022
|
+
RUNNER3 = /\b(?:jest|vitest|playwright|ava|tap)\b/;
|
|
9926
10023
|
PM_TEST_SCRIPT = /(?:^|\s)(?:npm|pnpm|yarn|bun)\s+(?:t|tst|test|run(?:-script)?\s+\S*test\S*)(?:\s|$)/;
|
|
9927
10024
|
UPDATE_ANY = /--(?:update-?[sS]napshots?|test-update-snapshots|snapshot-update)\b/;
|
|
9928
|
-
UPDATE_WITH_RUNNER = /(?:^|\s)(?:-u|--update)(?:\s|$)/;
|
|
10025
|
+
UPDATE_WITH_RUNNER = /(?:^|\s)(?:-u|--update|--snapshot)(?:=(?:1|true))?(?:\s|$)/;
|
|
9929
10026
|
INSTA_ACCEPT = /\bcargo\s+insta\s+(?:accept\b|.*\s--accept\b)/;
|
|
9930
10027
|
UPDATE_EXPECT = /(?:^|\s)UPDATE_EXPECT=\S+/;
|
|
10028
|
+
TAP_SNAPSHOT = /(?:^|\s)TAP_SNAPSHOT=1(?:\s|$)/;
|
|
9931
10029
|
REGEN_SCRIPT = /\b(?:update|regen(?:erate)?|re?bless)[-_.]?(?:golden|snapshots?|baselines?|expected)\b/i;
|
|
9932
10030
|
MUTATE = /(?:^|\s)(?:rm|cp|mv|tee|truncate|dd)(?:\s|$)|sed\s+-i|>{1,2}|\bfind\b.*\s-(?:delete\b|exec\s+rm\b)|\bgit\s+(?:checkout|restore)\b/;
|
|
9933
10031
|
snapshotRewrite = {
|
|
@@ -9945,6 +10043,7 @@ var init_snapshot_rewrite = __esm({
|
|
|
9945
10043
|
else if ((RUNNER3.test(seg) || PM_TEST_SCRIPT.test(seg)) && UPDATE_WITH_RUNNER.test(seg)) why = "running the test runner in update mode rewrites failing snapshots to match current output";
|
|
9946
10044
|
else if (INSTA_ACCEPT.test(seg)) why = "cargo insta accept rewrites every pending snapshot to match current output";
|
|
9947
10045
|
else if (UPDATE_EXPECT.test(seg)) why = "UPDATE_EXPECT=1 rewrites every expect-test expectation to match current output";
|
|
10046
|
+
else if (TAP_SNAPSHOT.test(seg)) why = "TAP_SNAPSHOT=1 rewrites every node-tap snapshot to match current output";
|
|
9948
10047
|
else if (REGEN_SCRIPT.test(seg)) why = "a regeneration script rewrites the recorded expected output from current output";
|
|
9949
10048
|
else {
|
|
9950
10049
|
const path = MUTATE.test(seg) ? namesProtectedSnapshot(seg, policy) : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamperward",
|
|
3
|
-
"version": "2.29.
|
|
3
|
+
"version": "2.29.8",
|
|
4
4
|
"description": "The deterministic agent-integrity gate. One ruleset, evaluated on the actual diff/commands as a verdict, enforced everywhere a change can be made.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "hexrift",
|