fullshield 0.4.0 → 1.0.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.
@@ -1,118 +1,2 @@
1
- // src/bench/score.ts
2
- var BENCH_CLASSES = [
3
- "sqli",
4
- "nosqli",
5
- "cmdi",
6
- "path",
7
- "xss",
8
- "ssrf",
9
- "redirect",
10
- "eval",
11
- "jwt",
12
- "crypto",
13
- "proto",
14
- "secrets",
15
- "deps",
16
- "config",
17
- "other"
18
- ];
19
- var IN_SCOPE_CLASSES = [
20
- "sqli",
21
- "nosqli",
22
- "cmdi",
23
- "path",
24
- "xss",
25
- "ssrf",
26
- "redirect",
27
- "eval",
28
- "jwt",
29
- "crypto",
30
- "proto",
31
- "secrets",
32
- "deps",
33
- "config"
34
- ];
35
- var RULE_CLASS = {
36
- "SAST-SQLI-001": "sqli",
37
- "SAST-NOSQLI-001": "nosqli",
38
- "SAST-CMDI-001": "cmdi",
39
- "SAST-PATH-001": "path",
40
- "SAST-XSS-001": "xss",
41
- "SAST-SSRF-001": "ssrf",
42
- "SAST-REDIRECT-001": "redirect",
43
- "SAST-EVAL-001": "eval",
44
- "SAST-JWT-001": "jwt",
45
- "SAST-CRYPTO-001": "crypto",
46
- "SAST-PROTO-001": "proto"
47
- };
48
- function classForRule(ruleId) {
49
- if (RULE_CLASS[ruleId]) return RULE_CLASS[ruleId];
50
- if (ruleId.startsWith("SECRET-")) return "secrets";
51
- if (ruleId.startsWith("DEPS-")) return "deps";
52
- if (ruleId.startsWith("CONFIG-")) return "config";
53
- return "other";
54
- }
55
- function normFile(file) {
56
- return file.replaceAll("\\", "/").replace(/^\.\//, "");
57
- }
58
- function findingKey(finding) {
59
- return `${finding.ruleId}|${normFile(finding.file ?? "")}|${finding.line ?? 0}`;
60
- }
61
- function filesMatch(finding, truth) {
62
- if (!finding.file) return false;
63
- const ff = normFile(finding.file);
64
- const tf = normFile(truth.file);
65
- return ff === tf || ff.endsWith(`/${tf}`) || tf.endsWith(`/${ff}`);
66
- }
67
- function isFileLevelFinding(finding) {
68
- return finding.line === void 0 || finding.line === 0;
69
- }
70
- function isTruePositive(finding, truth) {
71
- if (classForRule(finding.ruleId) !== truth.class) return false;
72
- if (!filesMatch(finding, truth)) return false;
73
- const line = finding.line ?? 0;
74
- return Math.abs(line - truth.line) <= 3;
75
- }
76
- function isLineAttributionOnly(findings, truth) {
77
- const same = findings.filter((f) => classForRule(f.ruleId) === truth.class && filesMatch(f, truth));
78
- const ruleIds = new Set(same.map((f) => f.ruleId));
79
- for (const ruleId of ruleIds) {
80
- const group = same.filter((f) => f.ruleId === ruleId);
81
- const lined = group.some((f) => !isFileLevelFinding(f) && Math.abs((f.line ?? 0) - truth.line) <= 3);
82
- const fileLevel = group.some((f) => isFileLevelFinding(f));
83
- if (lined && fileLevel) return true;
84
- }
85
- return false;
86
- }
87
- function scoreFindings(findings, truth) {
88
- const used = /* @__PURE__ */ new Set();
89
- const truePositives = [];
90
- const lineAttributionOnly = [];
91
- const inScope = truth.filter((e) => e.inScope === true);
92
- const outOfScope = truth.filter((e) => e.inScope !== true);
93
- for (const entry of inScope) {
94
- if (isLineAttributionOnly(findings, entry)) {
95
- lineAttributionOnly.push(entry);
96
- continue;
97
- }
98
- const hit = findings.findIndex((f, i) => !used.has(i) && isTruePositive(f, entry));
99
- if (hit >= 0) {
100
- used.add(hit);
101
- truePositives.push(entry);
102
- }
103
- }
104
- const counted = /* @__PURE__ */ new Set([...truePositives, ...lineAttributionOnly]);
105
- const inScopeMisses = inScope.filter((e) => !counted.has(e));
106
- const unmatched = findings.filter((_, i) => !used.has(i));
107
- return { truePositives, lineAttributionOnly, inScopeMisses, outOfScope, unmatched };
108
- }
109
- function precisionFromTriage(entries) {
110
- const realIssue = entries.filter((e) => e.verdict === "realIssue").length;
111
- const falsePositive = entries.filter((e) => e.verdict === "falsePositive").length;
112
- const unsure = entries.filter((e) => e.verdict === "unsure").length;
113
- const den = realIssue + falsePositive;
114
- const precision = den === 0 ? "n/a" : `${(100 * realIssue / den).toFixed(1)}%`;
115
- return { realIssue, falsePositive, unsure, precision };
116
- }
117
-
118
- export { BENCH_CLASSES, IN_SCOPE_CLASSES, classForRule, findingKey, isFileLevelFinding, isLineAttributionOnly, isTruePositive, precisionFromTriage, scoreFindings };
1
+ var x=["sqli","nosqli","cmdi","path","xss","ssrf","redirect","eval","jwt","crypto","proto","secrets","deps","config","other"],m=["sqli","nosqli","cmdi","path","xss","ssrf","redirect","eval","jwt","crypto","proto","secrets","deps","config"],S={"SAST-SQLI-001":"sqli","SAST-NOSQLI-001":"nosqli","SAST-CMDI-001":"cmdi","SAST-PATH-001":"path","SAST-XSS-001":"xss","SAST-SSRF-001":"ssrf","SAST-REDIRECT-001":"redirect","SAST-EVAL-001":"eval","SAST-JWT-001":"jwt","SAST-CRYPTO-001":"crypto","SAST-PROTO-001":"proto"};function p(e){return S[e]?S[e]:e.startsWith("SECRET-")?"secrets":e.startsWith("DEPS-")?"deps":e.startsWith("CONFIG-")?"config":"other"}function f(e){return e.replaceAll("\\","/").replace(/^\.\//,"")}function L(e){return `${e.ruleId}|${f(e.file??"")}|${e.line??0}`}function h(e,r){if(!e.file)return false;let n=f(e.file),i=f(r.file);return n===i||n.endsWith(`/${i}`)||i.endsWith(`/${n}`)}function d(e){return e.line===void 0||e.line===0}function E(e,r){if(p(e.ruleId)!==r.class||!h(e,r))return false;let n=e.line??0;return Math.abs(n-r.line)<=3}function A(e,r){let n=e.filter(t=>p(t.ruleId)===r.class&&h(t,r)),i=new Set(n.map(t=>t.ruleId));for(let t of i){let u=n.filter(c=>c.ruleId===t),o=u.some(c=>!d(c)&&Math.abs((c.line??0)-r.line)<=3),a=u.some(c=>d(c));if(o&&a)return true}return false}function b(e,r){let n=new Set,i=[],t=[],u=r.filter(s=>s.inScope===true),o=r.filter(s=>s.inScope!==true);for(let s of u){if(A(e,s)){t.push(s);continue}let l=e.findIndex((g,y)=>!n.has(y)&&E(g,s));l>=0&&(n.add(l),i.push(s));}let a=new Set([...i,...t]),c=u.filter(s=>!a.has(s)),T=e.filter((s,l)=>!n.has(l));return {truePositives:i,lineAttributionOnly:t,inScopeMisses:c,outOfScope:o,unmatched:T}}function v(e){let r=e.filter(o=>o.verdict==="realIssue").length,n=e.filter(o=>o.verdict==="falsePositive").length,i=e.filter(o=>o.verdict==="unsure").length,t=r+n,u=t===0?"n/a":`${(100*r/t).toFixed(1)}%`;return {realIssue:r,falsePositive:n,unsure:i,precision:u}}
2
+ export{x as BENCH_CLASSES,m as IN_SCOPE_CLASSES,p as classForRule,L as findingKey,d as isFileLevelFinding,A as isLineAttributionOnly,E as isTruePositive,v as precisionFromTriage,b as scoreFindings};