asterscanner 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.
@@ -0,0 +1,160 @@
1
+ import { SECURITY_PATTERNS } from "./patterns.js";
2
+ import { calculateScore, scorePassesThreshold } from "./scoring.js";
3
+ /**
4
+ * Default scan options
5
+ */
6
+ const DEFAULT_OPTIONS = {
7
+ minScore: 50,
8
+ categories: ["secrets", "code_execution", "file_system", "network", "credentials", "system"],
9
+ severities: ["critical", "high", "medium", "low", "info"],
10
+ customPatterns: [],
11
+ includeInfoInScore: false,
12
+ };
13
+ /**
14
+ * Security scanner for skill content
15
+ */
16
+ export class Scanner {
17
+ options;
18
+ patterns;
19
+ constructor(options = {}) {
20
+ this.options = { ...DEFAULT_OPTIONS, ...options };
21
+ this.patterns = this.buildPatternList();
22
+ }
23
+ /**
24
+ * Build the list of patterns to use based on options
25
+ */
26
+ buildPatternList() {
27
+ const patterns = [
28
+ ...SECURITY_PATTERNS.filter((p) => this.options.categories.includes(p.category) &&
29
+ this.options.severities.includes(p.severity)),
30
+ ...this.options.customPatterns,
31
+ ];
32
+ return patterns;
33
+ }
34
+ /**
35
+ * Sanitize matched content for display (truncate and mask sensitive parts)
36
+ */
37
+ sanitizeMatch(match) {
38
+ if (match.length > 50) {
39
+ return match.substring(0, 47) + "...";
40
+ }
41
+ // Mask potential secrets
42
+ if (match.includes("=") || match.includes(":")) {
43
+ const parts = match.split(/[:=]/);
44
+ if (parts.length === 2 && parts[1].length > 4) {
45
+ const visible = parts[1].substring(0, 4);
46
+ return `${parts[0]}=${visible}${"*".repeat(Math.min(parts[1].length - 4, 10))}`;
47
+ }
48
+ }
49
+ return match;
50
+ }
51
+ /**
52
+ * Scan a single line for security issues
53
+ */
54
+ scanLine(line, lineNumber) {
55
+ const issues = [];
56
+ for (const patternDef of this.patterns) {
57
+ // Reset lastIndex for global patterns
58
+ patternDef.pattern.lastIndex = 0;
59
+ let match;
60
+ while ((match = patternDef.pattern.exec(line)) !== null) {
61
+ issues.push({
62
+ patternId: patternDef.id,
63
+ type: patternDef.type,
64
+ category: patternDef.category,
65
+ severity: patternDef.severity,
66
+ message: patternDef.message,
67
+ line: lineNumber,
68
+ column: match.index + 1,
69
+ match: this.sanitizeMatch(match[0]),
70
+ recommendation: patternDef.recommendation,
71
+ });
72
+ // Prevent infinite loops for patterns that match empty strings
73
+ if (match[0].length === 0) {
74
+ patternDef.pattern.lastIndex++;
75
+ }
76
+ }
77
+ }
78
+ return issues;
79
+ }
80
+ /**
81
+ * Scan content for security issues
82
+ */
83
+ scan(content) {
84
+ const startTime = Date.now();
85
+ const lines = content.split("\n");
86
+ const issues = [];
87
+ for (let i = 0; i < lines.length; i++) {
88
+ const lineIssues = this.scanLine(lines[i], i + 1);
89
+ issues.push(...lineIssues);
90
+ }
91
+ // Sort issues by severity, then by line number
92
+ const severityOrder = {
93
+ critical: 0,
94
+ high: 1,
95
+ medium: 2,
96
+ low: 3,
97
+ info: 4,
98
+ };
99
+ issues.sort((a, b) => {
100
+ const severityDiff = severityOrder[a.severity] - severityOrder[b.severity];
101
+ if (severityDiff !== 0)
102
+ return severityDiff;
103
+ return a.line - b.line;
104
+ });
105
+ const score = calculateScore(issues, this.options.includeInfoInScore);
106
+ const passed = scorePassesThreshold(score, this.options.minScore);
107
+ // Build summary
108
+ const summary = {
109
+ critical: issues.filter((i) => i.severity === "critical").length,
110
+ high: issues.filter((i) => i.severity === "high").length,
111
+ medium: issues.filter((i) => i.severity === "medium").length,
112
+ low: issues.filter((i) => i.severity === "low").length,
113
+ info: issues.filter((i) => i.severity === "info").length,
114
+ total: issues.length,
115
+ };
116
+ return {
117
+ score,
118
+ passed,
119
+ issues,
120
+ summary,
121
+ metadata: {
122
+ scannedAt: new Date().toISOString(),
123
+ contentLength: content.length,
124
+ lineCount: lines.length,
125
+ scanDurationMs: Date.now() - startTime,
126
+ },
127
+ };
128
+ }
129
+ /**
130
+ * Quick check if content passes security requirements
131
+ */
132
+ passes(content) {
133
+ return this.scan(content).passed;
134
+ }
135
+ /**
136
+ * Get the current options
137
+ */
138
+ getOptions() {
139
+ return { ...this.options };
140
+ }
141
+ /**
142
+ * Get the active patterns
143
+ */
144
+ getPatterns() {
145
+ return [...this.patterns];
146
+ }
147
+ }
148
+ /**
149
+ * Create a new scanner instance
150
+ */
151
+ export function createScanner(options) {
152
+ return new Scanner(options);
153
+ }
154
+ /**
155
+ * Quick scan function for simple use cases
156
+ */
157
+ export function scan(content, options) {
158
+ return new Scanner(options).scan(content);
159
+ }
160
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { SecurityIssue, Severity } from "./types.js";
2
+ /**
3
+ * Weight deductions for each severity level
4
+ */
5
+ export declare const SEVERITY_WEIGHTS: Record<Severity, number>;
6
+ /**
7
+ * Calculate security score based on issues found
8
+ *
9
+ * @param issues - List of security issues
10
+ * @param includeInfo - Whether to include info-level issues (default: false)
11
+ * @returns Score from 0-100
12
+ */
13
+ export declare function calculateScore(issues: SecurityIssue[], includeInfo?: boolean): number;
14
+ /**
15
+ * Determine if a score passes the minimum threshold
16
+ *
17
+ * @param score - The security score
18
+ * @param minScore - Minimum passing score (default: 50)
19
+ * @returns Whether the score passes
20
+ */
21
+ export declare function scorePassesThreshold(score: number, minScore?: number): boolean;
22
+ /**
23
+ * Get a human-readable rating based on score
24
+ */
25
+ export declare function getScoreRating(score: number): "excellent" | "good" | "fair" | "poor" | "critical";
26
+ /**
27
+ * Get a color code for the score (for terminal output)
28
+ */
29
+ export declare function getScoreColor(score: number): "green" | "yellow" | "red";
30
+ //# sourceMappingURL=scoring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoring.d.ts","sourceRoot":"","sources":["../src/scoring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAMrD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EAAE,EACvB,WAAW,GAAE,OAAe,GAC3B,MAAM,CAWR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,MAAW,GACpB,OAAO,CAET;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,GACZ,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAMrD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAIvE"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Weight deductions for each severity level
3
+ */
4
+ export const SEVERITY_WEIGHTS = {
5
+ critical: 25,
6
+ high: 15,
7
+ medium: 10,
8
+ low: 5,
9
+ info: 0,
10
+ };
11
+ /**
12
+ * Calculate security score based on issues found
13
+ *
14
+ * @param issues - List of security issues
15
+ * @param includeInfo - Whether to include info-level issues (default: false)
16
+ * @returns Score from 0-100
17
+ */
18
+ export function calculateScore(issues, includeInfo = false) {
19
+ let score = 100;
20
+ for (const issue of issues) {
21
+ if (!includeInfo && issue.severity === "info") {
22
+ continue;
23
+ }
24
+ score -= SEVERITY_WEIGHTS[issue.severity];
25
+ }
26
+ return Math.max(0, score);
27
+ }
28
+ /**
29
+ * Determine if a score passes the minimum threshold
30
+ *
31
+ * @param score - The security score
32
+ * @param minScore - Minimum passing score (default: 50)
33
+ * @returns Whether the score passes
34
+ */
35
+ export function scorePassesThreshold(score, minScore = 50) {
36
+ return score >= minScore;
37
+ }
38
+ /**
39
+ * Get a human-readable rating based on score
40
+ */
41
+ export function getScoreRating(score) {
42
+ if (score >= 90)
43
+ return "excellent";
44
+ if (score >= 70)
45
+ return "good";
46
+ if (score >= 50)
47
+ return "fair";
48
+ if (score >= 25)
49
+ return "poor";
50
+ return "critical";
51
+ }
52
+ /**
53
+ * Get a color code for the score (for terminal output)
54
+ */
55
+ export function getScoreColor(score) {
56
+ if (score >= 70)
57
+ return "green";
58
+ if (score >= 50)
59
+ return "yellow";
60
+ return "red";
61
+ }
62
+ //# sourceMappingURL=scoring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoring.js","sourceRoot":"","sources":["../src/scoring.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA6B;IACxD,QAAQ,EAAE,EAAE;IACZ,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,EAAE;IACV,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACR,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAuB,EACvB,cAAuB,KAAK;IAE5B,IAAI,KAAK,GAAG,GAAG,CAAC;IAEhB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC9C,SAAS;QACX,CAAC;QACD,KAAK,IAAI,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAa,EACb,WAAmB,EAAE;IAErB,OAAO,KAAK,IAAI,QAAQ,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa;IAEb,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,WAAW,CAAC;IACpC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IAC/B,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IAC/B,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IAC/B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,OAAO,CAAC;IAChC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAC;IACjC,OAAO,KAAK,CAAC;AACf,CAAC"}