@anomira/node-sdk 0.1.0 → 0.1.2
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/README.md +131 -0
- package/package.json +29 -15
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# @anomira/node-sdk
|
|
2
|
+
|
|
3
|
+
Drop-in API security monitoring for Node.js. Detect brute force, credential stuffing, account takeover, data scraping, path traversal, XSS, geo-velocity attacks, and more — in real time.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @anomira/node-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { SentinelAPI } from "@anomira/node-sdk";
|
|
15
|
+
|
|
16
|
+
const sentinel = new SentinelAPI({
|
|
17
|
+
apiKey: process.env.ANOMIRA_API_KEY!,
|
|
18
|
+
appId: process.env.ANOMIRA_APP_ID!,
|
|
19
|
+
});
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Express
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import express from "express";
|
|
26
|
+
import { SentinelAPI } from "@anomira/node-sdk";
|
|
27
|
+
|
|
28
|
+
const app = express();
|
|
29
|
+
const sentinel = new SentinelAPI({
|
|
30
|
+
apiKey: process.env.ANOMIRA_API_KEY!,
|
|
31
|
+
appId: process.env.ANOMIRA_APP_ID!,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Add as global middleware — must come before your routes
|
|
35
|
+
app.use(sentinel.express());
|
|
36
|
+
|
|
37
|
+
app.listen(3000);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Fastify
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import Fastify from "fastify";
|
|
44
|
+
import { SentinelAPI } from "@anomira/node-sdk";
|
|
45
|
+
|
|
46
|
+
const app = Fastify();
|
|
47
|
+
const sentinel = new SentinelAPI({
|
|
48
|
+
apiKey: process.env.ANOMIRA_API_KEY!,
|
|
49
|
+
appId: process.env.ANOMIRA_APP_ID!,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
await app.register(sentinel.fastify());
|
|
53
|
+
|
|
54
|
+
app.listen({ port: 3000 });
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Manual Event Tracking
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
// Track a failed OTP attempt
|
|
61
|
+
sentinel.track("auth.otp.failed", {
|
|
62
|
+
ip: req.ip,
|
|
63
|
+
userId: req.body.phone,
|
|
64
|
+
meta: { endpoint: "/api/verify-otp" },
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Track a login and run geo-velocity check automatically
|
|
68
|
+
await sentinel.trackLogin({ ip: req.ip, userId: user.id });
|
|
69
|
+
|
|
70
|
+
// Track phone-based auth (SIM swap detection)
|
|
71
|
+
sentinel.trackPhoneAuth({ ip: req.ip, userId: user.id, phone: user.phone });
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Structured Logging
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
sentinel.log("info", "User registered", { userId: user.id });
|
|
78
|
+
sentinel.log("warn", "Slow DB query", { queryMs: 1240 });
|
|
79
|
+
sentinel.log("error", "Payment failed", { reason: err.message });
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Blocklist & Firewall
|
|
83
|
+
|
|
84
|
+
The SDK syncs your blocklist and firewall rules from the dashboard every 60 seconds. In your own middleware you can check:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
if (sentinel.isBlocked(req.ip)) {
|
|
88
|
+
return res.status(403).json({ error: "Forbidden" });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const match = sentinel.matchFirewallRule({
|
|
92
|
+
url: req.url,
|
|
93
|
+
body: req.body,
|
|
94
|
+
headers: req.headers as Record<string, string>,
|
|
95
|
+
ip: req.ip,
|
|
96
|
+
});
|
|
97
|
+
if (match?.rule.action === "block") {
|
|
98
|
+
return res.status(403).json({ error: "Blocked by firewall rule" });
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Secret Scanner CLI
|
|
103
|
+
|
|
104
|
+
Scan your codebase for hardcoded secrets, API keys, and PII before they reach production:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npx anomira scan ./src
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Exit code `1` if violations are found — CI/CD compatible.
|
|
111
|
+
|
|
112
|
+
## Configuration
|
|
113
|
+
|
|
114
|
+
| Option | Type | Default | Description |
|
|
115
|
+
|---|---|---|---|
|
|
116
|
+
| `apiKey` | `string` | — | Your Anomira API key (required) |
|
|
117
|
+
| `appId` | `string` | — | Your Anomira app ID (required) |
|
|
118
|
+
| `ingestUrl` | `string` | Anomira cloud | Custom ingest endpoint |
|
|
119
|
+
| `debug` | `boolean` | `false` | Log SDK activity to console |
|
|
120
|
+
| `captureConsole` | `boolean` | `false` | Forward `console.*` calls to the Logs dashboard |
|
|
121
|
+
| `service` | `string` | `"app"` | Service name tag for logs |
|
|
122
|
+
| `detect.bruteForce` | `boolean` | `true` | Detect brute force login attempts |
|
|
123
|
+
| `detect.rateAbuse` | `boolean` | `true` | Detect rate limit abuse |
|
|
124
|
+
| `detect.pathTraversal` | `boolean` | `true` | Detect path traversal attempts |
|
|
125
|
+
| `detect.xss` | `boolean` | `true` | Detect XSS in request bodies |
|
|
126
|
+
| `detect.scanDetection` | `boolean` | `true` | Detect scanner/bot probing |
|
|
127
|
+
| `detect.geoVelocity` | `boolean` | `true` | Detect impossible travel between logins |
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anomira/node-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Anomira Node.js SDK — drop-in API security monitoring for Express and Fastify",
|
|
5
5
|
"author": "Anomira <sdk@anomira.io>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,35 +17,49 @@
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
-
"main":
|
|
20
|
+
"main": "./dist/index.cjs",
|
|
21
21
|
"module": "./dist/index.js",
|
|
22
22
|
"types": "./dist/index.d.ts",
|
|
23
|
-
"files": [
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
24
27
|
"bin": {
|
|
25
28
|
"anomira": "./dist/cli.js"
|
|
26
29
|
},
|
|
27
30
|
"scripts": {
|
|
28
|
-
"build":
|
|
29
|
-
"dev":
|
|
31
|
+
"build": "tsup",
|
|
32
|
+
"dev": "tsup --watch",
|
|
30
33
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
31
|
-
"test":
|
|
32
|
-
"test:watch":"vitest"
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest"
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {},
|
|
35
38
|
"devDependencies": {
|
|
36
|
-
"@types/node":
|
|
37
|
-
"@types/express":
|
|
38
|
-
"typescript":
|
|
39
|
-
"tsup":
|
|
40
|
-
"vitest":
|
|
39
|
+
"@types/node": "^20.12.12",
|
|
40
|
+
"@types/express": "^4.17.21",
|
|
41
|
+
"typescript": "^5.4.5",
|
|
42
|
+
"tsup": "^8.0.2",
|
|
43
|
+
"vitest": "^1.6.0"
|
|
41
44
|
},
|
|
42
45
|
"peerDependencies": {
|
|
43
46
|
"express": ">=4.0.0",
|
|
44
47
|
"fastify": ">=4.0.0"
|
|
45
48
|
},
|
|
46
49
|
"peerDependenciesMeta": {
|
|
47
|
-
"express": {
|
|
48
|
-
|
|
50
|
+
"express": {
|
|
51
|
+
"optional": true
|
|
52
|
+
},
|
|
53
|
+
"fastify": {
|
|
54
|
+
"optional": true
|
|
55
|
+
}
|
|
49
56
|
},
|
|
50
|
-
"keywords": [
|
|
57
|
+
"keywords": [
|
|
58
|
+
"security",
|
|
59
|
+
"api",
|
|
60
|
+
"monitoring",
|
|
61
|
+
"anomira",
|
|
62
|
+
"fraud-detection",
|
|
63
|
+
"api-security"
|
|
64
|
+
]
|
|
51
65
|
}
|