@contrast/common 1.0.3 → 1.1.1

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,6 +1,13 @@
1
1
  export declare enum Event {
2
2
  ASSESS = "assess",
3
- PROTECT = "protect"
3
+ PROTECT = "protect",
4
+ SERVER_SETTINGS_UPDATE = "server-settings-update"
5
+ }
6
+ export declare enum ProtectRuleMode {
7
+ OFF = "off",
8
+ MONITOR = "monitor",
9
+ BLOCK = "block",
10
+ BLOCK_AT_PERIMETER = "block_at_perimeter"
4
11
  }
5
12
  export declare enum Rule {
6
13
  BOT_BLOCKER = "bot-blocker",
@@ -21,3 +28,28 @@ export declare enum Rule {
21
28
  UNSAFE_FILE_UPLOAD = "unsafe-file-upload",
22
29
  XXE = "xxe"
23
30
  }
31
+ export declare enum InputType {
32
+ UNDEFINED_TYPE = "UNDEFINED_TYPE",
33
+ BODY = "BODY",
34
+ COOKIE_NAME = "COOKIE_NAME",
35
+ COOKIE_VALUE = "COOKIE_VALUE",
36
+ HEADER = "HEADER",
37
+ PARAMETER_NAME = "PARAMETER_NAME",
38
+ PARAMETER_VALUE = "PARAMETER_VALUE",
39
+ QUERYSTRING = "QUERYSTRING",
40
+ URI = "URI",
41
+ SOCKET = "SOCKET",
42
+ JSON_VALUE = "JSON_VALUE",
43
+ JSON_ARRAYED_VALUE = "JSON_ARRAYED_VALUE",
44
+ MULTIPART_CONTENT_TYPE = "MULTIPART_CONTENT_TYPE",
45
+ MULTIPART_VALUE = "MULTIPART_VALUE",
46
+ MULTIPART_FIELD_NAME = "MULTIPART_FIELD_NAME",
47
+ MULTIPART_NAME = "MULTIPART_NAME",
48
+ XML_VALUE = "XML_VALUE",
49
+ DWR_VALUE = "DWR_VALUE",
50
+ METHOD = "METHOD",
51
+ REQUEST = "REQUEST",
52
+ URL_PARAMETER = "URL_PARAMETER",
53
+ UNKNOWN = "UNKNOWN"
54
+ }
55
+ export declare const BLOCKING_MODES: string[];
package/lib/constants.js CHANGED
@@ -14,12 +14,20 @@
14
14
  * way not consistent with the End User License Agreement.
15
15
  */
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.Rule = exports.Event = void 0;
17
+ exports.BLOCKING_MODES = exports.InputType = exports.Rule = exports.ProtectRuleMode = exports.Event = void 0;
18
18
  var Event;
19
19
  (function (Event) {
20
20
  Event["ASSESS"] = "assess";
21
21
  Event["PROTECT"] = "protect";
22
+ Event["SERVER_SETTINGS_UPDATE"] = "server-settings-update";
22
23
  })(Event = exports.Event || (exports.Event = {}));
24
+ var ProtectRuleMode;
25
+ (function (ProtectRuleMode) {
26
+ ProtectRuleMode["OFF"] = "off";
27
+ ProtectRuleMode["MONITOR"] = "monitor";
28
+ ProtectRuleMode["BLOCK"] = "block";
29
+ ProtectRuleMode["BLOCK_AT_PERIMETER"] = "block_at_perimeter";
30
+ })(ProtectRuleMode = exports.ProtectRuleMode || (exports.ProtectRuleMode = {}));
23
31
  var Rule;
24
32
  (function (Rule) {
25
33
  Rule["BOT_BLOCKER"] = "bot-blocker";
@@ -40,4 +48,30 @@ var Rule;
40
48
  Rule["UNSAFE_FILE_UPLOAD"] = "unsafe-file-upload";
41
49
  Rule["XXE"] = "xxe";
42
50
  })(Rule = exports.Rule || (exports.Rule = {}));
51
+ var InputType;
52
+ (function (InputType) {
53
+ InputType["UNDEFINED_TYPE"] = "UNDEFINED_TYPE";
54
+ InputType["BODY"] = "BODY";
55
+ InputType["COOKIE_NAME"] = "COOKIE_NAME";
56
+ InputType["COOKIE_VALUE"] = "COOKIE_VALUE";
57
+ InputType["HEADER"] = "HEADER";
58
+ InputType["PARAMETER_NAME"] = "PARAMETER_NAME";
59
+ InputType["PARAMETER_VALUE"] = "PARAMETER_VALUE";
60
+ InputType["QUERYSTRING"] = "QUERYSTRING";
61
+ InputType["URI"] = "URI";
62
+ InputType["SOCKET"] = "SOCKET";
63
+ InputType["JSON_VALUE"] = "JSON_VALUE";
64
+ InputType["JSON_ARRAYED_VALUE"] = "JSON_ARRAYED_VALUE";
65
+ InputType["MULTIPART_CONTENT_TYPE"] = "MULTIPART_CONTENT_TYPE";
66
+ InputType["MULTIPART_VALUE"] = "MULTIPART_VALUE";
67
+ InputType["MULTIPART_FIELD_NAME"] = "MULTIPART_FIELD_NAME";
68
+ InputType["MULTIPART_NAME"] = "MULTIPART_NAME";
69
+ InputType["XML_VALUE"] = "XML_VALUE";
70
+ InputType["DWR_VALUE"] = "DWR_VALUE";
71
+ InputType["METHOD"] = "METHOD";
72
+ InputType["REQUEST"] = "REQUEST";
73
+ InputType["URL_PARAMETER"] = "URL_PARAMETER";
74
+ InputType["UNKNOWN"] = "UNKNOWN";
75
+ })(InputType = exports.InputType || (exports.InputType = {}));
76
+ exports.BLOCKING_MODES = ['block', 'block_at_perimeter'];
43
77
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;AAEH,IAAY,KAGX;AAHD,WAAY,KAAK;IACf,0BAAiB,CAAA;IACjB,4BAAmB,CAAA;AACrB,CAAC,EAHW,KAAK,GAAL,aAAK,KAAL,aAAK,QAGhB;AAED,IAAY,IAkBX;AAlBD,WAAY,IAAI;IACd,mCAA2B,CAAA;IAC3B,uCAA+B,CAAA;IAC/B,2EAAmE,CAAA;IACnE,2FAAmF,CAAA;IACnF,yFAAiF,CAAA;IACjF,mCAA2B,CAAA;IAC3B,6CAAqC,CAAA;IACrC,2CAAmC,CAAA;IACnC,uDAA+C,CAAA;IAC/C,yCAAiC,CAAA;IACjC,uCAA+B,CAAA;IAC/B,uCAA+B,CAAA;IAC/B,yCAAiC,CAAA;IACjC,uCAA+B,CAAA;IAC/B,+DAAuD,CAAA;IACvD,iDAAyC,CAAA;IACzC,mBAAW,CAAA;AACb,CAAC,EAlBW,IAAI,GAAJ,YAAI,KAAJ,YAAI,QAkBf"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;AAEH,IAAY,KAIX;AAJD,WAAY,KAAK;IACf,0BAAiB,CAAA;IACjB,4BAAmB,CAAA;IACnB,0DAAiD,CAAA;AACnD,CAAC,EAJW,KAAK,GAAL,aAAK,KAAL,aAAK,QAIhB;AACD,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,8BAAW,CAAA;IACX,sCAAmB,CAAA;IACnB,kCAAe,CAAA;IACf,4DAAyC,CAAA;AAC3C,CAAC,EALW,eAAe,GAAf,uBAAe,KAAf,uBAAe,QAK1B;AAED,IAAY,IAkBX;AAlBD,WAAY,IAAI;IACd,mCAA2B,CAAA;IAC3B,uCAA+B,CAAA;IAC/B,2EAAmE,CAAA;IACnE,2FAAmF,CAAA;IACnF,yFAAiF,CAAA;IACjF,mCAA2B,CAAA;IAC3B,6CAAqC,CAAA;IACrC,2CAAmC,CAAA;IACnC,uDAA+C,CAAA;IAC/C,yCAAiC,CAAA;IACjC,uCAA+B,CAAA;IAC/B,uCAA+B,CAAA;IAC/B,yCAAiC,CAAA;IACjC,uCAA+B,CAAA;IAC/B,+DAAuD,CAAA;IACvD,iDAAyC,CAAA;IACzC,mBAAW,CAAA;AACb,CAAC,EAlBW,IAAI,GAAJ,YAAI,KAAJ,YAAI,QAkBf;AAED,IAAY,SAuBX;AAvBD,WAAY,SAAS;IACnB,8CAAiC,CAAA;IACjC,0BAAa,CAAA;IACb,wCAA2B,CAAA;IAC3B,0CAA6B,CAAA;IAC7B,8BAAiB,CAAA;IACjB,8CAAiC,CAAA;IACjC,gDAAmC,CAAA;IACnC,wCAA2B,CAAA;IAC3B,wBAAW,CAAA;IACX,8BAAiB,CAAA;IACjB,sCAAyB,CAAA;IACzB,sDAAyC,CAAA;IACzC,8DAAiD,CAAA;IACjD,gDAAmC,CAAA;IACnC,0DAA6C,CAAA;IAC7C,8CAAiC,CAAA;IACjC,oCAAuB,CAAA;IACvB,oCAAuB,CAAA;IACvB,8BAAiB,CAAA;IACjB,gCAAmB,CAAA;IACnB,4CAA+B,CAAA;IAC/B,gCAAmB,CAAA;AACrB,CAAC,EAvBW,SAAS,GAAT,iBAAS,KAAT,iBAAS,QAuBpB;AAEY,QAAA,cAAc,GAAG,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC"}
package/lib/index.d.ts CHANGED
@@ -5,4 +5,7 @@ export * from './types';
5
5
  * String object.
