@vpdeva/blackwall-llm-shield-js 0.2.3 → 0.6.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/README.md +12 -2
- package/edge.d.ts +5 -0
- package/index.d.ts +54 -0
- package/package.json +6 -1
- package/src/edge.js +71 -0
- package/src/index.js +730 -16
- package/src/scorecard.js +48 -1
- package/src/semantic.js +10 -2
package/README.md
CHANGED
|
@@ -100,6 +100,10 @@ Enterprise deployments can also enrich emitted events with SSO/user context and
|
|
|
100
100
|
|
|
101
101
|
Use `createExpressMiddleware()`, `createLangChainCallbacks()`, or `createLlamaIndexCallback()` to drop Blackwall into existing app and orchestration flows faster.
|
|
102
102
|
|
|
103
|
+
### Example guide
|
|
104
|
+
|
|
105
|
+
Use the wiki-ready examples page at [`wiki/Running-Examples.md`](/Users/vishnu/Documents/blackwall-llm-shield/blackwall-llm-shield-js/wiki/Running-Examples.md) for copy-paste setup and run commands.
|
|
106
|
+
|
|
103
107
|
### Subpath modules
|
|
104
108
|
|
|
105
109
|
Use `require('@vpdeva/blackwall-llm-shield-js/integrations')` for callback wrappers and `require('@vpdeva/blackwall-llm-shield-js/semantic')` for optional local semantic scoring adapters.
|
|
@@ -150,7 +154,7 @@ Recommended presets:
|
|
|
150
154
|
|
|
151
155
|
### Global Governance Pack
|
|
152
156
|
|
|
153
|
-
The 0.
|
|
157
|
+
The 0.5.0 line also adds globally applicable enterprise controls that are useful across regulated industries, not just one country or sector:
|
|
154
158
|
|
|
155
159
|
- `DataClassificationGate` to classify traffic as `public`, `internal`, `confidential`, or `restricted`
|
|
156
160
|
- `ProviderRoutingPolicy` to keep sensitive classes on approved providers
|
|
@@ -158,6 +162,8 @@ The 0.2.2 line also adds globally applicable enterprise controls that are useful
|
|
|
158
162
|
- `buildComplianceEventBundle()` and `sanitizeAuditEvent()` for audit-safe event export
|
|
159
163
|
- `RetrievalTrustScorer` and `OutboundCommunicationGuard` for retrieval trust and outbound checks
|
|
160
164
|
- `detectOperationalDrift()` for release-over-release noise monitoring
|
|
165
|
+
- `ConversationThreatTracker`, `shield.use(plugin)`, `generateCoverageReport()`, and `unvault()` for multi-turn defense, ecosystem extensions, OWASP reporting, and reversible PII workflows
|
|
166
|
+
- `AdversarialMutationEngine`, `PromptProvenanceGraph`, and `src/edge` for corpus hardening, cross-hop tracing, and edge-safe deployments
|
|
161
167
|
|
|
162
168
|
### `AuditTrail`
|
|
163
169
|
|
|
@@ -168,9 +174,12 @@ Use it to record signed events, summarize security activity, and power dashboard
|
|
|
168
174
|
- `ValueAtRiskCircuitBreaker` for financial or high-value operational actions
|
|
169
175
|
- `ShadowConsensusAuditor` for second-model or secondary-review logic conflict checks
|
|
170
176
|
- `CrossModelConsensusWrapper` for automatic cross-model verification of high-impact actions
|
|
177
|
+
- `QuorumApprovalEngine` for committee-based approvals and trust-score-aware multi-agent decisions
|
|
171
178
|
- `DigitalTwinOrchestrator` for mock tool environments and sandbox simulations
|
|
179
|
+
- `SovereignRoutingEngine` for local-vs-global provider routing based on data classification
|
|
172
180
|
- `PolicyLearningLoop` plus `suggestPolicyOverride()` for narrow false-positive tuning suggestions after HITL approvals
|
|
173
|
-
- `
|
|
181
|
+
- `buildTransparencyReport()` for explainable operator and compliance artifacts
|
|
182
|
+
- `AgentIdentityRegistry.issueSignedPassport()` and `issuePassportToken()` for signed agent identity exchange with capability manifests and lineage
|
|
174
183
|
|
|
175
184
|
## Example Workflows
|
|
176
185
|
|
|
@@ -452,6 +461,7 @@ console.log(tools.inspectCall({ tool: 'lookupCustomer', args: { id: 'cus_123' }
|
|
|
452
461
|
|
|
453
462
|
- [`examples/nextjs-app-router/app/api/chat/route.js`](/Users/vishnu/Documents/blackwall-llm-shield/blackwall-llm-shield-js/examples/nextjs-app-router/app/api/chat/route.js) shows guarded request handling in a Next.js route
|
|
454
463
|
- [`examples/admin-dashboard/index.html`](/Users/vishnu/Documents/blackwall-llm-shield/blackwall-llm-shield-js/examples/admin-dashboard/index.html) shows a polished security command center demo
|
|
464
|
+
- [`wiki/Running-Examples.md`](/Users/vishnu/Documents/blackwall-llm-shield/blackwall-llm-shield-js/wiki/Running-Examples.md) shows how to run the available examples end to end
|
|
455
465
|
|
|
456
466
|
For Next.js, the most production-real patterns are App Router route handlers, server actions for trusted internal mutations, and streaming endpoints that apply output review to assembled or final chunks instead of raw intermediate tokens.
|
|
457
467
|
|
package/edge.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export function detectPromptInjectionEdge(input?: string): Record<string, unknown>;
|
|
2
|
+
export function maskTextEdge(input?: string): Record<string, unknown>;
|
|
3
|
+
export class EdgeBlackwallShield {
|
|
4
|
+
guardModelRequest(input?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
5
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -62,12 +62,15 @@ export interface ShieldOptions {
|
|
|
62
62
|
|
|
63
63
|
export class BlackwallShield {
|
|
64
64
|
constructor(options?: ShieldOptions);
|
|
65
|
+
use(plugin: Record<string, unknown>): this;
|
|
65
66
|
inspectText(text: unknown): Record<string, unknown>;
|
|
66
67
|
guardModelRequest(input?: { messages?: ShieldMessage[]; metadata?: Record<string, unknown>; allowSystemMessages?: boolean; comparePolicyPacks?: string[] }): Promise<GuardResult>;
|
|
67
68
|
reviewModelResponse(input?: { output: unknown; metadata?: Record<string, unknown>; outputFirewall?: OutputFirewall | null; firewallOptions?: Record<string, unknown> }): Promise<ReviewResult>;
|
|
68
69
|
protectModelCall(input: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
70
|
+
protectZeroTrustModelCall(input: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
69
71
|
protectJsonModelCall(input: Record<string, unknown>): Promise<JsonProtectionResult>;
|
|
70
72
|
protectWithAdapter(input: { adapter: ProviderAdapter; messages?: ShieldMessage[]; metadata?: Record<string, unknown>; allowSystemMessages?: boolean; comparePolicyPacks?: string[]; outputFirewall?: OutputFirewall | null; firewallOptions?: Record<string, unknown> }): Promise<Record<string, unknown>>;
|
|
73
|
+
generateCoverageReport(options?: Record<string, unknown>): Record<string, unknown>;
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
export class OutputFirewall {
|
|
@@ -81,6 +84,25 @@ export class ToolPermissionFirewall {
|
|
|
81
84
|
inspectCallAsync?(input: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
export class AgentIdentityRegistry {
|
|
88
|
+
constructor(options?: Record<string, unknown>);
|
|
89
|
+
register(agentId: string, profile?: Record<string, unknown>): Record<string, unknown>;
|
|
90
|
+
get(agentId: string): Record<string, unknown> | null;
|
|
91
|
+
issueEphemeralToken(agentId: string, options?: Record<string, unknown>): Record<string, unknown>;
|
|
92
|
+
verifyEphemeralToken(token: string): Record<string, unknown>;
|
|
93
|
+
recordSecurityEvent(agentId: string, event?: Record<string, unknown>): Record<string, unknown>;
|
|
94
|
+
getTrustScore(agentId: string): number | null;
|
|
95
|
+
issueSignedPassport(agentId: string, options?: Record<string, unknown>): Record<string, unknown>;
|
|
96
|
+
verifySignedPassport(passport?: Record<string, unknown>): Record<string, unknown>;
|
|
97
|
+
issuePassportToken(agentId: string, options?: Record<string, unknown>): string;
|
|
98
|
+
verifyPassportToken(token: string): Record<string, unknown>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export class AgenticCapabilityGater {
|
|
102
|
+
constructor(options?: Record<string, unknown>);
|
|
103
|
+
evaluate(agentId: string, capabilities?: Record<string, unknown>): Record<string, unknown>;
|
|
104
|
+
}
|
|
105
|
+
|
|
84
106
|
export class ValueAtRiskCircuitBreaker {
|
|
85
107
|
constructor(options?: Record<string, unknown>);
|
|
86
108
|
inspect(input?: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -97,12 +119,35 @@ export class CrossModelConsensusWrapper {
|
|
|
97
119
|
evaluate(input?: Record<string, unknown>): Promise<Record<string, unknown>> | Record<string, unknown>;
|
|
98
120
|
}
|
|
99
121
|
|
|
122
|
+
export class QuorumApprovalEngine {
|
|
123
|
+
constructor(options?: Record<string, unknown>);
|
|
124
|
+
evaluate(input?: Record<string, unknown>): Promise<Record<string, unknown>> | Record<string, unknown>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export class ConversationThreatTracker {
|
|
128
|
+
constructor(options?: Record<string, unknown>);
|
|
129
|
+
record(sessionId: string, injection?: Record<string, unknown>): Record<string, unknown> | null;
|
|
130
|
+
summarize(sessionId: string): Record<string, unknown>;
|
|
131
|
+
clear(sessionId: string): void;
|
|
132
|
+
}
|
|
133
|
+
|
|
100
134
|
export class DigitalTwinOrchestrator {
|
|
101
135
|
constructor(options?: Record<string, unknown>);
|
|
102
136
|
generate(): Record<string, unknown>;
|
|
103
137
|
static fromToolPermissionFirewall(firewall: unknown): DigitalTwinOrchestrator;
|
|
104
138
|
}
|
|
105
139
|
|
|
140
|
+
export class AdversarialMutationEngine {
|
|
141
|
+
mutate(prompt?: string): Array<Record<string, unknown>>;
|
|
142
|
+
hardenCorpus(input?: Record<string, unknown>): Record<string, unknown>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export class PromptProvenanceGraph {
|
|
146
|
+
constructor();
|
|
147
|
+
append(input?: Record<string, unknown>): Record<string, unknown>;
|
|
148
|
+
summarize(): Record<string, unknown>;
|
|
149
|
+
}
|
|
150
|
+
|
|
106
151
|
export class DataClassificationGate {
|
|
107
152
|
constructor(options?: Record<string, unknown>);
|
|
108
153
|
classify(input?: Record<string, unknown>): string;
|
|
@@ -114,6 +159,11 @@ export class ProviderRoutingPolicy {
|
|
|
114
159
|
choose(input?: Record<string, unknown>): Record<string, unknown>;
|
|
115
160
|
}
|
|
116
161
|
|
|
162
|
+
export class SovereignRoutingEngine {
|
|
163
|
+
constructor(options?: Record<string, unknown>);
|
|
164
|
+
route(input?: Record<string, unknown>): Record<string, unknown>;
|
|
165
|
+
}
|
|
166
|
+
|
|
117
167
|
export class ApprovalInboxModel {
|
|
118
168
|
constructor(options?: Record<string, unknown>);
|
|
119
169
|
createRequest(input?: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -139,6 +189,7 @@ export class PolicyLearningLoop {
|
|
|
139
189
|
constructor();
|
|
140
190
|
recordDecision(input?: Record<string, unknown>): Record<string, unknown> | null;
|
|
141
191
|
suggestOverrides(): Array<Record<string, unknown>>;
|
|
192
|
+
buildTransparencyReport(input?: Record<string, unknown>): Record<string, unknown>;
|
|
142
193
|
}
|
|
143
194
|
|
|
144
195
|
export class RetrievalSanitizer {
|
|
@@ -165,7 +216,10 @@ export function buildPowerBIRecord(event?: Record<string, unknown>): Record<stri
|
|
|
165
216
|
export function buildComplianceEventBundle(event?: Record<string, unknown>): Record<string, unknown>;
|
|
166
217
|
export function sanitizeAuditEvent(event?: Record<string, unknown>, options?: Record<string, unknown>): Record<string, unknown>;
|
|
167
218
|
export function detectOperationalDrift(previousSummary?: Record<string, unknown>, currentSummary?: Record<string, unknown>): Record<string, unknown>;
|
|
219
|
+
export function buildTransparencyReport(input?: Record<string, unknown>): Record<string, unknown>;
|
|
220
|
+
export function generateCoverageReport(options?: Record<string, unknown>): Record<string, unknown>;
|
|
168
221
|
export function suggestPolicyOverride(input?: Record<string, unknown>): Record<string, unknown> | null;
|
|
222
|
+
export function unvault(output?: unknown, vault?: Record<string, string>): string;
|
|
169
223
|
export class PowerBIExporter {
|
|
170
224
|
constructor(options?: Record<string, unknown>);
|
|
171
225
|
send(events?: Array<Record<string, unknown>> | Record<string, unknown>): Promise<Array<Record<string, unknown>>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vpdeva/blackwall-llm-shield-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Open-source JavaScript enterprise LLM protection toolkit for Node.js and Next.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Vish <hello@vish.au> (https://vish.au)",
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
"types": "./providers.d.ts",
|
|
21
21
|
"default": "./src/providers.js"
|
|
22
22
|
},
|
|
23
|
+
"./edge": {
|
|
24
|
+
"types": "./edge.d.ts",
|
|
25
|
+
"default": "./src/edge.js"
|
|
26
|
+
},
|
|
23
27
|
"./semantic": {
|
|
24
28
|
"types": "./semantic.d.ts",
|
|
25
29
|
"default": "./src/semantic.js"
|
|
@@ -39,6 +43,7 @@
|
|
|
39
43
|
},
|
|
40
44
|
"files": [
|
|
41
45
|
"src",
|
|
46
|
+
"edge.d.ts",
|
|
42
47
|
"index.d.ts",
|
|
43
48
|
"integrations.d.ts",
|
|
44
49
|
"providers.d.ts",
|
package/src/edge.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const EDGE_PROMPT_PATTERNS = [
|
|
2
|
+
{ id: 'ignore_instructions', score: 25, regex: /\bignore\b.{0,40}\b(instructions?|policy|guardrails?|safety)\b/i },
|
|
3
|
+
{ id: 'secret_exfiltration', score: 25, regex: /\b(reveal|dump|print|show)\b.{0,40}\b(secret|token|system prompt|hidden instructions?)\b/i },
|
|
4
|
+
{ id: 'tool_override', score: 20, regex: /\b(bypass|override|disable)\b.{0,40}\b(tool|policy|guardrail|safety)\b/i },
|
|
5
|
+
];
|
|
6
|
+
|
|
7
|
+
function edgeRiskLevel(score) {
|
|
8
|
+
if (score >= 70) return 'critical';
|
|
9
|
+
if (score >= 45) return 'high';
|
|
10
|
+
if (score >= 20) return 'medium';
|
|
11
|
+
return 'low';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function detectPromptInjectionEdge(input = '') {
|
|
15
|
+
const text = String(input || '');
|
|
16
|
+
const matches = EDGE_PROMPT_PATTERNS.filter((rule) => rule.regex.test(text)).map((rule) => ({
|
|
17
|
+
id: rule.id,
|
|
18
|
+
score: rule.score,
|
|
19
|
+
reason: `Edge rule matched ${rule.id}`,
|
|
20
|
+
}));
|
|
21
|
+
const score = Math.min(matches.reduce((sum, item) => sum + item.score, 0), 100);
|
|
22
|
+
return {
|
|
23
|
+
score,
|
|
24
|
+
level: edgeRiskLevel(score),
|
|
25
|
+
matches,
|
|
26
|
+
blockedByDefault: score >= 45,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function maskTextEdge(text = '') {
|
|
31
|
+
let masked = String(text || '');
|
|
32
|
+
const vault = {};
|
|
33
|
+
const patterns = [
|
|
34
|
+
['EMAIL', /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g],
|
|
35
|
+
['CREDIT_CARD', /\b(?:\d{4}[\s-]?){3}\d{4}\b/g],
|
|
36
|
+
['API_KEY', /\b(?:sk|rk|pk|api)[-_][A-Za-z0-9_-]{8,}\b/g],
|
|
37
|
+
['JWT', /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+\b/g],
|
|
38
|
+
['BEARER', /\bBearer\s+[A-Za-z0-9\-._~+/]+=*\b/gi],
|
|
39
|
+
['PHONE', /(\+?\d{1,3}[\s-]?)?(\(0\d\)|0\d|\(?\d{2,4}\)?)[\s-]?\d{3,4}[\s-]?\d{3,4}\b/g],
|
|
40
|
+
];
|
|
41
|
+
for (const [label, pattern] of patterns) {
|
|
42
|
+
masked = masked.replace(pattern, (match) => {
|
|
43
|
+
const token = `[${label}_${Object.keys(vault).length + 1}]`;
|
|
44
|
+
vault[token] = match;
|
|
45
|
+
return token;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return { masked, vault, hasSensitiveData: Object.keys(vault).length > 0 };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
class EdgeBlackwallShield {
|
|
52
|
+
async guardModelRequest({ messages = [], metadata = {} } = {}) {
|
|
53
|
+
const text = (Array.isArray(messages) ? messages : []).map((item) => String(item.content || '')).join('\n');
|
|
54
|
+
const masked = maskTextEdge(text);
|
|
55
|
+
const injection = detectPromptInjectionEdge(text);
|
|
56
|
+
return {
|
|
57
|
+
allowed: !injection.blockedByDefault,
|
|
58
|
+
blocked: injection.blockedByDefault,
|
|
59
|
+
reason: injection.blockedByDefault ? 'Prompt injection risk exceeded edge threshold' : null,
|
|
60
|
+
messages,
|
|
61
|
+
report: { metadata, promptInjection: injection, sensitiveData: masked },
|
|
62
|
+
vault: masked.vault,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
EdgeBlackwallShield,
|
|
69
|
+
detectPromptInjectionEdge,
|
|
70
|
+
maskTextEdge,
|
|
71
|
+
};
|