agentlint 0.1.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.
Files changed (136) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +190 -0
  3. package/README.md +246 -0
  4. package/dist/cli/index.d.ts +7 -0
  5. package/dist/cli/index.d.ts.map +1 -0
  6. package/dist/cli/index.js +351 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/diff/index.d.ts +16 -0
  9. package/dist/diff/index.d.ts.map +1 -0
  10. package/dist/diff/index.js +204 -0
  11. package/dist/diff/index.js.map +1 -0
  12. package/dist/index.d.ts +21 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +55 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/ir/index.d.ts +2 -0
  17. package/dist/ir/index.d.ts.map +1 -0
  18. package/dist/ir/index.js +18 -0
  19. package/dist/ir/index.js.map +1 -0
  20. package/dist/ir/types.d.ts +369 -0
  21. package/dist/ir/types.d.ts.map +1 -0
  22. package/dist/ir/types.js +12 -0
  23. package/dist/ir/types.js.map +1 -0
  24. package/dist/parsers/base.d.ts +104 -0
  25. package/dist/parsers/base.d.ts.map +1 -0
  26. package/dist/parsers/base.js +373 -0
  27. package/dist/parsers/base.js.map +1 -0
  28. package/dist/parsers/claude.d.ts +30 -0
  29. package/dist/parsers/claude.d.ts.map +1 -0
  30. package/dist/parsers/claude.js +453 -0
  31. package/dist/parsers/claude.js.map +1 -0
  32. package/dist/parsers/cursor.d.ts +24 -0
  33. package/dist/parsers/cursor.d.ts.map +1 -0
  34. package/dist/parsers/cursor.js +305 -0
  35. package/dist/parsers/cursor.js.map +1 -0
  36. package/dist/parsers/factory.d.ts +30 -0
  37. package/dist/parsers/factory.d.ts.map +1 -0
  38. package/dist/parsers/factory.js +78 -0
  39. package/dist/parsers/factory.js.map +1 -0
  40. package/dist/parsers/index.d.ts +5 -0
  41. package/dist/parsers/index.d.ts.map +1 -0
  42. package/dist/parsers/index.js +21 -0
  43. package/dist/parsers/index.js.map +1 -0
  44. package/dist/policy/index.d.ts +3 -0
  45. package/dist/policy/index.d.ts.map +1 -0
  46. package/dist/policy/index.js +19 -0
  47. package/dist/policy/index.js.map +1 -0
  48. package/dist/policy/loader.d.ts +23 -0
  49. package/dist/policy/loader.d.ts.map +1 -0
  50. package/dist/policy/loader.js +252 -0
  51. package/dist/policy/loader.js.map +1 -0
  52. package/dist/policy/types.d.ts +79 -0
  53. package/dist/policy/types.d.ts.map +1 -0
  54. package/dist/policy/types.js +99 -0
  55. package/dist/policy/types.js.map +1 -0
  56. package/dist/reports/index.d.ts +14 -0
  57. package/dist/reports/index.d.ts.map +1 -0
  58. package/dist/reports/index.js +54 -0
  59. package/dist/reports/index.js.map +1 -0
  60. package/dist/reports/json.d.ts +16 -0
  61. package/dist/reports/json.d.ts.map +1 -0
  62. package/dist/reports/json.js +126 -0
  63. package/dist/reports/json.js.map +1 -0
  64. package/dist/reports/sarif.d.ts +20 -0
  65. package/dist/reports/sarif.d.ts.map +1 -0
  66. package/dist/reports/sarif.js +169 -0
  67. package/dist/reports/sarif.js.map +1 -0
  68. package/dist/reports/text.d.ts +25 -0
  69. package/dist/reports/text.d.ts.map +1 -0
  70. package/dist/reports/text.js +283 -0
  71. package/dist/reports/text.js.map +1 -0
  72. package/dist/reports/types.d.ts +88 -0
  73. package/dist/reports/types.d.ts.map +1 -0
  74. package/dist/reports/types.js +6 -0
  75. package/dist/reports/types.js.map +1 -0
  76. package/dist/rules/base.d.ts +16 -0
  77. package/dist/rules/base.d.ts.map +1 -0
  78. package/dist/rules/base.js +48 -0
  79. package/dist/rules/base.js.map +1 -0
  80. package/dist/rules/engine.d.ts +61 -0
  81. package/dist/rules/engine.d.ts.map +1 -0
  82. package/dist/rules/engine.js +195 -0
  83. package/dist/rules/engine.js.map +1 -0
  84. package/dist/rules/execution.d.ts +33 -0
  85. package/dist/rules/execution.d.ts.map +1 -0
  86. package/dist/rules/execution.js +154 -0
  87. package/dist/rules/execution.js.map +1 -0
  88. package/dist/rules/filesystem.d.ts +36 -0
  89. package/dist/rules/filesystem.d.ts.map +1 -0
  90. package/dist/rules/filesystem.js +227 -0
  91. package/dist/rules/filesystem.js.map +1 -0
  92. package/dist/rules/hook.d.ts +25 -0
  93. package/dist/rules/hook.d.ts.map +1 -0
  94. package/dist/rules/hook.js +112 -0
  95. package/dist/rules/hook.js.map +1 -0
  96. package/dist/rules/index.d.ts +12 -0
  97. package/dist/rules/index.d.ts.map +1 -0
  98. package/dist/rules/index.js +28 -0
  99. package/dist/rules/index.js.map +1 -0
  100. package/dist/rules/instruction.d.ts +25 -0
  101. package/dist/rules/instruction.d.ts.map +1 -0
  102. package/dist/rules/instruction.js +162 -0
  103. package/dist/rules/instruction.js.map +1 -0
  104. package/dist/rules/network.d.ts +33 -0
  105. package/dist/rules/network.d.ts.map +1 -0
  106. package/dist/rules/network.js +145 -0
  107. package/dist/rules/network.js.map +1 -0
  108. package/dist/rules/observability.d.ts +25 -0
  109. package/dist/rules/observability.d.ts.map +1 -0
  110. package/dist/rules/observability.js +105 -0
  111. package/dist/rules/observability.js.map +1 -0
  112. package/dist/rules/scope.d.ts +37 -0
  113. package/dist/rules/scope.d.ts.map +1 -0
  114. package/dist/rules/scope.js +173 -0
  115. package/dist/rules/scope.js.map +1 -0
  116. package/dist/rules/secrets.d.ts +35 -0
  117. package/dist/rules/secrets.d.ts.map +1 -0
  118. package/dist/rules/secrets.js +273 -0
  119. package/dist/rules/secrets.js.map +1 -0
  120. package/dist/rules/types.d.ts +58 -0
  121. package/dist/rules/types.d.ts.map +1 -0
  122. package/dist/rules/types.js +6 -0
  123. package/dist/rules/types.js.map +1 -0
  124. package/dist/scanner.d.ts +61 -0
  125. package/dist/scanner.d.ts.map +1 -0
  126. package/dist/scanner.js +441 -0
  127. package/dist/scanner.js.map +1 -0
  128. package/dist/utils/hash.d.ts +28 -0
  129. package/dist/utils/hash.d.ts.map +1 -0
  130. package/dist/utils/hash.js +94 -0
  131. package/dist/utils/hash.js.map +1 -0
  132. package/dist/utils/index.d.ts +2 -0
  133. package/dist/utils/index.d.ts.map +1 -0
  134. package/dist/utils/index.js +18 -0
  135. package/dist/utils/index.js.map +1 -0
  136. package/package.json +76 -0
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Base rule class with common functionality
3
+ */
4
+ import { Finding, AgentDocument, Evidence, Anchors } from '../ir/types';
5
+ import { Rule, RuleDefinition, RuleContext } from './types';
6
+ export declare abstract class BaseRule implements Rule {
7
+ protected definition: RuleDefinition;
8
+ constructor(definition: RuleDefinition);
9
+ getDefinition(): RuleDefinition;
10
+ abstract evaluate(context: RuleContext): Finding[];
11
+ /**
12
+ * Create a finding with proper fingerprints
13
+ */
14
+ protected createFinding(document: AgentDocument, location: Anchors, message: string, evidence: Evidence[], confidence?: number): Finding;
15
+ }
16
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/rules/base.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,aAAa,EAAY,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAO5D,8BAAsB,QAAS,YAAW,IAAI;IAC5C,SAAS,CAAC,UAAU,EAAE,cAAc,CAAC;gBAEzB,UAAU,EAAE,cAAc;IAItC,aAAa,IAAI,cAAc;IAI/B,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,EAAE;IAElD;;OAEG;IACH,SAAS,CAAC,aAAa,CACrB,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAAE,EACpB,UAAU,GAAE,MAAY,GACvB,OAAO;CA2CX"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * Base rule class with common functionality
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BaseRule = void 0;
7
+ const hash_1 = require("../utils/hash");
8
+ class BaseRule {
9
+ definition;
10
+ constructor(definition) {
11
+ this.definition = definition;
12
+ }
13
+ getDefinition() {
14
+ return this.definition;
15
+ }
16
+ /**
17
+ * Create a finding with proper fingerprints
18
+ */
19
+ createFinding(document, location, message, evidence, confidence = 0.9) {
20
+ const evidenceValue = evidence.length > 0 ? evidence[0].value : '';
21
+ return {
22
+ finding_id: (0, hash_1.generateFindingId)(this.definition.id, document.path, location.start_line, evidenceValue),
23
+ rule_id: this.definition.id,
24
+ group: this.definition.group,
25
+ severity: this.definition.severity,
26
+ title: this.definition.title,
27
+ description: this.definition.description,
28
+ message,
29
+ recommendation: this.definition.recommendation,
30
+ confidence,
31
+ tags: this.definition.tags,
32
+ location: {
33
+ path: document.path,
34
+ start_line: location.start_line,
35
+ end_line: location.end_line,
36
+ },
37
+ evidence,
38
+ related_actions: [],
39
+ fingerprints: {
40
+ stable: (0, hash_1.generateFindingId)(this.definition.id, document.path, location.start_line, evidenceValue),
41
+ location: (0, hash_1.generateLocationFingerprint)(this.definition.id, document.path, location.start_line, location.end_line),
42
+ content: (0, hash_1.generateContentFingerprint)(this.definition.id, evidenceValue),
43
+ },
44
+ };
45
+ }
46
+ }
47
+ exports.BaseRule = BaseRule;
48
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/rules/base.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAIH,wCAIuB;AAEvB,MAAsB,QAAQ;IAClB,UAAU,CAAiB;IAErC,YAAY,UAA0B;QACpC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAID;;OAEG;IACO,aAAa,CACrB,QAAuB,EACvB,QAAiB,EACjB,OAAe,EACf,QAAoB,EACpB,aAAqB,GAAG;QAExB,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAEnE,OAAO;YACL,UAAU,EAAE,IAAA,wBAAiB,EAC3B,IAAI,CAAC,UAAU,CAAC,EAAE,EAClB,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,UAAU,EACnB,aAAa,CACd;YACD,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE;YAC3B,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;YAC5B,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ;YAClC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;YAC5B,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW;YACxC,OAAO;YACP,cAAc,EAAE,IAAI,CAAC,UAAU,CAAC,cAAc;YAC9C,UAAU;YACV,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI;YAC1B,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;aAC5B;YACD,QAAQ;YACR,eAAe,EAAE,EAAE;YACnB,YAAY,EAAE;gBACZ,MAAM,EAAE,IAAA,wBAAiB,EACvB,IAAI,CAAC,UAAU,CAAC,EAAE,EAClB,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,UAAU,EACnB,aAAa,CACd;gBACD,QAAQ,EAAE,IAAA,kCAA2B,EACnC,IAAI,CAAC,UAAU,CAAC,EAAE,EAClB,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,UAAU,EACnB,QAAQ,CAAC,QAAQ,CAClB;gBACD,OAAO,EAAE,IAAA,iCAA0B,EAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,aAAa,CAAC;aACvE;SACF,CAAC;IACJ,CAAC;CACF;AAjED,4BAiEC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Rule Engine
3
+ * Orchestrates rule evaluation and finding generation
4
+ */
5
+ import { AgentDocument, Finding, CapabilitySummary, Severity } from '../ir/types';
6
+ import { Rule, RuleDefinition, RuleEngineOptions, RuleGroup } from './types';
7
+ /**
8
+ * Rule Engine - evaluates all rules against documents
9
+ */
10
+ export declare class RuleEngine {
11
+ private rules;
12
+ private options;
13
+ private ruleMap;
14
+ constructor(options?: Partial<RuleEngineOptions>);
15
+ /**
16
+ * Get all available rules
17
+ */
18
+ getAllRules(): RuleDefinition[];
19
+ /**
20
+ * Get enabled rules (after applying disabled list)
21
+ */
22
+ getEnabledRules(): RuleDefinition[];
23
+ /**
24
+ * Get a rule by ID
25
+ */
26
+ getRule(ruleId: string): Rule | undefined;
27
+ /**
28
+ * Get rule definition by ID
29
+ */
30
+ getRuleDefinition(ruleId: string): RuleDefinition | undefined;
31
+ /**
32
+ * Get rules by group
33
+ */
34
+ getRulesByGroup(group: RuleGroup): RuleDefinition[];
35
+ /**
36
+ * Evaluate all rules against a single document
37
+ */
38
+ evaluateDocument(document: AgentDocument, allDocuments: AgentDocument[], capabilitySummary: CapabilitySummary): Finding[];
39
+ /**
40
+ * Evaluate all rules against multiple documents
41
+ */
42
+ evaluateAll(documents: AgentDocument[], capabilitySummary: CapabilitySummary): Finding[];
43
+ /**
44
+ * Sort findings by severity, path, and line number
45
+ */
46
+ private sortFindings;
47
+ /**
48
+ * Count findings by severity
49
+ */
50
+ countBySeverity(findings: Finding[]): Record<Severity, number>;
51
+ /**
52
+ * Filter findings by minimum severity
53
+ */
54
+ filterBySeverity(findings: Finding[], minSeverity: Severity): Finding[];
55
+ /**
56
+ * Check if any finding meets or exceeds the threshold
57
+ */
58
+ hasFindings(findings: Finding[], threshold: Severity | 'none'): boolean;
59
+ }
60
+ export declare const defaultRuleEngine: RuleEngine;
61
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/rules/engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,aAAa,EACb,OAAO,EACP,iBAAiB,EACjB,QAAQ,EACT,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,IAAI,EAAe,cAAc,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAU1F;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,OAAO,CAAoB;gBAEvB,OAAO,GAAE,OAAO,CAAC,iBAAiB,CAAM;IA0BpD;;OAEG;IACH,WAAW,IAAI,cAAc,EAAE;IAI/B;;OAEG;IACH,eAAe,IAAI,cAAc,EAAE;IAMnC;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIzC;;OAEG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAK7D;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc,EAAE;IAMnD;;OAEG;IACH,gBAAgB,CACd,QAAQ,EAAE,aAAa,EACvB,YAAY,EAAE,aAAa,EAAE,EAC7B,iBAAiB,EAAE,iBAAiB,GACnC,OAAO,EAAE;IA0CZ;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,aAAa,EAAE,EAC1B,iBAAiB,EAAE,iBAAiB,GACnC,OAAO,EAAE;IAgBZ;;OAEG;IACH,OAAO,CAAC,YAAY;IAyBpB;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC;IAc9D;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,EAAE;IAWvE;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO;CAIxE;AAGD,eAAO,MAAM,iBAAiB,YAAmB,CAAC"}
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ /**
3
+ * Rule Engine
4
+ * Orchestrates rule evaluation and finding generation
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.defaultRuleEngine = exports.RuleEngine = void 0;
8
+ const execution_1 = require("./execution");
9
+ const filesystem_1 = require("./filesystem");
10
+ const network_1 = require("./network");
11
+ const secrets_1 = require("./secrets");
12
+ const hook_1 = require("./hook");
13
+ const instruction_1 = require("./instruction");
14
+ const scope_1 = require("./scope");
15
+ const observability_1 = require("./observability");
16
+ /**
17
+ * Rule Engine - evaluates all rules against documents
18
+ */
19
+ class RuleEngine {
20
+ rules;
21
+ options;
22
+ ruleMap;
23
+ constructor(options = {}) {
24
+ this.options = {
25
+ minConfidence: options.minConfidence ?? 0.6,
26
+ disabledRules: options.disabledRules ?? [],
27
+ severityOverrides: options.severityOverrides ?? {},
28
+ };
29
+ // Collect all rules
30
+ this.rules = [
31
+ ...execution_1.executionRules,
32
+ ...filesystem_1.filesystemRules,
33
+ ...network_1.networkRules,
34
+ ...secrets_1.secretRules,
35
+ ...hook_1.hookRules,
36
+ ...instruction_1.instructionRules,
37
+ ...scope_1.scopeRules,
38
+ ...observability_1.observabilityRules,
39
+ ];
40
+ // Build rule map for quick lookup
41
+ this.ruleMap = new Map();
42
+ for (const rule of this.rules) {
43
+ this.ruleMap.set(rule.getDefinition().id, rule);
44
+ }
45
+ }
46
+ /**
47
+ * Get all available rules
48
+ */
49
+ getAllRules() {
50
+ return this.rules.map(r => r.getDefinition());
51
+ }
52
+ /**
53
+ * Get enabled rules (after applying disabled list)
54
+ */
55
+ getEnabledRules() {
56
+ return this.rules
57
+ .filter(r => !this.options.disabledRules.includes(r.getDefinition().id))
58
+ .map(r => r.getDefinition());
59
+ }
60
+ /**
61
+ * Get a rule by ID
62
+ */
63
+ getRule(ruleId) {
64
+ return this.ruleMap.get(ruleId);
65
+ }
66
+ /**
67
+ * Get rule definition by ID
68
+ */
69
+ getRuleDefinition(ruleId) {
70
+ const rule = this.ruleMap.get(ruleId);
71
+ return rule?.getDefinition();
72
+ }
73
+ /**
74
+ * Get rules by group
75
+ */
76
+ getRulesByGroup(group) {
77
+ return this.rules
78
+ .filter(r => r.getDefinition().group === group)
79
+ .map(r => r.getDefinition());
80
+ }
81
+ /**
82
+ * Evaluate all rules against a single document
83
+ */
84
+ evaluateDocument(document, allDocuments, capabilitySummary) {
85
+ const findings = [];
86
+ const context = {
87
+ document,
88
+ allDocuments,
89
+ capabilitySummary,
90
+ minConfidence: this.options.minConfidence,
91
+ };
92
+ for (const rule of this.rules) {
93
+ const definition = rule.getDefinition();
94
+ // Skip disabled rules
95
+ if (this.options.disabledRules.includes(definition.id)) {
96
+ continue;
97
+ }
98
+ try {
99
+ const ruleFindings = rule.evaluate(context);
100
+ // Apply severity overrides and filter by confidence
101
+ for (const finding of ruleFindings) {
102
+ // Apply severity override if configured
103
+ if (this.options.severityOverrides[definition.id]) {
104
+ finding.severity = this.options.severityOverrides[definition.id];
105
+ }
106
+ // Filter by confidence threshold
107
+ if (finding.confidence >= this.options.minConfidence) {
108
+ findings.push(finding);
109
+ }
110
+ }
111
+ }
112
+ catch (error) {
113
+ // Log but don't fail on individual rule errors
114
+ console.error(`Error evaluating rule ${definition.id}:`, error);
115
+ }
116
+ }
117
+ return findings;
118
+ }
119
+ /**
120
+ * Evaluate all rules against multiple documents
121
+ */
122
+ evaluateAll(documents, capabilitySummary) {
123
+ const findings = [];
124
+ for (const document of documents) {
125
+ const docFindings = this.evaluateDocument(document, documents, capabilitySummary);
126
+ findings.push(...docFindings);
127
+ }
128
+ // Sort findings: severity (high first), then path, then line
129
+ return this.sortFindings(findings);
130
+ }
131
+ /**
132
+ * Sort findings by severity, path, and line number
133
+ */
134
+ sortFindings(findings) {
135
+ const severityOrder = {
136
+ high: 0,
137
+ medium: 1,
138
+ low: 2,
139
+ };
140
+ return findings.sort((a, b) => {
141
+ // Sort by severity first
142
+ const severityDiff = severityOrder[a.severity] - severityOrder[b.severity];
143
+ if (severityDiff !== 0)
144
+ return severityDiff;
145
+ // Then by path
146
+ const pathDiff = a.location.path.localeCompare(b.location.path);
147
+ if (pathDiff !== 0)
148
+ return pathDiff;
149
+ // Then by line number
150
+ const lineDiff = a.location.start_line - b.location.start_line;
151
+ if (lineDiff !== 0)
152
+ return lineDiff;
153
+ // Finally by rule ID for stability
154
+ return a.rule_id.localeCompare(b.rule_id);
155
+ });
156
+ }
157
+ /**
158
+ * Count findings by severity
159
+ */
160
+ countBySeverity(findings) {
161
+ const counts = {
162
+ high: 0,
163
+ medium: 0,
164
+ low: 0,
165
+ };
166
+ for (const finding of findings) {
167
+ counts[finding.severity]++;
168
+ }
169
+ return counts;
170
+ }
171
+ /**
172
+ * Filter findings by minimum severity
173
+ */
174
+ filterBySeverity(findings, minSeverity) {
175
+ const severityLevel = {
176
+ high: 3,
177
+ medium: 2,
178
+ low: 1,
179
+ };
180
+ const minLevel = severityLevel[minSeverity];
181
+ return findings.filter(f => severityLevel[f.severity] >= minLevel);
182
+ }
183
+ /**
184
+ * Check if any finding meets or exceeds the threshold
185
+ */
186
+ hasFindings(findings, threshold) {
187
+ if (threshold === 'none')
188
+ return false;
189
+ return this.filterBySeverity(findings, threshold).length > 0;
190
+ }
191
+ }
192
+ exports.RuleEngine = RuleEngine;
193
+ // Export a default instance
194
+ exports.defaultRuleEngine = new RuleEngine();
195
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/rules/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Execution Rules (EXEC)
3
+ * Rules for detecting shell execution risks
4
+ */
5
+ import { Finding } from '../ir/types';
6
+ import { BaseRule } from './base';
7
+ import { RuleContext } from './types';
8
+ /**
9
+ * EXEC-001: Dynamic Shell Execution
10
+ * Detects shell execution where the command is dynamically constructed or fetched
11
+ */
12
+ export declare class DynamicShellExecutionRule extends BaseRule {
13
+ constructor();
14
+ evaluate(context: RuleContext): Finding[];
15
+ }
16
+ /**
17
+ * EXEC-002: Shell Execution in Non-Interactive Context
18
+ * Shell commands executed inside hooks or auto-triggered contexts
19
+ */
20
+ export declare class ShellInNonInteractiveRule extends BaseRule {
21
+ constructor();
22
+ evaluate(context: RuleContext): Finding[];
23
+ }
24
+ /**
25
+ * EXEC-003: Broad Shell Capability Declaration
26
+ * Shell execution allowed without scope restriction
27
+ */
28
+ export declare class BroadShellCapabilityRule extends BaseRule {
29
+ constructor();
30
+ evaluate(context: RuleContext): Finding[];
31
+ }
32
+ export declare const executionRules: (DynamicShellExecutionRule | ShellInNonInteractiveRule | BroadShellCapabilityRule)[];
33
+ //# sourceMappingURL=execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../src/rules/execution.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,WAAW,EAAkB,MAAM,SAAS,CAAC;AAEtD;;;GAGG;AACH,qBAAa,yBAA0B,SAAQ,QAAQ;;IAerD,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,EAAE;CA2C1C;AAED;;;GAGG;AACH,qBAAa,yBAA0B,SAAQ,QAAQ;;IAerD,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,EAAE;CAmC1C;AAED;;;GAGG;AACH,qBAAa,wBAAyB,SAAQ,QAAQ;;IAepD,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,EAAE;CAuC1C;AAGD,eAAO,MAAM,cAAc,sFAI1B,CAAC"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ /**
3
+ * Execution Rules (EXEC)
4
+ * Rules for detecting shell execution risks
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.executionRules = exports.BroadShellCapabilityRule = exports.ShellInNonInteractiveRule = exports.DynamicShellExecutionRule = void 0;
8
+ const base_1 = require("./base");
9
+ /**
10
+ * EXEC-001: Dynamic Shell Execution
11
+ * Detects shell execution where the command is dynamically constructed or fetched
12
+ */
13
+ class DynamicShellExecutionRule extends base_1.BaseRule {
14
+ constructor() {
15
+ super({
16
+ id: 'EXEC-001',
17
+ group: 'execution',
18
+ severity: 'high',
19
+ title: 'Dynamic Shell Execution',
20
+ description: 'Detects shell execution where the command is dynamically constructed or fetched. This includes patterns like curl|bash, wget|sh, and eval with variables.',
21
+ recommendation: 'Replace with fixed commands or disable shell access. Use pinned, verified installers instead of fetching scripts from the network.',
22
+ tags: ['rce', 'supply-chain', 'dynamic-execution'],
23
+ });
24
+ }
25
+ evaluate(context) {
26
+ const findings = [];
27
+ const { document, minConfidence } = context;
28
+ for (const action of document.actions) {
29
+ if (action.type !== 'shell_exec')
30
+ continue;
31
+ if (!action.shell?.dynamic)
32
+ continue;
33
+ const confidence = action.evidence[0]?.confidence || 0.9;
34
+ if (confidence < minConfidence)
35
+ continue;
36
+ const patterns = action.shell.patterns || [];
37
+ let message = 'Dynamic shell execution detected.';
38
+ if (patterns.includes('curl|bash') || patterns.includes('wget|bash')) {
39
+ message = 'Remote code execution risk: curl|bash or wget|bash pattern detected.';
40
+ }
41
+ else if (patterns.includes('eval')) {
42
+ message = 'Dynamic shell execution via eval detected.';
43
+ }
44
+ else if (patterns.includes('variable_interpolation')) {
45
+ message = 'Shell command with variable interpolation detected.';
46
+ }
47
+ const finding = this.createFinding(document, action.anchors, message, action.evidence, confidence);
48
+ // Add related action info
49
+ finding.related_actions.push({
50
+ action_type: action.type,
51
+ context: action.context,
52
+ summary: action.summary,
53
+ anchors: action.anchors,
54
+ });
55
+ findings.push(finding);
56
+ }
57
+ return findings;
58
+ }
59
+ }
60
+ exports.DynamicShellExecutionRule = DynamicShellExecutionRule;
61
+ /**
62
+ * EXEC-002: Shell Execution in Non-Interactive Context
63
+ * Shell commands executed inside hooks or auto-triggered contexts
64
+ */
65
+ class ShellInNonInteractiveRule extends base_1.BaseRule {
66
+ constructor() {
67
+ super({
68
+ id: 'EXEC-002',
69
+ group: 'execution',
70
+ severity: 'high',
71
+ title: 'Shell Execution in Non-Interactive Context',
72
+ description: 'Shell commands executed inside hooks or auto-triggered contexts. Users do not explicitly approve these actions at runtime.',
73
+ recommendation: 'Move shell execution to interactive contexts where user approval is required, or remove automatic hook execution.',
74
+ tags: ['rce', 'hook', 'automation'],
75
+ });
76
+ }
77
+ evaluate(context) {
78
+ const findings = [];
79
+ const { document, minConfidence } = context;
80
+ // Only applies to hook context
81
+ if (document.context_profile.primary !== 'hook') {
82
+ return findings;
83
+ }
84
+ for (const action of document.actions) {
85
+ if (action.type !== 'shell_exec')
86
+ continue;
87
+ const confidence = action.evidence[0]?.confidence || 0.9;
88
+ if (confidence < minConfidence)
89
+ continue;
90
+ const finding = this.createFinding(document, action.anchors, `Shell execution in hook context: ${action.summary}. Users do not explicitly approve hook actions.`, action.evidence, confidence);
91
+ finding.related_actions.push({
92
+ action_type: action.type,
93
+ context: action.context,
94
+ summary: action.summary,
95
+ anchors: action.anchors,
96
+ });
97
+ findings.push(finding);
98
+ }
99
+ return findings;
100
+ }
101
+ }
102
+ exports.ShellInNonInteractiveRule = ShellInNonInteractiveRule;
103
+ /**
104
+ * EXEC-003: Broad Shell Capability Declaration
105
+ * Shell execution allowed without scope restriction
106
+ */
107
+ class BroadShellCapabilityRule extends base_1.BaseRule {
108
+ constructor() {
109
+ super({
110
+ id: 'EXEC-003',
111
+ group: 'execution',
112
+ severity: 'medium',
113
+ title: 'Broad Shell Capability Declaration',
114
+ description: 'Shell execution is allowed without command scope restriction. This enables arbitrary command execution.',
115
+ recommendation: 'Define an explicit command allowlist in the permission manifest, or disable shell execution.',
116
+ tags: ['shell', 'permissions', 'least-privilege'],
117
+ });
118
+ }
119
+ evaluate(context) {
120
+ const findings = [];
121
+ const { document, capabilitySummary } = context;
122
+ // Check if shell execution is enabled without restrictions
123
+ if (!capabilitySummary.shell_exec.enabled) {
124
+ return findings;
125
+ }
126
+ // Check each capability for unrestricted shell access
127
+ for (const cap of document.capabilities) {
128
+ if (cap.type !== 'shell_exec')
129
+ continue;
130
+ const hasAllowlist = cap.scope.shell_exec?.allowed_commands &&
131
+ cap.scope.shell_exec.allowed_commands.length > 0;
132
+ if (!hasAllowlist) {
133
+ const finding = this.createFinding(document, { start_line: 1, end_line: 1 }, 'Shell execution capability declared without command restrictions.', [
134
+ {
135
+ kind: 'heuristic',
136
+ value: 'shell_exec: enabled without allowlist',
137
+ confidence: 0.8,
138
+ },
139
+ ], 0.8);
140
+ findings.push(finding);
141
+ break; // Only report once per document
142
+ }
143
+ }
144
+ return findings;
145
+ }
146
+ }
147
+ exports.BroadShellCapabilityRule = BroadShellCapabilityRule;
148
+ // Export all execution rules
149
+ exports.executionRules = [
150
+ new DynamicShellExecutionRule(),
151
+ new ShellInNonInteractiveRule(),
152
+ new BroadShellCapabilityRule(),
153
+ ];
154
+ //# sourceMappingURL=execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/rules/execution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Filesystem Rules (FS)
3
+ * Rules for detecting filesystem access risks
4
+ */
5
+ import { Finding } from '../ir/types';
6
+ import { BaseRule } from './base';
7
+ import { RuleContext } from './types';
8
+ /**
9
+ * FS-001: Unscoped Write Access
10
+ * Agent writes to filesystem without a restricted path scope
11
+ */
12
+ export declare class UnscopedWriteAccessRule extends BaseRule {
13
+ constructor();
14
+ evaluate(context: RuleContext): Finding[];
15
+ private isUnscopedPath;
16
+ }
17
+ /**
18
+ * FS-002: Sensitive Path Write
19
+ * Writes to known sensitive locations
20
+ */
21
+ export declare class SensitivePathWriteRule extends BaseRule {
22
+ constructor();
23
+ evaluate(context: RuleContext): Finding[];
24
+ private isSensitivePath;
25
+ }
26
+ /**
27
+ * FS-003: Cross-Boundary Write
28
+ * Agent writes outside declared project scope
29
+ */
30
+ export declare class CrossBoundaryWriteRule extends BaseRule {
31
+ constructor();
32
+ evaluate(context: RuleContext): Finding[];
33
+ private isCrossBoundaryPath;
34
+ }
35
+ export declare const filesystemRules: (UnscopedWriteAccessRule | SensitivePathWriteRule | CrossBoundaryWriteRule)[];
36
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/rules/filesystem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,WAAW,EAAkB,MAAM,SAAS,CAAC;AAuBtD;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;;IAenD,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,EAAE;IA0DzC,OAAO,CAAC,cAAc;CAiBvB;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,QAAQ;;IAelD,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,EAAE;IAoEzC,OAAO,CAAC,eAAe;CAMxB;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,QAAQ;;IAelD,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,EAAE;IAoCzC,OAAO,CAAC,mBAAmB;CAU5B;AAGD,eAAO,MAAM,eAAe,+EAI3B,CAAC"}