6
6
  */
7
7
  export declare function isString(value: unknown): value is string | String;
8
+ export declare function isNonEmptyObject(value: unknown): value is object;
8
9
  export declare function encodeString(str: string): string;
10
+ export declare function simpleTraverse(obj: any, cb: Function): void;
11
+ export declare function installChildComponentsSync(parent: any, order: string[]): void;
package/lib/index.js CHANGED
@@ -28,7 +28,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
28
28
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
29
29
  };
30
30
  Object.defineProperty(exports, "__esModule", { value: true });
31
- exports.encodeString = exports.isString = void 0;
31
+ exports.installChildComponentsSync = exports.simpleTraverse = exports.encodeString = exports.isNonEmptyObject = exports.isString = void 0;
32
32
  __exportStar(require("./constants"), exports);
33
33
  __exportStar(require("./types"), exports);
34
34
  /**
@@ -40,8 +40,65 @@ function isString(value) {
40
40
  return typeof value === 'string' || value instanceof String;
41
41
  }
42
42
  exports.isString = isString;
43
+ function isNonEmptyObject(value) {
44
+ return !!value && typeof value === 'object' && Object.keys(value).length > 0;
45
+ }
46
+ exports.isNonEmptyObject = isNonEmptyObject;
47
+ /* c8 ignore next 3 */
43
48
  function encodeString(str) {
44
49
  return Buffer.from(str).toString('base64');
45
50
  }
