@queno/agent-node 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 +421 -0
- package/dist/agent.d.ts +222 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +591 -0
- package/dist/agent.js.map +1 -0
- package/dist/api-discovery/discovery-buffer.d.ts +27 -0
- package/dist/api-discovery/discovery-buffer.d.ts.map +1 -0
- package/dist/api-discovery/discovery-buffer.js +50 -0
- package/dist/api-discovery/discovery-buffer.js.map +1 -0
- package/dist/api-discovery/endpoint-observer.d.ts +25 -0
- package/dist/api-discovery/endpoint-observer.d.ts.map +1 -0
- package/dist/api-discovery/endpoint-observer.js +127 -0
- package/dist/api-discovery/endpoint-observer.js.map +1 -0
- package/dist/api-discovery/route-normalizer.d.ts +15 -0
- package/dist/api-discovery/route-normalizer.d.ts.map +1 -0
- package/dist/api-discovery/route-normalizer.js +34 -0
- package/dist/api-discovery/route-normalizer.js.map +1 -0
- package/dist/config.d.ts +100 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +101 -0
- package/dist/config.js.map +1 -0
- package/dist/db-hooks/correlate.d.ts +19 -0
- package/dist/db-hooks/correlate.d.ts.map +1 -0
- package/dist/db-hooks/correlate.js +45 -0
- package/dist/db-hooks/correlate.js.map +1 -0
- package/dist/db-hooks/instrument.d.ts +27 -0
- package/dist/db-hooks/instrument.d.ts.map +1 -0
- package/dist/db-hooks/instrument.js +194 -0
- package/dist/db-hooks/instrument.js.map +1 -0
- package/dist/detectors/base.d.ts +61 -0
- package/dist/detectors/base.d.ts.map +1 -0
- package/dist/detectors/base.js +57 -0
- package/dist/detectors/base.js.map +1 -0
- package/dist/detectors/bola.d.ts +60 -0
- package/dist/detectors/bola.d.ts.map +1 -0
- package/dist/detectors/bola.js +108 -0
- package/dist/detectors/bola.js.map +1 -0
- package/dist/detectors/command-injection.d.ts +22 -0
- package/dist/detectors/command-injection.d.ts.map +1 -0
- package/dist/detectors/command-injection.js +41 -0
- package/dist/detectors/command-injection.js.map +1 -0
- package/dist/detectors/custom-rule.d.ts +24 -0
- package/dist/detectors/custom-rule.d.ts.map +1 -0
- package/dist/detectors/custom-rule.js +65 -0
- package/dist/detectors/custom-rule.js.map +1 -0
- package/dist/detectors/index.d.ts +17 -0
- package/dist/detectors/index.d.ts.map +1 -0
- package/dist/detectors/index.js +31 -0
- package/dist/detectors/index.js.map +1 -0
- package/dist/detectors/nosql-injection.d.ts +23 -0
- package/dist/detectors/nosql-injection.d.ts.map +1 -0
- package/dist/detectors/nosql-injection.js +54 -0
- package/dist/detectors/nosql-injection.js.map +1 -0
- package/dist/detectors/path-traversal.d.ts +21 -0
- package/dist/detectors/path-traversal.d.ts.map +1 -0
- package/dist/detectors/path-traversal.js +54 -0
- package/dist/detectors/path-traversal.js.map +1 -0
- package/dist/detectors/prototype-pollution.d.ts +23 -0
- package/dist/detectors/prototype-pollution.d.ts.map +1 -0
- package/dist/detectors/prototype-pollution.js +50 -0
- package/dist/detectors/prototype-pollution.js.map +1 -0
- package/dist/detectors/sql-injection.d.ts +22 -0
- package/dist/detectors/sql-injection.d.ts.map +1 -0
- package/dist/detectors/sql-injection.js +42 -0
- package/dist/detectors/sql-injection.js.map +1 -0
- package/dist/detectors/ssrf.d.ts +26 -0
- package/dist/detectors/ssrf.d.ts.map +1 -0
- package/dist/detectors/ssrf.js +37 -0
- package/dist/detectors/ssrf.js.map +1 -0
- package/dist/detectors/suspicious-headers.d.ts +25 -0
- package/dist/detectors/suspicious-headers.d.ts.map +1 -0
- package/dist/detectors/suspicious-headers.js +87 -0
- package/dist/detectors/suspicious-headers.js.map +1 -0
- package/dist/detectors/template-injection.d.ts +27 -0
- package/dist/detectors/template-injection.d.ts.map +1 -0
- package/dist/detectors/template-injection.js +35 -0
- package/dist/detectors/template-injection.js.map +1 -0
- package/dist/detectors/xss.d.ts +22 -0
- package/dist/detectors/xss.d.ts.map +1 -0
- package/dist/detectors/xss.js +38 -0
- package/dist/detectors/xss.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/express.d.ts +39 -0
- package/dist/integrations/express.d.ts.map +1 -0
- package/dist/integrations/express.js +62 -0
- package/dist/integrations/express.js.map +1 -0
- package/dist/integrations/fastify.d.ts +33 -0
- package/dist/integrations/fastify.d.ts.map +1 -0
- package/dist/integrations/fastify.js +63 -0
- package/dist/integrations/fastify.js.map +1 -0
- package/dist/integrations/nestjs.d.ts +40 -0
- package/dist/integrations/nestjs.d.ts.map +1 -0
- package/dist/integrations/nestjs.js +58 -0
- package/dist/integrations/nestjs.js.map +1 -0
- package/dist/policy/canonical.d.ts +23 -0
- package/dist/policy/canonical.d.ts.map +1 -0
- package/dist/policy/canonical.js +40 -0
- package/dist/policy/canonical.js.map +1 -0
- package/dist/policy/policy-manager.d.ts +43 -0
- package/dist/policy/policy-manager.d.ts.map +1 -0
- package/dist/policy/policy-manager.js +89 -0
- package/dist/policy/policy-manager.js.map +1 -0
- package/dist/policy/types.d.ts +70 -0
- package/dist/policy/types.d.ts.map +1 -0
- package/dist/policy/types.js +2 -0
- package/dist/policy/types.js.map +1 -0
- package/dist/policy/verify.d.ts +11 -0
- package/dist/policy/verify.d.ts.map +1 -0
- package/dist/policy/verify.js +61 -0
- package/dist/policy/verify.js.map +1 -0
- package/dist/redaction/audit-log.d.ts +40 -0
- package/dist/redaction/audit-log.d.ts.map +1 -0
- package/dist/redaction/audit-log.js +110 -0
- package/dist/redaction/audit-log.js.map +1 -0
- package/dist/redaction/engine.d.ts +50 -0
- package/dist/redaction/engine.d.ts.map +1 -0
- package/dist/redaction/engine.js +143 -0
- package/dist/redaction/engine.js.map +1 -0
- package/dist/redaction/patterns.d.ts +24 -0
- package/dist/redaction/patterns.d.ts.map +1 -0
- package/dist/redaction/patterns.js +142 -0
- package/dist/redaction/patterns.js.map +1 -0
- package/dist/runtime-context.d.ts +33 -0
- package/dist/runtime-context.d.ts.map +1 -0
- package/dist/runtime-context.js +46 -0
- package/dist/runtime-context.js.map +1 -0
- package/dist/self-protect.d.ts +34 -0
- package/dist/self-protect.d.ts.map +1 -0
- package/dist/self-protect.js +134 -0
- package/dist/self-protect.js.map +1 -0
- package/dist/transport/buffer.d.ts +52 -0
- package/dist/transport/buffer.d.ts.map +1 -0
- package/dist/transport/buffer.js +57 -0
- package/dist/transport/buffer.js.map +1 -0
- package/dist/transport/client.d.ts +77 -0
- package/dist/transport/client.d.ts.map +1 -0
- package/dist/transport/client.js +178 -0
- package/dist/transport/client.js.map +1 -0
- package/dist/transport/heartbeat.d.ts +86 -0
- package/dist/transport/heartbeat.d.ts.map +1 -0
- package/dist/transport/heartbeat.js +110 -0
- package/dist/transport/heartbeat.js.map +1 -0
- package/dist/transport/secure-request.d.ts +30 -0
- package/dist/transport/secure-request.d.ts.map +1 -0
- package/dist/transport/secure-request.js +95 -0
- package/dist/transport/secure-request.js.map +1 -0
- package/dist/types.d.ts +311 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
package/dist/agent.js
ADDED
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@link RaspAgent} - the entry point of the RASP runtime.
|
|
3
|
+
*
|
|
4
|
+
* Wires together five subsystems:
|
|
5
|
+
* 1. Detectors - pattern matchers run on every incoming request.
|
|
6
|
+
* 2. Redaction engine - strips secrets/PII before anything leaves the process.
|
|
7
|
+
* 3. Audit log - local JSONL trace of every redaction action.
|
|
8
|
+
* 4. Event buffer - batches sanitised events to the collector.
|
|
9
|
+
* 5. Heartbeat - liveness signal + kill-switch / policy delivery channel.
|
|
10
|
+
*
|
|
11
|
+
* Invariants enforced here:
|
|
12
|
+
* - {@link RaspAgent.inspect} never throws (fail-open).
|
|
13
|
+
* - A detection is **never** enqueued before passing through the redaction
|
|
14
|
+
* engine; if redaction fails the event is dropped and audit-logged.
|
|
15
|
+
* - When the kill switch is received, inspection is disabled and the buffer
|
|
16
|
+
* is drained.
|
|
17
|
+
*/
|
|
18
|
+
import { validateConfig, COLLECTOR_URL } from "./config.js";
|
|
19
|
+
import { RedactionEngine } from "./redaction/engine.js";
|
|
20
|
+
import { AuditLog } from "./redaction/audit-log.js";
|
|
21
|
+
import { TransportClient } from "./transport/client.js";
|
|
22
|
+
import { EventBuffer } from "./transport/buffer.js";
|
|
23
|
+
import { HeartbeatScheduler } from "./transport/heartbeat.js";
|
|
24
|
+
import { createDefaultDetectors } from "./detectors/index.js";
|
|
25
|
+
import { CustomRuleDetector } from "./detectors/custom-rule.js";
|
|
26
|
+
import { extractPathId, extractJwtSub } from "./detectors/bola.js";
|
|
27
|
+
import { EndpointObserver } from "./api-discovery/endpoint-observer.js";
|
|
28
|
+
import { DiscoveryBuffer } from "./api-discovery/discovery-buffer.js";
|
|
29
|
+
import { PolicyManager } from "./policy/policy-manager.js";
|
|
30
|
+
import { instrumentDatabaseDrivers } from "./db-hooks/instrument.js";
|
|
31
|
+
import { correlateBola } from "./db-hooks/correlate.js";
|
|
32
|
+
import { startSelfProtection } from "./self-protect.js";
|
|
33
|
+
import { enterContext } from "./runtime-context.js";
|
|
34
|
+
export class RaspAgent {
|
|
35
|
+
/** Fully validated configuration with defaults applied. */
|
|
36
|
+
cfg;
|
|
37
|
+
redaction;
|
|
38
|
+
auditLog;
|
|
39
|
+
client;
|
|
40
|
+
buffer;
|
|
41
|
+
heartbeat;
|
|
42
|
+
/** Built-in signature detectors. */
|
|
43
|
+
baseDetectors;
|
|
44
|
+
/** User-supplied detectors passed to the constructor. */
|
|
45
|
+
extraDetectors;
|
|
46
|
+
/** Active detector chain, rebuilt when custom rules arrive via policy. */
|
|
47
|
+
detectors;
|
|
48
|
+
observer;
|
|
49
|
+
discoveryBuffer;
|
|
50
|
+
/** Verifies and tracks signed policies distributed by the control plane. */
|
|
51
|
+
policyManager;
|
|
52
|
+
/** Data residency directives applied in {@link handleDetection}. */
|
|
53
|
+
dataResidency = null;
|
|
54
|
+
/** Version the control plane wants this agent to run (canary cohort / pin). */
|
|
55
|
+
targetVersion = null;
|
|
56
|
+
/** True when an upgrade is available for this agent. */
|
|
57
|
+
upgradePending = false;
|
|
58
|
+
/** Set to true after a kill-switch heartbeat - short-circuits {@link inspect}. */
|
|
59
|
+
killed = false;
|
|
60
|
+
/** Stops the self-protection timer (Addendum E.7); null when disabled. */
|
|
61
|
+
stopSelfProtection = null;
|
|
62
|
+
/**
|
|
63
|
+
* Enforcement mode in effect. Initialised from `cfg.mode` and updated
|
|
64
|
+
* whenever the collector returns a different mode in a heartbeat response.
|
|
65
|
+
*/
|
|
66
|
+
currentMode;
|
|
67
|
+
/**
|
|
68
|
+
* Deduplication key for `policy_rejected` telemetry: `"<version>:<reason>"`.
|
|
69
|
+
* Prevents spamming the collector on every heartbeat cycle when the same
|
|
70
|
+
* policy is repeatedly rejected (e.g. a persistent trust-anchor mismatch).
|
|
71
|
+
*/
|
|
72
|
+
lastRejectedPolicyKey = null;
|
|
73
|
+
/**
|
|
74
|
+
* Build a new agent.
|
|
75
|
+
*
|
|
76
|
+
* The constructor validates the config (throws on bad input), instantiates
|
|
77
|
+
* the subsystems and registers the default detectors. The heartbeat loop is
|
|
78
|
+
* **not** started until {@link start} is called.
|
|
79
|
+
*
|
|
80
|
+
* @param rawConfig - User-supplied configuration. Validated via
|
|
81
|
+
* {@link validateConfig}; throws if required fields are missing.
|
|
82
|
+
* @param extraDetectors - Optional custom detectors appended after the
|
|
83
|
+
* built-in set. They run in declaration order and the first non-null
|
|
84
|
+
* detection wins.
|
|
85
|
+
*/
|
|
86
|
+
constructor(rawConfig, extraDetectors = []) {
|
|
87
|
+
this.cfg = validateConfig(rawConfig);
|
|
88
|
+
this.currentMode = this.cfg.mode;
|
|
89
|
+
this.redaction = new RedactionEngine();
|
|
90
|
+
this.auditLog = this.cfg.auditLog
|
|
91
|
+
? new AuditLog(this.cfg.auditLogPath, this.cfg.auditLogMaxBytes)
|
|
92
|
+
: null;
|
|
93
|
+
this.client = new TransportClient({
|
|
94
|
+
collectorUrl: COLLECTOR_URL,
|
|
95
|
+
apiKey: this.cfg.apiKey,
|
|
96
|
+
timeoutMs: this.cfg.transportTimeoutMs,
|
|
97
|
+
hmacSecret: this.cfg.hmacSecret,
|
|
98
|
+
tls: this.cfg.tls,
|
|
99
|
+
});
|
|
100
|
+
this.buffer = new EventBuffer(this.client, {
|
|
101
|
+
flushIntervalMs: this.cfg.flushIntervalMs,
|
|
102
|
+
maxSize: this.cfg.bufferMaxSize,
|
|
103
|
+
});
|
|
104
|
+
this.heartbeat = new HeartbeatScheduler(this.client, this.cfg, {
|
|
105
|
+
onKillSwitch: () => this.handleKillSwitch(),
|
|
106
|
+
onRecover: () => this.handleRecover(),
|
|
107
|
+
onPolicyChange: (version) => this.handlePolicyChange(version),
|
|
108
|
+
onModeChange: (mode) => {
|
|
109
|
+
// When a trust anchor is configured, mode changes must arrive through
|
|
110
|
+
// a verified signed policy (applyPolicy). The heartbeat mode field is
|
|
111
|
+
// an unsigned hint from the collector and must not bypass Ed25519
|
|
112
|
+
// verification - otherwise a compromised network path or collector
|
|
113
|
+
// could silently switch block → monitor (Addendum E.4.1).
|
|
114
|
+
//
|
|
115
|
+
// When no trust anchor is configured (e.g. legacy deployments that
|
|
116
|
+
// pre-date the signed-policy system) the heartbeat mode is the only
|
|
117
|
+
// available control channel, so we keep the original behaviour.
|
|
118
|
+
if (!this.policyManager.hasTrustAnchor) {
|
|
119
|
+
this.currentMode = mode;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
onTargetVersion: (info) => this.handleTargetVersion(info),
|
|
123
|
+
getMode: () => this.currentMode,
|
|
124
|
+
});
|
|
125
|
+
this.baseDetectors = createDefaultDetectors();
|
|
126
|
+
this.extraDetectors = extraDetectors;
|
|
127
|
+
this.detectors = [...this.baseDetectors, ...this.extraDetectors];
|
|
128
|
+
this.policyManager = new PolicyManager(this.cfg.projectId, [this.cfg.policyPublicKey]);
|
|
129
|
+
this.observer = new EndpointObserver();
|
|
130
|
+
this.discoveryBuffer = new DiscoveryBuffer(this.client, this.observer, {
|
|
131
|
+
projectId: this.cfg.projectId,
|
|
132
|
+
agentId: this.cfg.agentId,
|
|
133
|
+
flushIntervalMs: this.cfg.discoveryFlushIntervalMs,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Start the heartbeat loop. Idempotent.
|
|
138
|
+
*
|
|
139
|
+
* Call once during application bootstrap, after the framework middleware
|
|
140
|
+
* has been registered. The buffer flush timer is already armed by the
|
|
141
|
+
* constructor.
|
|
142
|
+
*/
|
|
143
|
+
start() {
|
|
144
|
+
if (this.cfg.instrumentDb) {
|
|
145
|
+
// Best-effort; never throws.
|
|
146
|
+
instrumentDatabaseDrivers();
|
|
147
|
+
}
|
|
148
|
+
if (this.cfg.selfProtect) {
|
|
149
|
+
this.stopSelfProtection = startSelfProtection({
|
|
150
|
+
checkHooks: this.cfg.instrumentDb,
|
|
151
|
+
antiDebug: true,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
this.heartbeat.start();
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Begin a request's runtime context for DB correlation. Called by the
|
|
158
|
+
* framework integration at the start of the request, before the handler runs,
|
|
159
|
+
* so DB queries issued during the request are attributed to it.
|
|
160
|
+
*
|
|
161
|
+
* @returns The bound context, or `null` when DB instrumentation is disabled.
|
|
162
|
+
*/
|
|
163
|
+
beginRequest(req) {
|
|
164
|
+
if (!this.cfg.instrumentDb || this.killed)
|
|
165
|
+
return null;
|
|
166
|
+
const ctx = {
|
|
167
|
+
method: req.method,
|
|
168
|
+
path: req.path,
|
|
169
|
+
pathId: extractPathId(req.path),
|
|
170
|
+
userId: extractJwtSub(req.headers["authorization"]),
|
|
171
|
+
sourceIp: req.sourceIp,
|
|
172
|
+
authEnforced: false,
|
|
173
|
+
dbQueries: [],
|
|
174
|
+
};
|
|
175
|
+
try {
|
|
176
|
+
enterContext(ctx);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
return ctx;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Finalise a request: record its outcome for traffic profiling and, when a
|
|
185
|
+
* DB context is present, run BOLA-via-DB correlation and report any finding.
|
|
186
|
+
*/
|
|
187
|
+
endRequest(ctx, req, outcome) {
|
|
188
|
+
this.observeOutcome(req, outcome);
|
|
189
|
+
if (!ctx || this.killed)
|
|
190
|
+
return;
|
|
191
|
+
try {
|
|
192
|
+
if (outcome.authenticated) {
|
|
193
|
+
ctx.authEnforced = true;
|
|
194
|
+
if (!ctx.userId)
|
|
195
|
+
ctx.userId = "authenticated";
|
|
196
|
+
}
|
|
197
|
+
const detection = correlateBola(ctx);
|
|
198
|
+
if (detection)
|
|
199
|
+
this.handleDetection(detection, req).catch(() => { });
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// Fail open.
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The enforcement mode currently in effect. Reflects remote mode changes
|
|
207
|
+
* (heartbeat) and applied policies, so integrations should consult this
|
|
208
|
+
* rather than the boot config.
|
|
209
|
+
*/
|
|
210
|
+
get mode() {
|
|
211
|
+
return this.currentMode;
|
|
212
|
+
}
|
|
213
|
+
/** The policy version currently applied (0 if none). */
|
|
214
|
+
get policyVersion() {
|
|
215
|
+
return this.policyManager.currentVersion;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Version the control plane wants this agent to run, and whether an upgrade
|
|
219
|
+
* is pending. The Node agent is delivered as an npm package and cannot
|
|
220
|
+
* hot-swap its own binary, so the upgrade is surfaced (logged + queryable)
|
|
221
|
+
* for the host's deployment automation to act on, rather than self-applied.
|
|
222
|
+
*/
|
|
223
|
+
get desiredVersion() {
|
|
224
|
+
return { targetVersion: this.targetVersion, upgradePending: this.upgradePending };
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* React to the target version advertised by the heartbeat. Records the target
|
|
228
|
+
* and logs an actionable message when an upgrade is available. Never throws.
|
|
229
|
+
*/
|
|
230
|
+
handleTargetVersion(info) {
|
|
231
|
+
this.targetVersion = info.targetVersion;
|
|
232
|
+
this.upgradePending =
|
|
233
|
+
info.upgradeAvailable &&
|
|
234
|
+
info.targetVersion != null &&
|
|
235
|
+
info.targetVersion !== this.cfg.agentVersion;
|
|
236
|
+
if (this.upgradePending) {
|
|
237
|
+
const parts = [`[rasp] upgrade available: ${this.cfg.agentVersion ?? "?"} -> ${info.targetVersion}`];
|
|
238
|
+
if (info.impact)
|
|
239
|
+
parts.push(`impact: ${info.impact}`);
|
|
240
|
+
if (info.changelog)
|
|
241
|
+
parts.push(`changelog: ${info.changelog}`);
|
|
242
|
+
try {
|
|
243
|
+
console.info(parts.join(" | "));
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// Ignore logging failures.
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Graceful shutdown.
|
|
252
|
+
*
|
|
253
|
+
* Stops the heartbeat timer, drains the buffer (final flush) and closes
|
|
254
|
+
* the audit log file descriptor. Safe to await during process exit.
|
|
255
|
+
*/
|
|
256
|
+
async stop() {
|
|
257
|
+
this.heartbeat.stop();
|
|
258
|
+
this.stopSelfProtection?.();
|
|
259
|
+
await this.buffer.stop();
|
|
260
|
+
await this.discoveryBuffer.stop();
|
|
261
|
+
this.auditLog?.close();
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Run every detector against a normalised request.
|
|
265
|
+
*
|
|
266
|
+
* Detectors run in registration order; the first one returning a non-null
|
|
267
|
+
* result wins. Detector exceptions are swallowed so that a bug in one
|
|
268
|
+
* detector cannot take down the host application.
|
|
269
|
+
*
|
|
270
|
+
* @param req - Framework-agnostic request view.
|
|
271
|
+
* @returns The first {@link DetectionResult} found, or `null` when the
|
|
272
|
+
* request is clean (or when the kill switch is active).
|
|
273
|
+
*
|
|
274
|
+
* @remarks Side-effects (redaction, audit log, buffering) happen in the
|
|
275
|
+
* background via {@link handleDetection}; this method itself returns
|
|
276
|
+
* synchronously.
|
|
277
|
+
*/
|
|
278
|
+
/**
|
|
279
|
+
* Record the response-phase outcome of a request for API-discovery traffic
|
|
280
|
+
* profiling (status code, latency, confirmed auth middleware execution).
|
|
281
|
+
* Called by the framework integration's response hook. Never throws.
|
|
282
|
+
*/
|
|
283
|
+
observeOutcome(req, outcome) {
|
|
284
|
+
if (this.killed)
|
|
285
|
+
return;
|
|
286
|
+
try {
|
|
287
|
+
this.observer.observeOutcome(req, outcome);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
// Fail open.
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
inspect(req) {
|
|
294
|
+
if (this.killed)
|
|
295
|
+
return null;
|
|
296
|
+
// Observe passively before running detectors - fail open
|
|
297
|
+
this.observer.observe(req);
|
|
298
|
+
for (const detector of this.detectors) {
|
|
299
|
+
let result = null;
|
|
300
|
+
try {
|
|
301
|
+
result = detector.detect(req);
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
if (result) {
|
|
307
|
+
this.handleDetection(result, req).catch(() => { });
|
|
308
|
+
return result;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Build a raw event payload, redact it, audit-log locally and enqueue it.
|
|
315
|
+
*
|
|
316
|
+
* Control flow:
|
|
317
|
+
* 1. Assemble the raw {@link EventPayload} from config + detection + request.
|
|
318
|
+
* 2. Run it through the {@link RedactionEngine}. On failure → drop and
|
|
319
|
+
* audit-log with `dropped: true`.
|
|
320
|
+
* 3. If any field was redacted → write a non-dropped audit-log line.
|
|
321
|
+
* 4. Stamp `auditLoggedLocally` into the event metadata and enqueue.
|
|
322
|
+
*/
|
|
323
|
+
async handleDetection(detection, req) {
|
|
324
|
+
const raw = {
|
|
325
|
+
projectId: this.cfg.projectId,
|
|
326
|
+
agentId: this.cfg.agentId,
|
|
327
|
+
agentVersion: this.cfg.agentVersion,
|
|
328
|
+
runtime: this.cfg.runtime,
|
|
329
|
+
framework: this.cfg.framework,
|
|
330
|
+
eventType: detection.eventType,
|
|
331
|
+
severity: detection.severity,
|
|
332
|
+
action: this.currentMode,
|
|
333
|
+
method: req.method,
|
|
334
|
+
path: req.path,
|
|
335
|
+
sourceIp: req.sourceIp,
|
|
336
|
+
timestamp: new Date().toISOString(),
|
|
337
|
+
metadata: {
|
|
338
|
+
redacted: true,
|
|
339
|
+
matchedRule: detection.detectorName,
|
|
340
|
+
detectorDescription: detection.description,
|
|
341
|
+
location: detection.location,
|
|
342
|
+
matchedValue: detection.matchedValue,
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
let redacted;
|
|
346
|
+
let redactedFields;
|
|
347
|
+
try {
|
|
348
|
+
const result = this.redaction.redact(raw);
|
|
349
|
+
redacted = result.redacted;
|
|
350
|
+
redactedFields = result.redactedFields;
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
this.auditLog?.write({
|
|
354
|
+
ts: new Date().toISOString(),
|
|
355
|
+
agentId: this.cfg.agentId,
|
|
356
|
+
projectId: this.cfg.projectId,
|
|
357
|
+
eventType: detection.eventType,
|
|
358
|
+
redactedFields: [],
|
|
359
|
+
dropped: true,
|
|
360
|
+
dropReason: err instanceof Error ? err.message : "redaction_failed",
|
|
361
|
+
});
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const auditLoggedLocally = redactedFields.length > 0;
|
|
365
|
+
this.auditLog?.write({
|
|
366
|
+
ts: new Date().toISOString(),
|
|
367
|
+
agentId: this.cfg.agentId,
|
|
368
|
+
projectId: this.cfg.projectId,
|
|
369
|
+
eventType: detection.eventType,
|
|
370
|
+
severity: detection.severity,
|
|
371
|
+
detectorName: detection.detectorName,
|
|
372
|
+
redactedFields,
|
|
373
|
+
dropped: false,
|
|
374
|
+
});
|
|
375
|
+
const event = redacted;
|
|
376
|
+
event.metadata["auditLoggedLocally"] = auditLoggedLocally;
|
|
377
|
+
const forSend = this.applyDataResidency(event);
|
|
378
|
+
if (forSend) {
|
|
379
|
+
this.buffer.enqueue(forSend);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Apply data residency directives (Addendum B.3) before an event is queued
|
|
384
|
+
* for transmission.
|
|
385
|
+
*
|
|
386
|
+
* @returns The (possibly trimmed) event to send, or `null` if the event must
|
|
387
|
+
* stay local / be skipped. The local audit log has already been written by
|
|
388
|
+
* the caller, so dropping here still leaves a verifiable local record.
|
|
389
|
+
*/
|
|
390
|
+
applyDataResidency(event) {
|
|
391
|
+
const dr = this.dataResidency;
|
|
392
|
+
if (!dr)
|
|
393
|
+
return event;
|
|
394
|
+
// Local-only: nothing leaves the customer environment.
|
|
395
|
+
if (dr.localOnly)
|
|
396
|
+
return null;
|
|
397
|
+
// Selective export by event type.
|
|
398
|
+
if (dr.exportEventTypes && dr.exportEventTypes.length > 0) {
|
|
399
|
+
if (!dr.exportEventTypes.includes(event.eventType))
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
// Selective export: blocked detections only.
|
|
403
|
+
if (dr.exportBlockedOnly && event.action !== "block")
|
|
404
|
+
return null;
|
|
405
|
+
// Metadata-only: strip everything but the minimal envelope + flags.
|
|
406
|
+
if (dr.metadataOnly) {
|
|
407
|
+
return {
|
|
408
|
+
...event,
|
|
409
|
+
metadata: {
|
|
410
|
+
redacted: true,
|
|
411
|
+
matchedRule: event.metadata.matchedRule,
|
|
412
|
+
auditLoggedLocally: event.metadata.auditLoggedLocally,
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
return event;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Handle a kill-switch heartbeat response.
|
|
420
|
+
*
|
|
421
|
+
* Disables inspection, drains the buffer and closes the audit log. The
|
|
422
|
+
* heartbeat scheduler has already stopped itself by the time this is
|
|
423
|
+
* called.
|
|
424
|
+
*/
|
|
425
|
+
handleKillSwitch() {
|
|
426
|
+
this.killed = true;
|
|
427
|
+
this.stopSelfProtection?.();
|
|
428
|
+
this.stopSelfProtection = null;
|
|
429
|
+
// Buffers and audit log are kept open so they can resume if the kill
|
|
430
|
+
// switch is lifted. Only agent.stop() (graceful shutdown) closes them.
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Called when the kill switch transitions from active back to inactive.
|
|
434
|
+
* Re-enables inspection and restarts self-protection if configured.
|
|
435
|
+
*/
|
|
436
|
+
handleRecover() {
|
|
437
|
+
this.killed = false;
|
|
438
|
+
if (this.cfg.selfProtect && !this.stopSelfProtection) {
|
|
439
|
+
this.stopSelfProtection = startSelfProtection({
|
|
440
|
+
checkHooks: this.cfg.instrumentDb,
|
|
441
|
+
antiDebug: true,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* React to a policy-version change signalled by the heartbeat.
|
|
447
|
+
*
|
|
448
|
+
* Fetches the latest signed policy, verifies its Ed25519 signature against
|
|
449
|
+
* the pinned trust anchor, and applies it. An untrusted, malformed or stale
|
|
450
|
+
* policy is ignored and the agent keeps its current configuration
|
|
451
|
+
* (self-rollback of policy - Addendum D.4 / E.4.1). Never throws.
|
|
452
|
+
*
|
|
453
|
+
* Rejections are surfaced via a `console.warn` and a `policy_rejected`
|
|
454
|
+
* telemetry event so operators can diagnose trust-anchor mismatches without
|
|
455
|
+
* reading raw application logs.
|
|
456
|
+
*/
|
|
457
|
+
handlePolicyChange(version) {
|
|
458
|
+
void version;
|
|
459
|
+
if (this.killed)
|
|
460
|
+
return;
|
|
461
|
+
if (!this.policyManager.hasTrustAnchor) {
|
|
462
|
+
try {
|
|
463
|
+
console.warn("[rasp] policy update ignored: no trust anchor configured");
|
|
464
|
+
}
|
|
465
|
+
catch {
|
|
466
|
+
// Ignore logging failures.
|
|
467
|
+
}
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
this.client
|
|
471
|
+
.fetchPolicy(this.cfg.agentId, this.cfg.channel)
|
|
472
|
+
.then((policy) => {
|
|
473
|
+
if (!policy)
|
|
474
|
+
return;
|
|
475
|
+
const result = this.policyManager.accept(policy);
|
|
476
|
+
if (result.applied) {
|
|
477
|
+
try {
|
|
478
|
+
this.applyPolicy(policy);
|
|
479
|
+
}
|
|
480
|
+
catch {
|
|
481
|
+
// Self-rollback: applying the new policy failed - restore the
|
|
482
|
+
// previous one so the agent keeps a known-good configuration.
|
|
483
|
+
const restored = this.policyManager.rollback();
|
|
484
|
+
if (restored) {
|
|
485
|
+
try {
|
|
486
|
+
this.applyPolicy(restored);
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
// Give up safely; existing in-memory config remains.
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
try {
|
|
496
|
+
console.warn(`[rasp] policy v${policy.version} rejected: ${result.reason}` +
|
|
497
|
+
(policy.signingKeyId ? ` (keyId: ${policy.signingKeyId})` : ""));
|
|
498
|
+
}
|
|
499
|
+
catch {
|
|
500
|
+
// Ignore logging failures.
|
|
501
|
+
}
|
|
502
|
+
this.enqueuePolicyRejected(policy.version, result.reason ?? "unknown", policy.signingKeyId);
|
|
503
|
+
}
|
|
504
|
+
})
|
|
505
|
+
.catch(() => {
|
|
506
|
+
// Fail-safe: keep the current policy on any error.
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Emit a single `policy_rejected` telemetry event so the control plane can
|
|
511
|
+
* surface trust-anchor or signature mismatches in the dashboard.
|
|
512
|
+
*
|
|
513
|
+
* The event is deduplicated by `version:reason` so a persistent rejection
|
|
514
|
+
* (e.g. a misconfigured trust anchor that the operator has not yet fixed)
|
|
515
|
+
* does not flood the collector on every heartbeat cycle.
|
|
516
|
+
*
|
|
517
|
+
* The payload passes through the redaction engine (Addendum B.2 / AGENTS.md
|
|
518
|
+
* rule: "All telemetry must pass through the redaction engine before
|
|
519
|
+
* buffering") and the data-residency filter before being enqueued.
|
|
520
|
+
*/
|
|
521
|
+
enqueuePolicyRejected(version, reason, signingKeyId) {
|
|
522
|
+
const key = `${version}:${reason}`;
|
|
523
|
+
if (key === this.lastRejectedPolicyKey)
|
|
524
|
+
return;
|
|
525
|
+
this.lastRejectedPolicyKey = key;
|
|
526
|
+
const raw = {
|
|
527
|
+
projectId: this.cfg.projectId,
|
|
528
|
+
agentId: this.cfg.agentId,
|
|
529
|
+
agentVersion: this.cfg.agentVersion,
|
|
530
|
+
runtime: this.cfg.runtime,
|
|
531
|
+
framework: this.cfg.framework,
|
|
532
|
+
eventType: "policy_rejected",
|
|
533
|
+
severity: "low",
|
|
534
|
+
action: this.currentMode,
|
|
535
|
+
timestamp: new Date().toISOString(),
|
|
536
|
+
metadata: {
|
|
537
|
+
redacted: true,
|
|
538
|
+
version,
|
|
539
|
+
reason,
|
|
540
|
+
...(signingKeyId ? { signingKeyId } : {}),
|
|
541
|
+
},
|
|
542
|
+
};
|
|
543
|
+
let event;
|
|
544
|
+
try {
|
|
545
|
+
event = this.redaction.redact(raw).redacted;
|
|
546
|
+
}
|
|
547
|
+
catch {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const forSend = this.applyDataResidency(event);
|
|
551
|
+
if (forSend) {
|
|
552
|
+
this.buffer.enqueue(forSend);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Apply a verified policy to the live agent: enforcement mode, customer
|
|
557
|
+
* detection rules, redaction configuration and data residency directives.
|
|
558
|
+
*/
|
|
559
|
+
applyPolicy(policy) {
|
|
560
|
+
// Mode
|
|
561
|
+
if (policy.mode === "monitor" || policy.mode === "block") {
|
|
562
|
+
this.currentMode = policy.mode;
|
|
563
|
+
}
|
|
564
|
+
// Custom detection rules → rebuild the detector chain.
|
|
565
|
+
this.rebuildDetectors(policy.detectionRules ?? []);
|
|
566
|
+
// Redaction configuration.
|
|
567
|
+
this.applyRedactionConfig(policy.redactionConfig);
|
|
568
|
+
// Data residency directives.
|
|
569
|
+
this.dataResidency = policy.dataResidency ?? null;
|
|
570
|
+
}
|
|
571
|
+
/** Rebuild the active detector chain from base + custom rules + extras. */
|
|
572
|
+
rebuildDetectors(rules) {
|
|
573
|
+
const next = [...this.baseDetectors];
|
|
574
|
+
if (rules.length > 0) {
|
|
575
|
+
const custom = new CustomRuleDetector(rules);
|
|
576
|
+
if (custom.size > 0)
|
|
577
|
+
next.push(custom);
|
|
578
|
+
}
|
|
579
|
+
next.push(...this.extraDetectors);
|
|
580
|
+
this.detectors = next;
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Reconfigure the redaction engine from a policy. The engine always keeps its
|
|
584
|
+
* built-in protections; the policy can only add field-name patterns and tune
|
|
585
|
+
* value-based redaction / IP handling.
|
|
586
|
+
*/
|
|
587
|
+
applyRedactionConfig(cfg) {
|
|
588
|
+
this.redaction = RedactionEngine.fromConfig(cfg ?? undefined);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Periodic buffer that drains {@link EndpointObserver} and ships batches to
|
|
3
|
+
* the collector via {@link TransportClient.sendDiscovery}.
|
|
4
|
+
*
|
|
5
|
+
* - Flushes every `flushIntervalMs` milliseconds (default 60 s).
|
|
6
|
+
* - Sends at most 500 endpoints per HTTP call; splits into multiple calls if needed.
|
|
7
|
+
* - Fail-open: transport errors are swallowed so the host application is not affected.
|
|
8
|
+
*/
|
|
9
|
+
import type { TransportClient } from "../transport/client.js";
|
|
10
|
+
import type { EndpointObserver } from "./endpoint-observer.js";
|
|
11
|
+
export interface DiscoveryBufferOptions {
|
|
12
|
+
projectId: string;
|
|
13
|
+
agentId: string;
|
|
14
|
+
flushIntervalMs: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class DiscoveryBuffer {
|
|
17
|
+
private readonly client;
|
|
18
|
+
private readonly observer;
|
|
19
|
+
private readonly projectId;
|
|
20
|
+
private readonly agentId;
|
|
21
|
+
private timer;
|
|
22
|
+
constructor(client: TransportClient, observer: EndpointObserver, opts: DiscoveryBufferOptions);
|
|
23
|
+
/** Stop the flush timer and send a final batch. */
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
private flush;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=discovery-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery-buffer.d.ts","sourceRoot":"","sources":["../../src/api-discovery/discovery-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB;AAID,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,KAAK,CAA+C;gBAG1D,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,sBAAsB;IAe9B,mDAAmD;IAC7C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAQb,KAAK;CAqBpB"}
|