@cdot65/prisma-airs-cli 7.1.2 → 7.1.4
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/dist/cli/index.js +146 -57
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -6111,6 +6111,138 @@ async function fetchJobAttackRecords(client, jobId, options = {}) {
|
|
|
6111
6111
|
// src/redteam/judge/ingest.ts
|
|
6112
6112
|
import { createHash } from "crypto";
|
|
6113
6113
|
|
|
6114
|
+
// src/redteam/judge/envelope.ts
|
|
6115
|
+
function pythonLiteral(source) {
|
|
6116
|
+
let i = 0;
|
|
6117
|
+
let nodes = 0;
|
|
6118
|
+
const fail2 = () => {
|
|
6119
|
+
throw new Error("Unsupported exported literal");
|
|
6120
|
+
};
|
|
6121
|
+
const space = () => {
|
|
6122
|
+
while (/\s/.test(source[i] ?? "") && i < source.length) i++;
|
|
6123
|
+
};
|
|
6124
|
+
function string() {
|
|
6125
|
+
const quote = source[i++];
|
|
6126
|
+
let result2 = "";
|
|
6127
|
+
while (i < source.length) {
|
|
6128
|
+
const ch = source[i++];
|
|
6129
|
+
if (ch === quote) return result2;
|
|
6130
|
+
if (ch === "\n" || ch === "\r") fail2();
|
|
6131
|
+
if (ch !== "\\") {
|
|
6132
|
+
result2 += ch;
|
|
6133
|
+
continue;
|
|
6134
|
+
}
|
|
6135
|
+
const esc = source[i++];
|
|
6136
|
+
const simple = {
|
|
6137
|
+
a: "\x07",
|
|
6138
|
+
b: "\b",
|
|
6139
|
+
f: "\f",
|
|
6140
|
+
n: "\n",
|
|
6141
|
+
r: "\r",
|
|
6142
|
+
t: " ",
|
|
6143
|
+
v: "\v",
|
|
6144
|
+
"\\": "\\",
|
|
6145
|
+
"'": "'",
|
|
6146
|
+
'"': '"'
|
|
6147
|
+
};
|
|
6148
|
+
if (Object.hasOwn(simple, esc)) {
|
|
6149
|
+
result2 += simple[esc];
|
|
6150
|
+
continue;
|
|
6151
|
+
}
|
|
6152
|
+
const width = esc === "x" ? 2 : esc === "u" ? 4 : esc === "U" ? 8 : 0;
|
|
6153
|
+
if (width) {
|
|
6154
|
+
const digits = source.slice(i, i + width);
|
|
6155
|
+
if (digits.length !== width || !/^[\da-f]+$/i.test(digits)) fail2();
|
|
6156
|
+
const code = Number.parseInt(digits, 16);
|
|
6157
|
+
if (code > 1114111) fail2();
|
|
6158
|
+
result2 += String.fromCodePoint(code);
|
|
6159
|
+
i += width;
|
|
6160
|
+
continue;
|
|
6161
|
+
}
|
|
6162
|
+
if (/[0-7]/.test(esc ?? "")) {
|
|
6163
|
+
let digits = esc;
|
|
6164
|
+
while (digits.length < 3 && /[0-7]/.test(source[i] ?? "")) digits += source[i++];
|
|
6165
|
+
result2 += String.fromCodePoint(Number.parseInt(digits, 8));
|
|
6166
|
+
continue;
|
|
6167
|
+
}
|
|
6168
|
+
if (esc === void 0) fail2();
|
|
6169
|
+
result2 += `\\${esc}`;
|
|
6170
|
+
}
|
|
6171
|
+
return fail2();
|
|
6172
|
+
}
|
|
6173
|
+
function value(depth) {
|
|
6174
|
+
if (++nodes > 5e4 || depth > 64) fail2();
|
|
6175
|
+
space();
|
|
6176
|
+
const ch = source[i];
|
|
6177
|
+
if (ch === "'" || ch === '"') return string();
|
|
6178
|
+
if (ch === "{" || ch === "[") {
|
|
6179
|
+
i++;
|
|
6180
|
+
const object4 = /* @__PURE__ */ Object.create(null);
|
|
6181
|
+
const list = [];
|
|
6182
|
+
const end = ch === "{" ? "}" : "]";
|
|
6183
|
+
space();
|
|
6184
|
+
while (source[i] !== end) {
|
|
6185
|
+
if (ch === "{") {
|
|
6186
|
+
if (source[i] !== "'" && source[i] !== '"') fail2();
|
|
6187
|
+
const key = string();
|
|
6188
|
+
space();
|
|
6189
|
+
if (source[i++] !== ":" || Object.hasOwn(object4, key)) fail2();
|
|
6190
|
+
object4[key] = value(depth + 1);
|
|
6191
|
+
} else list.push(value(depth + 1));
|
|
6192
|
+
space();
|
|
6193
|
+
if (source[i] === end) break;
|
|
6194
|
+
if (source[i++] !== ",") fail2();
|
|
6195
|
+
space();
|
|
6196
|
+
}
|
|
6197
|
+
i++;
|
|
6198
|
+
return ch === "{" ? object4 : list;
|
|
6199
|
+
}
|
|
6200
|
+
for (const [token, literal] of [
|
|
6201
|
+
["True", true],
|
|
6202
|
+
["False", false],
|
|
6203
|
+
["None", null]
|
|
6204
|
+
]) {
|
|
6205
|
+
if (source.startsWith(token, i)) {
|
|
6206
|
+
i += token.length;
|
|
6207
|
+
return literal;
|
|
6208
|
+
}
|
|
6209
|
+
}
|
|
6210
|
+
const match = source.slice(i).match(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/);
|
|
6211
|
+
if (!match) return fail2();
|
|
6212
|
+
i += match[0].length;
|
|
6213
|
+
const number = Number(match[0]);
|
|
6214
|
+
if (!Number.isFinite(number)) fail2();
|
|
6215
|
+
return number;
|
|
6216
|
+
}
|
|
6217
|
+
const result = value(0);
|
|
6218
|
+
space();
|
|
6219
|
+
if (i !== source.length) fail2();
|
|
6220
|
+
return result;
|
|
6221
|
+
}
|
|
6222
|
+
function decodeContainer(raw) {
|
|
6223
|
+
if (raw.length > 1e6) return [raw, "plain"];
|
|
6224
|
+
try {
|
|
6225
|
+
return [JSON.parse(raw), "json"];
|
|
6226
|
+
} catch {
|
|
6227
|
+
}
|
|
6228
|
+
try {
|
|
6229
|
+
return [pythonLiteral(raw), "python_literal"];
|
|
6230
|
+
} catch {
|
|
6231
|
+
return [raw, "plain"];
|
|
6232
|
+
}
|
|
6233
|
+
}
|
|
6234
|
+
function messageText(value) {
|
|
6235
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
6236
|
+
const message = value;
|
|
6237
|
+
if (message.kind !== "message" || !Object.hasOwn(message, "parts")) return null;
|
|
6238
|
+
const parts = message.parts;
|
|
6239
|
+
if (!Array.isArray(parts) || parts.some(
|
|
6240
|
+
(part) => !part || typeof part !== "object" || part.kind !== "text" || typeof part.text !== "string"
|
|
6241
|
+
))
|
|
6242
|
+
return ["", "a2a_unsupported_parts"];
|
|
6243
|
+
return [parts.map((part) => part.text).join("\n"), "a2a_text"];
|
|
6244
|
+
}
|
|
6245
|
+
|
|
6114
6246
|
// src/redteam/judge/questions.ts
|
|
6115
6247
|
var SCHEMA_VERSION = 1;
|
|
6116
6248
|
var DEFAULT_TYPESAFE_MODEL = "jev-latest";
|
|
@@ -6157,63 +6289,10 @@ function isDict(value) {
|
|
|
6157
6289
|
function digest(text2) {
|
|
6158
6290
|
return createHash("sha256").update(text2, "utf8").digest("hex").slice(0, 16);
|
|
6159
6291
|
}
|
|
6160
|
-
function pythonJson(value) {
|
|
6161
|
-
if (Array.isArray(value)) return `[${value.map(pythonJson).join(", ")}]`;
|
|
6162
|
-
if (isDict(value))
|
|
6163
|
-
return `{${Object.entries(value).filter(([, v]) => v !== void 0).map(([k, v]) => `${JSON.stringify(k)}: ${pythonJson(v)}`).join(", ")}}`;
|
|
6164
|
-
return JSON.stringify(value ?? null);
|
|
6165
|
-
}
|
|
6166
|
-
function textFromContentList(content) {
|
|
6167
|
-
if (!Array.isArray(content)) return null;
|
|
6168
|
-
const parts = content.filter((c) => isDict(c) && typeof c.text === "string").map((c) => c.text);
|
|
6169
|
-
return parts.length ? parts.join("\n") : null;
|
|
6170
|
-
}
|
|
6171
6292
|
function extractResponseText(raw) {
|
|
6172
6293
|
if (raw === null || raw === void 0) return ["", "empty"];
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
if (typeof raw === "string") {
|
|
6176
|
-
const stripped = raw.trim();
|
|
6177
|
-
if (!stripped) return ["", "empty"];
|
|
6178
|
-
if (stripped[0] !== "{" && stripped[0] !== "[") return [raw, "plain"];
|
|
6179
|
-
try {
|
|
6180
|
-
value = JSON.parse(stripped);
|
|
6181
|
-
method = "json";
|
|
6182
|
-
} catch {
|
|
6183
|
-
return [raw, "plain"];
|
|
6184
|
-
}
|
|
6185
|
-
}
|
|
6186
|
-
if (isDict(value)) {
|
|
6187
|
-
const outputs = value.output;
|
|
6188
|
-
if (Array.isArray(outputs)) {
|
|
6189
|
-
const texts = outputs.map((item) => isDict(item) ? textFromContentList(item.content) : null).filter((text2) => Boolean(text2));
|
|
6190
|
-
if (texts.length) return [texts.join("\n"), "responses_api"];
|
|
6191
|
-
}
|
|
6192
|
-
const choices = value.choices;
|
|
6193
|
-
if (Array.isArray(choices) && choices.length && isDict(choices[0])) {
|
|
6194
|
-
const message = choices[0].message;
|
|
6195
|
-
if (isDict(message) && typeof message.content === "string")
|
|
6196
|
-
return [message.content, "chat_completions"];
|
|
6197
|
-
}
|
|
6198
|
-
for (const key of ["output_text", "response", "text", "content", "message", "answer"]) {
|
|
6199
|
-
if (typeof value[key] === "string") return [value[key], `json.${key}`];
|
|
6200
|
-
}
|
|
6201
|
-
const turns = value.messages || value.turns || value.conversation;
|
|
6202
|
-
if (Array.isArray(turns) && turns.length) {
|
|
6203
|
-
const last = turns[turns.length - 1];
|
|
6204
|
-
if (isDict(last)) {
|
|
6205
|
-
const text2 = typeof last.content === "string" ? last.content : textFromContentList(last.content);
|
|
6206
|
-
if (text2) return [text2, "multi_turn_last"];
|
|
6207
|
-
}
|
|
6208
|
-
}
|
|
6209
|
-
return [pythonJson(value), `${method}_unparsed`];
|
|
6210
|
-
}
|
|
6211
|
-
if (Array.isArray(value)) {
|
|
6212
|
-
const texts = value.filter((item) => typeof item === "string");
|
|
6213
|
-
if (texts.length) return [texts.join("\n"), "list_of_strings"];
|
|
6214
|
-
return [pythonJson(value), `${method}_unparsed`];
|
|
6215
|
-
}
|
|
6216
|
-
return [String(value), "coerced"];
|
|
6294
|
+
if (typeof raw !== "string") throw new Error("Expected output to be a string");
|
|
6295
|
+
return [raw, raw.trim() ? "plain" : "empty"];
|
|
6217
6296
|
}
|
|
6218
6297
|
function recordsFromDocument(document) {
|
|
6219
6298
|
if (Array.isArray(document)) return [document.filter(isDict), "array"];
|
|
@@ -6250,11 +6329,21 @@ function normalizeScan(document, options = {}) {
|
|
|
6250
6329
|
};
|
|
6251
6330
|
const limit = options.limit;
|
|
6252
6331
|
for (const [index, record] of records.entries()) {
|
|
6253
|
-
const
|
|
6254
|
-
if (typeof
|
|
6332
|
+
const rawPrompt = record.prompt;
|
|
6333
|
+
if (typeof rawPrompt !== "string" || !rawPrompt.trim()) {
|
|
6255
6334
|
notes.skipped_no_prompt += 1;
|
|
6256
6335
|
continue;
|
|
6257
6336
|
}
|
|
6337
|
+
let prompt = rawPrompt;
|
|
6338
|
+
const promptMessage = prompt.trimStart().startsWith("{") ? messageText(decodeContainer(prompt.trim())[0]) : null;
|
|
6339
|
+
if (promptMessage !== null) {
|
|
6340
|
+
prompt = promptMessage[0];
|
|
6341
|
+
if (!prompt.trim()) {
|
|
6342
|
+
notes.skipped_no_prompt += 1;
|
|
6343
|
+
continue;
|
|
6344
|
+
}
|
|
6345
|
+
notes.normalized_prompt_envelopes = (notes.normalized_prompt_envelopes ?? 0) + 1;
|
|
6346
|
+
}
|
|
6258
6347
|
const attackId = label(record.uuid) || label(record.attack_id) || label(record.id) || `index-${index}`;
|
|
6259
6348
|
if (attackId === `index-${index}`) notes.fallback_row_ids = (notes.fallback_row_ids ?? 0) + 1;
|
|
6260
6349
|
if (!label(record.goal)) notes.objective_proxies = (notes.objective_proxies ?? 0) + 1;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdot65/prisma-airs-cli",
|
|
3
3
|
"packageManager": "pnpm@10.6.5",
|
|
4
|
-
"version": "7.1.
|
|
4
|
+
"version": "7.1.4",
|
|
5
5
|
"description": "CLI and library for Palo Alto Prisma AIRS — guardrail refinement, AI red teaming, model security scanning, profile audits",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|