46
51
  exports.encodeString = encodeString;
52
+ function simpleTraverse(obj, cb) {
53
+ if (typeof obj !== 'object' || obj === null) {
54
+ return;
55
+ }
56
+ const path = [];
57
+ /* eslint-disable complexity */
58
+ function traverse(obj) {
59
+ const isArray = Array.isArray(obj);
60
+ for (const k in obj) {
61
+ if (isArray) {
62
+ const _k = Number(k);
63
+ // if it is an array, store each index in path but don't call the
64
+ // callback on the index itself as they are just numeric strings.
65
+ path.push(_k);
66
+ if (typeof obj[_k] === 'object' && obj[_k] !== null) {
67
+ traverse(obj[_k]);
68
+ }
69
+ else if (typeof obj[_k] === 'string' && obj[_k]) {
70
+ cb(path, 'Value', obj[_k], obj);
71
+ }
72
+ path.pop();
73
+ }
74
+ else if (typeof obj[k] === 'object' && obj[k] !== null) {
75
+ cb(path, 'Key', k, obj);
76
+ path.push(k);
77
+ traverse(obj[k]);
78
+ path.pop();
79
+ }
80
+ else {
81
+ cb(path, 'Key', k, obj);
82
+ // only callback if the value is a non-empty string
83
+ if (typeof obj[k] === 'string' && obj[k]) {
84
+ path.push(k);
85
+ cb(path, 'Value', obj[k], obj);
86
+ path.pop();
87
+ }
88
+ }
89
+ }
90
+ }
91
+ traverse(obj);
92
+ }
93
+ exports.simpleTraverse = simpleTraverse;
94
+ function installChildComponentsSync(parent, order) {
95
+ const keys = order || Object.keys(parent);
96
+ for (const key of keys) {
97
+ const component = parent[key];
98
+ if (typeof component.install === 'function') {
99
+ component.install();
100
+ }
101
+ }
102
+ }
103
+ exports.installChildComponentsSync = installChildComponentsSync;
47
104
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;;;;;;;;;;;;;;;AAEH,8CAA4B;AAC5B,0CAAwB;AAExB;;;GAGG;AACH,wDAAwD;AACxD,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,MAAM,CAAC;AAC9D,CAAC;AAFD,4BAEC;AAED,SAAgB,YAAY,CAAC,GAAW;IACtC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAFD,oCAEC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,83 @@
1
+ /// <reference types="node" />
2
+ import { Event, Rule, ProtectRuleMode } from './constants';
3
+ import { EventEmitter } from 'events';
4
+ export declare type SemanticAnalysisRules = Rule.CMD_INJECTION_SEMANTIC_CHAINED_COMMANDS | Rule.CMD_INJECTION_COMMAND_BACKDOORS | Rule.CMD_INJECTION_SEMANTIC_DANGEROUS_PATHS;
5
+ export interface Result {
6
+ blocked: boolean;
7
+ ruleId: Rule;
8
+ inputType: string;
9
+ path?: string[];
10
+ key?: string;
11
+ value: string;
12
+ details?: any[];
13
+ mongoExpansionResult?: boolean;
14
+ idsList?: string[];
15
+ }
16
+ export interface SemanticAnalysisResult extends Result {
17
+ findings?: {
18
+ command?: string;
19
+ };
20
+ sinkContext?: any;
21
+ }
22
+ export interface HardeningResult extends Result {
23
+ findings?: {
24
+ command?: boolean;
25
+ deserializer?: string;
26
+ };
27
+ sinkContext?: any;
28
+ }
29
+ export interface ServerFeaturePreliminaryResult {
30
+ name?: string;
31
+ uuid: string;
32
+ ip?: string;
33
+ }
34
+ export interface ServerFeatureResult extends Result {
35
+ details?: ServerFeaturePreliminaryResult[];
36
+ }
37
+ export interface ReqData {
38
+ method: string;
39
+ headers: string[];
40
+ uriPath: string;
41
+ queries: string;
42
+ contentType?: string;
43
+ standardUrlParsing: boolean;
44
+ ip: string;
45
+ httpVersion: string;
46
+ }
47
+ export interface Findings {
48
+ trackRequest: boolean;
49
+ securityException?: [mode: ProtectRuleMode, ruleId: string];
50
+ bodyType?: 'json' | 'urlencoded';
51
+ resultsMap: Record<Rule, Result[]>;
52
+ semanticResultsMap: Record<Rule, SemanticAnalysisResult[]>;
53
+ serverFeaturesResultsMap: Record<Rule, ServerFeaturePreliminaryResult[]>;
54
+ hardeningResultsMap: Record<Rule, HardeningResult[]>;
55
+ }
56
+ export interface RequestStore {
57
+ protect?: ProtectMessage;
58
+ }
59
+ export interface ProtectMessage {
60
+ reqData: ReqData;
61
+ block: (mode: string, ruleId: string) => void;
62
+ policy: any;
63
+ exclusions: any[];
64
+ virtualPatches: any[];
65
+ findings: Findings;
66
+ parsedBody: any;
67
+ parsedCookies: any;
68
+ parsedParams: any;
69
+ parsedQuery: any;
70
+ }
71
+ export interface Messages extends EventEmitter {
72
+ addListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
73
+ emit(event: Event.PROTECT, msg: RequestStore): boolean;
74
+ emit(event: Event.SERVER_SETTINGS_UPDATE, msg: {
75
+ [key: string]: any;
76
+ }): boolean;
77
+ on(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
78
+ on(event: Event.SERVER_SETTINGS_UPDATE, listener: (msg: {
79
+ [key: string]: any;
80
+ }) => void): this;
81
+ prependListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
82
+ prependOnceListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
83
+ }
@@ -14,4 +14,4 @@
14
14
  * way not consistent with the End User License Agreement.
15
15
  */
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- //# sourceMappingURL=index.js.map
17
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/common",
3
- "version": "1.0.3",
3
+ "version": "1.1.1",
4
4
  "description": "Shared constants and utilities for all Contrast Agent modules",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
package/src/constants.ts CHANGED
@@ -16,6 +16,13 @@
16
16
  export enum Event {
17
17
  ASSESS = 'assess',
18
18
  PROTECT = 'protect',
19
+ SERVER_SETTINGS_UPDATE = 'server-settings-update',
20
+ }
21
+ export enum ProtectRuleMode {
22
+ OFF = 'off',
23
+ MONITOR = 'monitor',
24
+ BLOCK = 'block',
25
+ BLOCK_AT_PERIMETER = 'block_at_perimeter',
19
26
  }
20
27
 
21
28
  export enum Rule {
@@ -37,3 +44,31 @@ export enum Rule {
37
44
  UNSAFE_FILE_UPLOAD = 'unsafe-file-upload',
38
45
  XXE = 'xxe',
39
46
  }
47
+
48
+ export enum InputType {
49
+ UNDEFINED_TYPE = 'UNDEFINED_TYPE',
50
+ BODY = 'BODY',
51
+ COOKIE_NAME = 'COOKIE_NAME',
52
+ COOKIE_VALUE = 'COOKIE_VALUE',
53
+ HEADER = 'HEADER',
54
+ PARAMETER_NAME = 'PARAMETER_NAME',
55
+ PARAMETER_VALUE = 'PARAMETER_VALUE',
56
+ QUERYSTRING = 'QUERYSTRING',
57
+ URI = 'URI',
58
+ SOCKET = 'SOCKET',
59
+ JSON_VALUE = 'JSON_VALUE',
60
+ JSON_ARRAYED_VALUE = 'JSON_ARRAYED_VALUE',
61
+ MULTIPART_CONTENT_TYPE = 'MULTIPART_CONTENT_TYPE',
62
+ MULTIPART_VALUE = 'MULTIPART_VALUE',
63
+ MULTIPART_FIELD_NAME = 'MULTIPART_FIELD_NAME',
64
+ MULTIPART_NAME = 'MULTIPART_NAME',
65
+ XML_VALUE = 'XML_VALUE',
66
+ DWR_VALUE = 'DWR_VALUE',
67
+ METHOD = 'METHOD',
68
+ REQUEST = 'REQUEST',
69
+ URL_PARAMETER = 'URL_PARAMETER',
70
+ UNKNOWN = 'UNKNOWN',
71
+ }
72
+
73
+ export const BLOCKING_MODES = ['block', 'block_at_perimeter'];
74
+
package/src/index.ts CHANGED
@@ -25,6 +25,61 @@ export function isString(value: unknown): value is string | String {
25
25
  return typeof value === 'string' || value instanceof String;
26
26
  }
27
27
 
28
+ export function isNonEmptyObject(value: unknown): value is object {
29
+ return !!value && typeof value === 'object' && Object.keys(value).length > 0;
30
+ }
31
+
32
+ /* c8 ignore next 3 */
28
33
  export function encodeString(str: string): string {
29
34
  return Buffer.from(str).toString('base64');
30
35
  }
36
+
37
+ export function simpleTraverse(obj: any, cb: Function) {
38
+ if (typeof obj !== 'object' || obj === null) {
39
+ return;
40
+ }
41
+ const path: any[] = [];
42
+ /* eslint-disable complexity */
43
+ function traverse(obj: any) {
44
+ const isArray = Array.isArray(obj);
45
+ for (const k in obj) {
46
+ if (isArray) {
47
+ const _k = Number(k);
48
+ // if it is an array, store each index in path but don't call the
49
+ // callback on the index itself as they are just numeric strings.
50
+ path.push(_k);
51
+ if (typeof obj[_k] === 'object' && obj[_k] !== null) {
52
+ traverse(obj[_k]);
53
+ } else if (typeof obj[_k] === 'string' && obj[_k]) {
54
+ cb(path, 'Value', obj[_k], obj);
55
+ }
56
+ path.pop();
57
+ } else if (typeof obj[k] === 'object' && obj[k] !== null) {
58
+ cb(path, 'Key', k, obj);
59
+ path.push(k);
60
+ traverse(obj[k]);
61
+ path.pop();
62
+ } else {
63
+ cb(path, 'Key', k, obj);
64
+ // only callback if the value is a non-empty string
65
+ if (typeof obj[k] === 'string' && obj[k]) {
66
+ path.push(k);
67
+ cb(path, 'Value', obj[k], obj);
68
+ path.pop();
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ traverse(obj);
75
+ }
76
+
77
+ export function installChildComponentsSync(parent: any, order: string[]) {
78
+ const keys = order || Object.keys(parent);
79
+ for (const key of keys) {
80
+ const component: any = parent[key];
81
+ if (typeof component.install === 'function') {
82
+ component.install();
83
+ }
84
+ }
85
+ }
@@ -13,23 +13,46 @@
13
13
  * way not consistent with the End User License Agreement.
14
14
  */
15
15
 
16
- import { Event, Rule } from '../constants';
16
+ import { Event, Rule, ProtectRuleMode } from './constants';
17
17
  import { EventEmitter } from 'events';
18
18
 
19
- export interface RuleConfig {
20
- mode: 'monitor' | 'block' | 'block_at_perimeter' | 'off';
21
- }
22
-
23
- export interface RulesConfig extends Record<Rule, RuleConfig> {}
19
+ export type SemanticAnalysisRules = Rule.CMD_INJECTION_SEMANTIC_CHAINED_COMMANDS | Rule.CMD_INJECTION_COMMAND_BACKDOORS | Rule.CMD_INJECTION_SEMANTIC_DANGEROUS_PATHS;
24
20
 
25
21
  export interface Result {
26
22
  blocked: boolean;
27
23
  ruleId: Rule,
28
24
  inputType: string, // TODO
29
- path: string[],
30
- key: string,
25
+ path?: string[],
26
+ key?: string,
31
27
  value: string,
32
28
  details?: any[], // TODO
29
+ mongoExpansionResult?: boolean,
30
+ idsList?: string[],
31
+ }
32
+
33
+ export interface SemanticAnalysisResult extends Result {
34
+ findings?: {
35
+ command?: string
36
+ }
37
+ sinkContext?: any
38
+ }
39
+
40
+ export interface HardeningResult extends Result {
41
+ findings?: {
42
+ command?: boolean,
43
+ deserializer?: string
44
+ }
45
+ sinkContext?: any
46
+ }
47
+
48
+ export interface ServerFeaturePreliminaryResult {
49
+ name?: string,
50
+ uuid: string,
51
+ ip?: string
52
+ }
53
+
54
+ export interface ServerFeatureResult extends Result {
55
+ details?: ServerFeaturePreliminaryResult[]
33
56
  }
34
57
 
35
58
  export interface ReqData {
@@ -41,14 +64,16 @@ export interface ReqData {
41
64
  standardUrlParsing: boolean;
42
65
  ip: string;
43
66
  httpVersion: string,
44
- headers2: { [key: string]: Array<string> };
45
67
  }
46
68
 
47
69
  export interface Findings {
48
70
  trackRequest: boolean;
49
- securityException?: [mode: string, ruleId: string];
71
+ securityException?: [mode: ProtectRuleMode, ruleId: string];
50
72
  bodyType?: 'json' | 'urlencoded';
51
- resultsMap: Record<Rule, Result[]>
73
+ resultsMap: Record<Rule, Result[]>;
74
+ semanticResultsMap: Record<Rule, SemanticAnalysisResult[]>;
75
+ serverFeaturesResultsMap: Record<Rule, ServerFeaturePreliminaryResult[]>;
76
+ hardeningResultsMap: Record<Rule, HardeningResult[]>;
52
77
  }
53
78
 
54
79
  //
@@ -69,21 +94,22 @@ export interface RequestStore {
69
94
  export interface ProtectMessage {
70
95
  reqData: ReqData;
71
96
  block: (mode: string, ruleId: string) => void;
72
- rules: {
73
- agentLibRules: RulesConfig;
74
- agentLibRulesMask: number;
75
- agentRules: RulesConfig;
76
- };
97
+ policy: any;
77
98
  exclusions: any[]; // TODO
78
99
  virtualPatches: any[]; // TODO
79
100
  findings: Findings;
101
+ parsedBody: any;
102
+ parsedCookies: any;
103
+ parsedParams: any;
104
+ parsedQuery: any;
80
105
  }
81
106
 
82
107
  export interface Messages extends EventEmitter {
83
108
  addListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
84
109
  emit(event: Event.PROTECT, msg: RequestStore): boolean;
110
+ emit(event: Event.SERVER_SETTINGS_UPDATE, msg: { [key: string]: any }): boolean;
85
111
  on(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
86
- once(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
112
+ on(event: Event.SERVER_SETTINGS_UPDATE, listener: (msg: { [key: string]: any }) => void): this;
87
113
  prependListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
88
114
  prependOnceListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
89
115
  }
@@ -1,59 +0,0 @@
1
- /// <reference types="node" />
2
- import { Event, Rule } from '../constants';
3
- import { EventEmitter } from 'events';
4
- export interface RuleConfig {
5
- mode: 'monitor' | 'block' | 'block_at_perimeter' | 'off';
6
- }
7
- export interface RulesConfig extends Record<Rule, RuleConfig> {
8
- }
9
- export interface Result {
10
- blocked: boolean;
11
- ruleId: Rule;
12
- inputType: string;
13
- path: string[];
14
- key: string;
15
- value: string;
16
- details?: any[];
17
- }
18
- export interface ReqData {
19
- method: string;
20
- headers: string[];
21
- uriPath: string;
22
- queries: string;
23
- contentType?: string;
24
- standardUrlParsing: boolean;
25
- ip: string;
26
- httpVersion: string;
27
- headers2: {
28
- [key: string]: Array<string>;
29
- };
30
- }
31
- export interface Findings {
32
- trackRequest: boolean;
33
- securityException?: [mode: string, ruleId: string];
34
- bodyType?: 'json' | 'urlencoded';
35
- resultsMap: Record<Rule, Result[]>;
36
- }
37
- export interface RequestStore {
38
- protect?: ProtectMessage;
39
- }
40
- export interface ProtectMessage {
41
- reqData: ReqData;
42
- block: (mode: string, ruleId: string) => void;
43
- rules: {
44
- agentLibRules: RulesConfig;
45
- agentLibRulesMask: number;
46
- agentRules: RulesConfig;
47
- };
48
- exclusions: any[];
49
- virtualPatches: any[];
50
- findings: Findings;
51
- }
52
- export interface Messages extends EventEmitter {
53
- addListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
54
- emit(event: Event.PROTECT, msg: RequestStore): boolean;
55
- on(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
56
- once(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
57
- prependListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
58
- prependOnceListener(event: Event.PROTECT, listener: (msg: RequestStore) => void): this;
59
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG"}