@blamejs/core 0.14.26 → 0.15.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.
- package/CHANGELOG.md +6 -0
- package/README.md +2 -2
- package/index.js +4 -0
- package/lib/agent-envelope-mac.js +104 -0
- package/lib/agent-event-bus.js +105 -4
- package/lib/agent-posture-chain.js +8 -42
- package/lib/ai-content-detect.js +9 -10
- package/lib/api-key.js +107 -74
- package/lib/atomic-file.js +62 -4
- package/lib/audit-chain.js +47 -11
- package/lib/audit-sign.js +77 -2
- package/lib/audit-tools.js +79 -51
- package/lib/audit.js +249 -123
- package/lib/auth/openid-federation.js +108 -47
- package/lib/backup/index.js +13 -10
- package/lib/break-glass.js +202 -144
- package/lib/cache.js +174 -105
- package/lib/chain-writer.js +38 -16
- package/lib/cli.js +19 -14
- package/lib/cluster-provider-db.js +130 -104
- package/lib/cluster-storage.js +119 -22
- package/lib/cluster.js +119 -71
- package/lib/compliance.js +169 -4
- package/lib/consent.js +73 -24
- package/lib/constants.js +16 -11
- package/lib/crypto-field.js +474 -92
- package/lib/db-declare-row-policy.js +35 -22
- package/lib/db-file-lifecycle.js +3 -2
- package/lib/db-query.js +497 -255
- package/lib/db-schema.js +209 -44
- package/lib/db.js +176 -95
- package/lib/error-page.js +14 -1
- package/lib/external-db-migrate.js +229 -139
- package/lib/external-db.js +25 -15
- package/lib/file-upload.js +52 -7
- package/lib/framework-error.js +14 -1
- package/lib/framework-files.js +73 -0
- package/lib/framework-schema.js +695 -394
- package/lib/gate-contract.js +649 -1
- package/lib/guard-agent-registry.js +26 -44
- package/lib/guard-all.js +1 -0
- package/lib/guard-auth.js +42 -112
- package/lib/guard-cidr.js +33 -154
- package/lib/guard-csv.js +46 -113
- package/lib/guard-domain.js +34 -157
- package/lib/guard-dsn.js +27 -43
- package/lib/guard-email.js +47 -69
- package/lib/guard-envelope.js +19 -32
- package/lib/guard-event-bus-payload.js +24 -42
- package/lib/guard-event-bus-topic.js +25 -43
- package/lib/guard-filename.js +42 -106
- package/lib/guard-graphql.js +42 -123
- package/lib/guard-html.js +53 -108
- package/lib/guard-idempotency-key.js +24 -42
- package/lib/guard-image.js +46 -103
- package/lib/guard-imap-command.js +18 -32
- package/lib/guard-jmap.js +16 -30
- package/lib/guard-json.js +38 -108
- package/lib/guard-jsonpath.js +38 -171
- package/lib/guard-jwt.js +49 -179
- package/lib/guard-list-id.js +25 -41
- package/lib/guard-list-unsubscribe.js +27 -43
- package/lib/guard-mail-compose.js +24 -42
- package/lib/guard-mail-move.js +26 -44
- package/lib/guard-mail-query.js +28 -46
- package/lib/guard-mail-reply.js +24 -42
- package/lib/guard-mail-sieve.js +24 -42
- package/lib/guard-managesieve-command.js +17 -31
- package/lib/guard-markdown.js +37 -104
- package/lib/guard-message-id.js +26 -45
- package/lib/guard-mime.js +39 -151
- package/lib/guard-oauth.js +54 -135
- package/lib/guard-pdf.js +45 -101
- package/lib/guard-pop3-command.js +21 -31
- package/lib/guard-posture-chain.js +24 -42
- package/lib/guard-regex.js +33 -107
- package/lib/guard-saga-config.js +24 -42
- package/lib/guard-shell.js +42 -172
- package/lib/guard-smtp-command.js +48 -54
- package/lib/guard-snapshot-envelope.js +24 -42
- package/lib/guard-sql.js +1491 -0
- package/lib/guard-stream-args.js +24 -43
- package/lib/guard-svg.js +47 -65
- package/lib/guard-template.js +35 -172
- package/lib/guard-tenant-id.js +26 -45
- package/lib/guard-time.js +32 -154
- package/lib/guard-trace-context.js +25 -44
- package/lib/guard-uuid.js +32 -153
- package/lib/guard-xml.js +38 -113
- package/lib/guard-yaml.js +51 -163
- package/lib/http-client.js +37 -9
- package/lib/inbox.js +120 -107
- package/lib/legal-hold.js +107 -50
- package/lib/log-stream-cloudwatch.js +47 -31
- package/lib/log-stream-otlp.js +32 -18
- package/lib/mail-crypto-smime.js +2 -6
- package/lib/mail-greylist.js +2 -6
- package/lib/mail-helo.js +2 -6
- package/lib/mail-journal.js +85 -64
- package/lib/mail-rbl.js +2 -6
- package/lib/mail-scan.js +2 -6
- package/lib/mail-server-jmap.js +117 -12
- package/lib/mail-spam-score.js +2 -6
- package/lib/mail-store.js +287 -154
- package/lib/middleware/body-parser.js +71 -25
- package/lib/middleware/csrf-protect.js +19 -8
- package/lib/middleware/fetch-metadata.js +17 -7
- package/lib/middleware/idempotency-key.js +54 -38
- package/lib/middleware/rate-limit.js +102 -32
- package/lib/middleware/security-headers.js +21 -5
- package/lib/migrations.js +108 -66
- package/lib/network-heartbeat.js +7 -0
- package/lib/nonce-store.js +31 -9
- package/lib/object-store/azure-blob-bucket-ops.js +9 -4
- package/lib/object-store/azure-blob.js +57 -3
- package/lib/object-store/sigv4.js +10 -0
- package/lib/observability.js +87 -0
- package/lib/otel-export.js +25 -1
- package/lib/outbox.js +136 -82
- package/lib/parsers/safe-xml.js +47 -7
- package/lib/pqc-agent.js +44 -0
- package/lib/pubsub-cluster.js +42 -20
- package/lib/queue-local.js +202 -139
- package/lib/queue-redis.js +9 -1
- package/lib/queue-sqs.js +6 -0
- package/lib/redact.js +68 -11
- package/lib/redis-client.js +160 -31
- package/lib/retention.js +82 -39
- package/lib/router.js +212 -5
- package/lib/safe-dns.js +29 -45
- package/lib/safe-ical.js +18 -33
- package/lib/safe-icap.js +27 -43
- package/lib/safe-sieve.js +21 -40
- package/lib/safe-sql.js +124 -3
- package/lib/safe-vcard.js +18 -33
- package/lib/scheduler.js +35 -12
- package/lib/seeders.js +122 -74
- package/lib/session-stores.js +42 -14
- package/lib/session.js +109 -72
- package/lib/sql.js +3885 -0
- package/lib/ssrf-guard.js +51 -4
- package/lib/static.js +177 -34
- package/lib/subject.js +55 -17
- package/lib/vault/index.js +3 -2
- package/lib/vault/passphrase-ops.js +3 -2
- package/lib/vault/rotate.js +104 -64
- package/lib/vendor-data.js +2 -0
- package/lib/websocket.js +35 -5
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/guard-stream-args.js
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
var { defineClass } = require("./framework-error");
|
|
23
|
+
var gateContract = require("./gate-contract");
|
|
23
24
|
|
|
24
25
|
var GuardStreamArgsError = defineClass("GuardStreamArgsError", { alwaysPermanent: true });
|
|
25
26
|
|
|
@@ -31,11 +32,14 @@ var PROFILES = Object.freeze({
|
|
|
31
32
|
permissive: { maxBatchSize: 16384, minBatchSize: 1, maxOpenStreams: 64 },
|
|
32
33
|
});
|
|
33
34
|
|
|
34
|
-
var COMPLIANCE_POSTURES =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
36
|
+
|
|
37
|
+
var _resolveProfile = gateContract.makeProfileResolver({
|
|
38
|
+
profiles: PROFILES,
|
|
39
|
+
postures: COMPLIANCE_POSTURES,
|
|
40
|
+
defaults: DEFAULT_PROFILE,
|
|
41
|
+
errorClass: GuardStreamArgsError,
|
|
42
|
+
codePrefix: "stream-args",
|
|
39
43
|
});
|
|
40
44
|
|
|
41
45
|
/**
|
|
@@ -90,23 +94,6 @@ function validate(args, opts) {
|
|
|
90
94
|
return args;
|
|
91
95
|
}
|
|
92
96
|
|
|
93
|
-
/**
|
|
94
|
-
* @primitive b.guardStreamArgs.compliancePosture
|
|
95
|
-
* @signature b.guardStreamArgs.compliancePosture(posture)
|
|
96
|
-
* @since 0.9.24
|
|
97
|
-
* @status stable
|
|
98
|
-
*
|
|
99
|
-
* Return the effective profile for a given compliance posture name.
|
|
100
|
-
* Returns `null` for unknown posture names so operator typos surface
|
|
101
|
-
* here instead of silently falling through to the default profile.
|
|
102
|
-
*
|
|
103
|
-
* @example
|
|
104
|
-
* b.guardStreamArgs.compliancePosture("hipaa"); // → "strict"
|
|
105
|
-
*/
|
|
106
|
-
function compliancePosture(posture) {
|
|
107
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
97
|
function _checkCursorOpts(cursorOpts, depth) {
|
|
111
98
|
depth = depth || 0;
|
|
112
99
|
if (depth > 8) { // recursion depth cap
|
|
@@ -143,24 +130,18 @@ function _checkCursorOpts(cursorOpts, depth) {
|
|
|
143
130
|
}
|
|
144
131
|
}
|
|
145
132
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
PROFILES: PROFILES,
|
|
162
|
-
COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
|
|
163
|
-
GuardStreamArgsError: GuardStreamArgsError,
|
|
164
|
-
NAME: "streamArgs",
|
|
165
|
-
KIND: "stream-args",
|
|
166
|
-
};
|
|
133
|
+
// compliancePosture is assembled by gateContract.defineParser below; its
|
|
134
|
+
// wiki section renders from the single-sourced @abiTemplate (defineParser)
|
|
135
|
+
// block in gate-contract.js, instantiated for this guard by the page
|
|
136
|
+
// generator.
|
|
137
|
+
module.exports = gateContract.defineParser({
|
|
138
|
+
name: "stream-args",
|
|
139
|
+
entry: validate,
|
|
140
|
+
errorClass: GuardStreamArgsError,
|
|
141
|
+
profiles: PROFILES,
|
|
142
|
+
postures: COMPLIANCE_POSTURES,
|
|
143
|
+
extra: {
|
|
144
|
+
NAME: "streamArgs",
|
|
145
|
+
KIND: "stream-args",
|
|
146
|
+
},
|
|
147
|
+
});
|
package/lib/guard-svg.js
CHANGED
|
@@ -1093,71 +1093,53 @@ function gate(opts) {
|
|
|
1093
1093
|
});
|
|
1094
1094
|
}
|
|
1095
1095
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
* @since 0.7.7
|
|
1102
|
-
* @status stable
|
|
1103
|
-
* @compliance hipaa, pci-dss, gdpr, soc2
|
|
1104
|
-
* @related b.guardSvg.gate, b.compliance.set
|
|
1105
|
-
*
|
|
1106
|
-
* Look up a regulatory-posture override. Returns a shallow clone
|
|
1107
|
-
* of the named posture's option overlay; throws
|
|
1108
|
-
* `GuardSvgError` (`svg.bad-posture`) on unknown names. Operators
|
|
1109
|
-
* pass it through `gate({ compliancePosture: "hipaa" })` rather
|
|
1110
|
-
* than calling this directly — exposed for introspection and
|
|
1111
|
-
* audit-evidence collection.
|
|
1112
|
-
*
|
|
1113
|
-
* @example
|
|
1114
|
-
* var hipaa = b.guardSvg.compliancePosture("hipaa");
|
|
1115
|
-
* hipaa.bidiPolicy; // → "reject"
|
|
1116
|
-
* hipaa.allowExternalRefs; // → false
|
|
1117
|
-
* hipaa.allowAnimation; // → false
|
|
1118
|
-
*/
|
|
1119
|
-
function compliancePosture(name) {
|
|
1120
|
-
return gateContract.lookupCompliancePosture(name, COMPLIANCE_POSTURES, _err, "svg");
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
var _svgRulePacks = gateContract.makeRulePackLoader(GuardSvgError, "svg");
|
|
1124
|
-
var loadRulePack = _svgRulePacks.load;
|
|
1096
|
+
// buildProfile / compliancePosture / loadRulePack are assembled by
|
|
1097
|
+
// gateContract.defineGuard below (makeProfileBuilder(PROFILES) /
|
|
1098
|
+
// lookupCompliancePosture(_, COMPLIANCE_POSTURES) / makeRulePackLoader).
|
|
1099
|
+
// Their wiki sections render from the single-sourced @abiTemplate blocks
|
|
1100
|
+
// in gate-contract.js, instantiated per guard by the page generator.
|
|
1125
1101
|
|
|
1126
1102
|
void safeUrl;
|
|
1127
1103
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1104
|
+
// ---- adaptive integration-test fixtures (consumed by layer-5 host harness) ----
|
|
1105
|
+
var INTEGRATION_FIXTURES = Object.freeze({
|
|
1106
|
+
kind: "content",
|
|
1107
|
+
contentType: "image/svg+xml",
|
|
1108
|
+
extension: ".svg",
|
|
1109
|
+
benignBytes: Buffer.from('<svg><circle r="10"/></svg>', "utf8"),
|
|
1110
|
+
// Hostile: <script> inside SVG; refused regardless of profile.
|
|
1111
|
+
hostileBytes: Buffer.from('<svg><script>alert(1)</script></svg>', "utf8"),
|
|
1112
|
+
});
|
|
1113
|
+
|
|
1114
|
+
// Assembled from the gate-contract guard factory: error class, registry
|
|
1115
|
+
// exports (NAME / KIND / MIME_TYPES / EXTENSIONS / INTEGRATION_FIXTURES),
|
|
1116
|
+
// buildProfile / compliancePosture / loadRulePack wiring, plus the
|
|
1117
|
+
// per-guard inspection surface (validate / sanitize / gate) and the SVG
|
|
1118
|
+
// tag / scheme tables passed through verbatim. The bespoke `gate` carries
|
|
1119
|
+
// SVG's sanitize-reserialize chain and SVGZ refuse unchanged.
|
|
1120
|
+
module.exports = gateContract.defineGuard({
|
|
1121
|
+
name: "svg",
|
|
1122
|
+
kind: "content",
|
|
1123
|
+
errorClass: GuardSvgError,
|
|
1124
|
+
profiles: PROFILES,
|
|
1125
|
+
defaults: DEFAULTS,
|
|
1126
|
+
postures: COMPLIANCE_POSTURES,
|
|
1127
|
+
mimeTypes: ["image/svg+xml"],
|
|
1128
|
+
extensions: [".svg", ".svgz"],
|
|
1129
|
+
integrationFixtures: INTEGRATION_FIXTURES,
|
|
1130
|
+
validate: validate,
|
|
1131
|
+
sanitize: sanitize,
|
|
1132
|
+
gate: gate,
|
|
1133
|
+
extra: {
|
|
1134
|
+
DANGEROUS_TAGS: DANGEROUS_TAGS,
|
|
1135
|
+
ANIMATION_TAGS: ANIMATION_TAGS,
|
|
1136
|
+
ANIMATION_SAFE_TARGETS: ANIMATION_SAFE_TARGETS,
|
|
1137
|
+
STRICT_ALLOWED_TAGS: STRICT_ALLOWED_TAGS,
|
|
1138
|
+
BALANCED_ALLOWED_TAGS: BALANCED_ALLOWED_TAGS,
|
|
1139
|
+
PERMISSIVE_ALLOWED_TAGS: PERMISSIVE_ALLOWED_TAGS,
|
|
1140
|
+
DANGEROUS_ATTRS: DANGEROUS_ATTRS,
|
|
1141
|
+
URL_ATTRS: URL_ATTRS,
|
|
1142
|
+
SAFE_SCHEMES: SAFE_SCHEMES,
|
|
1143
|
+
DANGEROUS_SCHEMES: DANGEROUS_SCHEMES,
|
|
1144
|
+
},
|
|
1145
|
+
});
|
package/lib/guard-template.js
CHANGED
|
@@ -311,180 +311,43 @@ function sanitize(input, opts) {
|
|
|
311
311
|
throw _err("template.bad-input", "sanitize requires string input");
|
|
312
312
|
}
|
|
313
313
|
var issues = _detectIssues(input, opts);
|
|
314
|
-
|
|
315
|
-
if (issues[i].severity === "critical" || issues[i].severity === "high") {
|
|
316
|
-
throw _err(issues[i].ruleId || "template.refused",
|
|
317
|
-
"guardTemplate.sanitize: " + issues[i].snippet);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
314
|
+
gateContract.throwOnRefusalSeverity(issues, { errorClass: GuardTemplateError, codePrefix: "template" });
|
|
320
315
|
return input;
|
|
321
316
|
}
|
|
322
317
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
*
|
|
331
|
-
* Build a `b.gateContract` gate that screens `ctx.identifier` (or
|
|
332
|
-
* `ctx.text`) before any template engine renders the input.
|
|
333
|
-
* Action chain: `serve` (no issues) → `audit-only` (warn-only) →
|
|
334
|
-
* `refuse` (any `critical` or `high`). No `sanitize` action —
|
|
335
|
-
* template input cannot be repaired. Compose into form handlers /
|
|
336
|
-
* comment renderers / model fields fed to Mustache / Handlebars /
|
|
337
|
-
* Liquid so operator-untrusted strings never reach the rendering
|
|
338
|
-
* engine carrying engine syntax.
|
|
339
|
-
*
|
|
340
|
-
* @opts
|
|
341
|
-
* profile: "strict"|"balanced"|"permissive",
|
|
342
|
-
* compliancePosture: "hipaa"|"pci-dss"|"gdpr"|"soc2",
|
|
343
|
-
* name: string, // override gate name in audit emissions
|
|
344
|
-
* jinjaPolicy: "reject"|"audit"|"allow",
|
|
345
|
-
* erbPolicy: "reject"|"audit"|"allow",
|
|
346
|
-
* pugPolicy: "reject"|"audit"|"allow",
|
|
347
|
-
* dollarBracePolicy: "reject"|"audit"|"allow",
|
|
348
|
-
* velocityDirectivePolicy: "reject"|"audit"|"allow",
|
|
349
|
-
* maxBytes: number,
|
|
350
|
-
*
|
|
351
|
-
* @example
|
|
352
|
-
* var gate = b.guardTemplate.gate({ profile: "strict" });
|
|
353
|
-
*
|
|
354
|
-
* gate({ identifier: "Hello {{7*7}}" }).then(function (rv) {
|
|
355
|
-
* rv.ok; // → false
|
|
356
|
-
* rv.action; // → "refuse"
|
|
357
|
-
* });
|
|
358
|
-
*
|
|
359
|
-
* gate({ identifier: "Hello world" }).then(function (rv) {
|
|
360
|
-
* rv.action; // → "serve"
|
|
361
|
-
* });
|
|
362
|
-
*/
|
|
363
|
-
function gate(opts) {
|
|
364
|
-
opts = _resolveOpts(opts);
|
|
365
|
-
return gateContract.buildGuardGate(
|
|
366
|
-
opts.name || "guardTemplate:" + (opts.profile || "default"),
|
|
367
|
-
opts,
|
|
368
|
-
async function (ctx) {
|
|
369
|
-
var text = ctx && (ctx.identifier || ctx.text);
|
|
370
|
-
if (text === undefined || text === null) {
|
|
371
|
-
return { ok: true, action: "serve" };
|
|
372
|
-
}
|
|
373
|
-
var rv = validate(text, opts);
|
|
374
|
-
if (rv.issues.length === 0) return { ok: true, action: "serve" };
|
|
375
|
-
var hasCritical = rv.issues.some(function (i) {
|
|
376
|
-
return i.severity === "critical";
|
|
377
|
-
});
|
|
378
|
-
var hasHigh = rv.issues.some(function (i) {
|
|
379
|
-
return i.severity === "high";
|
|
380
|
-
});
|
|
381
|
-
if (!hasCritical && !hasHigh) {
|
|
382
|
-
return { ok: true, action: "audit-only", issues: rv.issues };
|
|
383
|
-
}
|
|
384
|
-
return { ok: false, action: "refuse", issues: rv.issues };
|
|
385
|
-
});
|
|
386
|
-
}
|
|
318
|
+
// gate / buildProfile / compliancePosture / loadRulePack are assembled by
|
|
319
|
+
// gateContract.defineGuard below. The gate is the standard
|
|
320
|
+
// serve -> audit-only -> refuse chain (template input cannot be repaired, so
|
|
321
|
+
// there is no sanitize action), dispatched to ctx.identifier || ctx.text via
|
|
322
|
+
// the spec's ctxFields. Its wiki section renders from the single-sourced
|
|
323
|
+
// @abiTemplate (defineGuard) blocks in gate-contract.js, instantiated per
|
|
324
|
+
// guard by the page generator.
|
|
387
325
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
*
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
*
|
|
395
|
-
|
|
396
|
-
* bases plus inline overrides. `opts.extends` is a profile name
|
|
397
|
-
* (`"strict"` / `"balanced"` / `"permissive"`) or an array of
|
|
398
|
-
* names; later entries shadow earlier ones. Inline `opts` keys win
|
|
399
|
-
* last. Used to keep operator-defined profiles traceable to a
|
|
400
|
-
* baseline rather than re-typing every key.
|
|
401
|
-
*
|
|
402
|
-
* @opts
|
|
403
|
-
* extends: string|string[], // base profile name(s) to compose
|
|
404
|
-
* ...: any guardTemplate key, // inline override of resolved keys
|
|
405
|
-
*
|
|
406
|
-
* @example
|
|
407
|
-
* var custom = b.guardTemplate.buildProfile({
|
|
408
|
-
* extends: "balanced",
|
|
409
|
-
* dollarBracePolicy: "reject",
|
|
410
|
-
* });
|
|
411
|
-
* custom.dollarBracePolicy; // → "reject"
|
|
412
|
-
* custom.jinjaPolicy; // → "reject"
|
|
413
|
-
*/
|
|
414
|
-
var buildProfile = gateContract.makeProfileBuilder(PROFILES);
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* @primitive b.guardTemplate.compliancePosture
|
|
418
|
-
* @signature b.guardTemplate.compliancePosture(name)
|
|
419
|
-
* @since 0.7.13
|
|
420
|
-
* @status stable
|
|
421
|
-
* @compliance hipaa, pci-dss, gdpr, soc2
|
|
422
|
-
* @related b.guardTemplate.gate, b.guardTemplate.buildProfile
|
|
423
|
-
*
|
|
424
|
-
* Look up a compliance-posture overlay by name (`"hipaa"` /
|
|
425
|
-
* `"pci-dss"` / `"gdpr"` / `"soc2"`). Returns a shallow clone of
|
|
426
|
-
* the posture object — the caller may mutate freely. Throws
|
|
427
|
-
* `GuardTemplateError("template.bad-posture")` on unknown name.
|
|
428
|
-
*
|
|
429
|
-
* @example
|
|
430
|
-
* var posture = b.guardTemplate.compliancePosture("hipaa");
|
|
431
|
-
* posture.jinjaPolicy; // → "reject"
|
|
432
|
-
* posture.forensicSnippetBytes; // → 512
|
|
433
|
-
*/
|
|
434
|
-
function compliancePosture(name) {
|
|
435
|
-
return gateContract.lookupCompliancePosture(name, COMPLIANCE_POSTURES,
|
|
436
|
-
_err, "template");
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
var _tplRulePacks = gateContract.makeRulePackLoader(GuardTemplateError, "template");
|
|
440
|
-
/**
|
|
441
|
-
* @primitive b.guardTemplate.loadRulePack
|
|
442
|
-
* @signature b.guardTemplate.loadRulePack(pack)
|
|
443
|
-
* @since 0.7.13
|
|
444
|
-
* @status stable
|
|
445
|
-
* @related b.guardTemplate.gate
|
|
446
|
-
*
|
|
447
|
-
* Register an operator-supplied rule pack with the guardTemplate
|
|
448
|
-
* registry. The pack is identified by `pack.id` (non-empty string)
|
|
449
|
-
* and stored for later inspection / dispatch by gates that opt in
|
|
450
|
-
* via `opts.rulePackId`. Returns the pack object unchanged on
|
|
451
|
-
* success; throws `GuardTemplateError("template.bad-opt")` when
|
|
452
|
-
* `pack` is missing or `pack.id` is not a non-empty string.
|
|
453
|
-
*
|
|
454
|
-
* @example
|
|
455
|
-
* var pack = b.guardTemplate.loadRulePack({
|
|
456
|
-
* id: "no-prototype-keys",
|
|
457
|
-
* rules: [
|
|
458
|
-
* { id: "proto-key", severity: "critical",
|
|
459
|
-
* detect: function (text) { return /__proto__|constructor/.test(text); },
|
|
460
|
-
* reason: "input references prototype-pollution sink" },
|
|
461
|
-
* ],
|
|
462
|
-
* });
|
|
463
|
-
* pack.id; // → "no-prototype-keys"
|
|
464
|
-
*/
|
|
465
|
-
var loadRulePack = _tplRulePacks.load;
|
|
326
|
+
var INTEGRATION_FIXTURES = Object.freeze({
|
|
327
|
+
kind: "identifier",
|
|
328
|
+
benignBytes: Buffer.from("Hello world", "utf8"),
|
|
329
|
+
hostileBytes: Buffer.from("Hello {{7*7}}", "utf8"),
|
|
330
|
+
benignIdentifier: "Hello world",
|
|
331
|
+
// Hostile: Jinja-shape SSTI probe.
|
|
332
|
+
hostileIdentifier: "Hello {{7*7}}",
|
|
333
|
+
});
|
|
466
334
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
PROFILES: PROFILES,
|
|
487
|
-
DEFAULTS: DEFAULTS,
|
|
488
|
-
COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
|
|
489
|
-
GuardTemplateError: GuardTemplateError,
|
|
490
|
-
};
|
|
335
|
+
// Assembled from the gate-contract guard factory: error class, registry
|
|
336
|
+
// exports (NAME / KIND / INTEGRATION_FIXTURES), the default gate, buildProfile
|
|
337
|
+
// / compliancePosture / loadRulePack wiring, plus the per-guard inspection
|
|
338
|
+
// surface (validate / sanitize) passed through verbatim. The gate is the
|
|
339
|
+
// factory default serve -> audit-only -> refuse chain; ctxFields names the
|
|
340
|
+
// ctx fields it reads (ctx.identifier, then ctx.text) so untrusted strings on
|
|
341
|
+
// either field reach the SSTI validator before any engine renders them.
|
|
342
|
+
module.exports = gateContract.defineGuard({
|
|
343
|
+
name: "template",
|
|
344
|
+
kind: "identifier",
|
|
345
|
+
errorClass: GuardTemplateError,
|
|
346
|
+
profiles: PROFILES,
|
|
347
|
+
defaults: DEFAULTS,
|
|
348
|
+
postures: COMPLIANCE_POSTURES,
|
|
349
|
+
integrationFixtures: INTEGRATION_FIXTURES,
|
|
350
|
+
validate: validate,
|
|
351
|
+
sanitize: sanitize,
|
|
352
|
+
ctxFields: ["identifier", "text"],
|
|
353
|
+
});
|
package/lib/guard-tenant-id.js
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
var { defineClass } = require("./framework-error");
|
|
26
|
+
var gateContract = require("./gate-contract");
|
|
26
27
|
|
|
27
28
|
var GuardTenantIdError = defineClass("GuardTenantIdError", { alwaysPermanent: true });
|
|
28
29
|
|
|
@@ -34,15 +35,18 @@ var PROFILES = Object.freeze({
|
|
|
34
35
|
permissive: { maxBytes: 512 },
|
|
35
36
|
});
|
|
36
37
|
|
|
37
|
-
var COMPLIANCE_POSTURES =
|
|
38
|
-
hipaa: "strict",
|
|
39
|
-
"pci-dss": "strict",
|
|
40
|
-
gdpr: "strict",
|
|
41
|
-
soc2: "strict",
|
|
42
|
-
});
|
|
38
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
43
39
|
|
|
44
40
|
var RESERVED = Object.freeze({ "ROOT": true, "FRAMEWORK": true, "*": true });
|
|
45
41
|
|
|
42
|
+
var _resolveProfile = gateContract.makeProfileResolver({
|
|
43
|
+
profiles: PROFILES,
|
|
44
|
+
postures: COMPLIANCE_POSTURES,
|
|
45
|
+
defaults: DEFAULT_PROFILE,
|
|
46
|
+
errorClass: GuardTenantIdError,
|
|
47
|
+
codePrefix: "tenant-id",
|
|
48
|
+
});
|
|
49
|
+
|
|
46
50
|
/**
|
|
47
51
|
* @primitive b.guardTenantId.validate
|
|
48
52
|
* @signature b.guardTenantId.validate(tenantId, opts?)
|
|
@@ -97,42 +101,19 @@ function validate(tenantId, opts) {
|
|
|
97
101
|
return tenantId;
|
|
98
102
|
}
|
|
99
103
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function _resolveProfile(opts) {
|
|
118
|
-
if (opts.posture && COMPLIANCE_POSTURES[opts.posture]) {
|
|
119
|
-
return COMPLIANCE_POSTURES[opts.posture];
|
|
120
|
-
}
|
|
121
|
-
var p = opts.profile || DEFAULT_PROFILE;
|
|
122
|
-
if (!PROFILES[p]) {
|
|
123
|
-
throw new GuardTenantIdError("tenant-id/bad-profile",
|
|
124
|
-
"guardTenantId: unknown profile '" + p + "'");
|
|
125
|
-
}
|
|
126
|
-
return p;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
module.exports = {
|
|
130
|
-
validate: validate,
|
|
131
|
-
compliancePosture: compliancePosture,
|
|
132
|
-
PROFILES: PROFILES,
|
|
133
|
-
COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
|
|
134
|
-
RESERVED: RESERVED,
|
|
135
|
-
GuardTenantIdError: GuardTenantIdError,
|
|
136
|
-
NAME: "tenantId",
|
|
137
|
-
KIND: "tenant-id",
|
|
138
|
-
};
|
|
104
|
+
// compliancePosture is assembled by gateContract.defineParser below; its
|
|
105
|
+
// wiki section renders from the single-sourced @abiTemplate (defineParser)
|
|
106
|
+
// block in gate-contract.js, instantiated for this guard by the page
|
|
107
|
+
// generator.
|
|
108
|
+
module.exports = gateContract.defineParser({
|
|
109
|
+
name: "tenant-id",
|
|
110
|
+
entry: validate,
|
|
111
|
+
errorClass: GuardTenantIdError,
|
|
112
|
+
profiles: PROFILES,
|
|
113
|
+
postures: COMPLIANCE_POSTURES,
|
|
114
|
+
extra: {
|
|
115
|
+
RESERVED: RESERVED,
|
|
116
|
+
NAME: "tenantId",
|
|
117
|
+
KIND: "tenant-id",
|
|
118
|
+
},
|
|
119
|
+
});
|