Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 34 additions & 11 deletions plugins/panw-prisma-airs/intercept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import { getText, post } from '../utils';
const AIRS_URL =
'https://service.api.aisecurity.paloaltonetworks.com/v1/scan/sync/request';

const fetchAIRS = async (payload: any, apiKey: string, timeout?: number) => {
const fetchAIRS = async (payload: any, apiKey: string) => {
const opts = {
headers: { 'x-pan-token': apiKey },
};
return post(AIRS_URL, payload, opts, timeout);
return post(AIRS_URL, payload, opts);
};

export const handler: PluginHandler = async (
Expand All @@ -26,31 +26,54 @@ export const handler: PluginHandler = async (
process.env.AIRS_API_KEY ||
'';

// Return verdict=true with error for missing credentials to allow traffic flow
if (!apiKey || apiKey.trim() === '') {
return {
verdict: true,
error:
'AIRS_API_KEY is required but not configured. Please add your API key in the Portkey dashboard.',
data: null,
};
}

let verdict = true;
let data: any = null;
let error: any = null;

try {
const text = getText(ctx, hook); // prompt or response

const payload = {
tr_id:
typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
? crypto.randomUUID()
: Math.random().toString(36).substring(2) + Date.now().toString(36),
ai_profile: {
profile_name: params.profile_name ?? 'dev-block-all-profile',
},
// Extract Portkey's trace ID from request headers to use as AIRS tr_id (AI Session ID)
const traceId =
ctx?.request?.headers?.['x-portkey-trace-id'] ||
(typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
? crypto.randomUUID()
: Math.random().toString(36).substring(2) + Date.now().toString(36));

const payload: any = {
tr_id: traceId, // Use Portkey's trace ID as AIRS AI Session ID
metadata: {
ai_model: params.ai_model ?? 'unknown-model',
app_user: params.app_user ?? 'portkey-gateway',
app_name: params.app_name ? `Portkey-${params.app_name}` : 'Portkey',
},
contents: [
{ [hook === 'beforeRequestHook' ? 'prompt' : 'response']: text },
],
};

const res: any = await fetchAIRS(payload, apiKey, params.timeout);
// Only include ai_profile if profile_name or profile_id is provided
if (params.profile_name || params.profile_id) {
payload.ai_profile = {};
if (params.profile_name) {
payload.ai_profile.profile_name = params.profile_name;
}
if (params.profile_id) {
payload.ai_profile.profile_id = params.profile_id;
}
}

const res: any = await fetchAIRS(payload, apiKey);

if (!res || typeof res.action !== 'string') {
throw new Error('Malformed AIRS response');
Expand Down
67 changes: 61 additions & 6 deletions plugins/panw-prisma-airs/manifest.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"id": "panwPrismaAirs",
"name": "PANW Prisma AIRS Guardrail",
"description": "Blocks prompt/response when Palo Alto Networks Prisma AI Runtime Security returns action=block.",
"description": "Palo Alto Networks Prisma AI Runtime Security provides real-time scanning for prompt injections, malicious content, PII leakage, and policy violations. Blocks requests or responses when action=block is returned.",
"credentials": {
"type": "object",
"properties": {
"AIRS_API_KEY": {
"type": "string",
"label": "AIRS API Key",
"description": "The API key for Palo Alto Networks Prisma AI Runtime Security",
"description": "API key for Palo Alto Networks Prisma AI Runtime Security. Find your API key in Strata Cloud Manager.",
"encrypted": true
}
},
Expand All @@ -20,14 +20,69 @@
"name": "PANW Prisma AIRS Guardrail",
"type": "guardrail",
"supportedHooks": ["beforeRequestHook", "afterRequestHook"],
"description": [
{
"type": "subHeading",
"text": "Scan prompts and responses for security threats using Prisma AIRS profiles linked to your API key."
}
],
"parameters": {
"type": "object",
"properties": {
"profile_name": { "type": "string" },
"ai_model": { "type": "string" },
"app_user": { "type": "string" }
"profile_name": {
"type": "string",
"label": "Profile Name",
"description": [
{
"type": "subHeading",
"text": "AI security profile name from Prisma AIRS. Leave empty to use the profile linked to your API key in Strata Cloud Manager."
}
]
},
"profile_id": {
"type": "string",
"label": "Profile ID",
"description": [
{
"type": "subHeading",
"text": "AI security profile ID. Can be used instead of or in addition to profile_name."
}
]
},
"ai_model": {
"type": "string",
"label": "AI Model",
"description": [
{
"type": "subHeading",
"text": "The AI model being used (e.g., gpt-4, claude-3-5-sonnet). Used for tracking and reporting."
}
],
"default": "unknown-model"
},
"app_user": {
"type": "string",
"label": "Application User",
"description": [
{
"type": "subHeading",
"text": "User identifier for tracking purposes. Useful for audit logs and user-level analytics."
}
],
"default": "portkey-gateway"
},
"app_name": {
"type": "string",
"label": "Application Name",
"description": [
{
"type": "subHeading",
"text": "Custom application name for tracking. Will be prefixed with 'Portkey-' (e.g., 'Portkey-chatbot')."
}
]
}
},
"required": ["profile_name"]
"required": []
}
}
]
Expand Down
Loading