skill-checker 0.1.13 → 0.1.15
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 +4 -4
- package/dist/cli.js +189 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.js +189 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -977,6 +977,40 @@ var DELIMITER_PATTERNS = [
|
|
|
977
977
|
/\[INST\]/i,
|
|
978
978
|
/\[\/INST\]/i
|
|
979
979
|
];
|
|
980
|
+
var DANGEROUS_ROLE_PATTERN = "(?:(?:an?\\s+)?(?:hacker|attacker|cracker|root|admin(?:istrator)?|superuser|unrestricted|jailbroken|evil|malicious|unfiltered|uncensored)\\b|DAN\\b|(?:a\\s+)?different\\b)";
|
|
981
|
+
var IDENTITY_HIJACKING_PATTERNS = [
|
|
982
|
+
new RegExp(`\\byou\\s+are\\s+now\\s+${DANGEROUS_ROLE_PATTERN}`, "i"),
|
|
983
|
+
new RegExp(`\\bact\\s+as\\s+${DANGEROUS_ROLE_PATTERN}`, "i"),
|
|
984
|
+
new RegExp(`\\bpretend\\s+(?:you\\s+are|to\\s+be)\\s+${DANGEROUS_ROLE_PATTERN}`, "i"),
|
|
985
|
+
new RegExp(`\\broleplay\\s+(?:as|like)\\s+${DANGEROUS_ROLE_PATTERN}`, "i"),
|
|
986
|
+
new RegExp(`\\bassume\\s+the\\s+role\\s+of\\s+${DANGEROUS_ROLE_PATTERN}`, "i"),
|
|
987
|
+
/\byou\s+are\s+no\s+longer\s+claude\b/i,
|
|
988
|
+
/\bfrom\s+now\s+on,?\s+you\s+are\b/i
|
|
989
|
+
];
|
|
990
|
+
var DECEPTION_SECRECY_PATTERNS = [
|
|
991
|
+
/\bdo\s+not\s+tell\s+(the\s+)?(user|human|person|operator)\b/i,
|
|
992
|
+
/\bdo\s+not\s+(mention|reveal|disclose|expose)\s+(this|that|the|any|these)\b/i,
|
|
993
|
+
/\bnever\s+(tell|mention|reveal|disclose)\s+(the\s+)?(user|human|person|operator)\b/i,
|
|
994
|
+
/\bkeep\s+this\s+(secret|hidden|private|confidential)\b(?!\s+key)/i,
|
|
995
|
+
/\bhide\s+this\s+(from|action|operation|instruction)\b/i,
|
|
996
|
+
/\bwithout\s+(the\s+)?(user|human)('?s)?\s+(knowledge|knowing|awareness|consent)\b/i,
|
|
997
|
+
/\bsilently\s+(execute|run|perform|install|download|delete|modify|send)\b/i
|
|
998
|
+
];
|
|
999
|
+
var CONFIG_TAMPERING_PATTERNS = [
|
|
1000
|
+
/\b(modify|change|update|edit|alter|rewrite)\s+(your|my)\s+(memory|config|configuration|settings?|instructions?|behavior|personality)\b/i,
|
|
1001
|
+
/\bwrite\s+to\s+(CLAUDE\.md|\.claude|settings\.json|memory\.md)\b/i,
|
|
1002
|
+
/\b(append|prepend|add|insert)\s+.{0,30}\bto\s+(CLAUDE\.md|\.claude|memory\.md)\b/i,
|
|
1003
|
+
/\boverwrite\s+(your|the)\s+(system|core)\s+(prompt|instructions?|config)\b/i,
|
|
1004
|
+
/\bpersist\s+(this|these|the)\s+(instruction|change|modification|setting)s?\b/i
|
|
1005
|
+
];
|
|
1006
|
+
var VERIFICATION_BYPASS_PATTERNS = [
|
|
1007
|
+
/\btrust\s+(this|the|these|that|my)\s+(result|output|response|answer|value|data|input)s?\b/i,
|
|
1008
|
+
/\bno\s+need\s+to\s+(check|verify|validate|review|confirm|inspect)\b/i,
|
|
1009
|
+
/\bdo\s+not\s+(verify|validate|check|review|confirm|inspect)\s+(the|this|that|any|these)\b/i,
|
|
1010
|
+
/\b(assume|consider)\s+(it|this|that)\s+(is|to\s+be)\s+(correct|safe|valid|trusted|clean|secure|legitimate)\b/i,
|
|
1011
|
+
/\baccept\s+(this|the|these|that)\s+without\s+(checking|verifying|validating|questioning)\b/i,
|
|
1012
|
+
/\bblindly\s+(trust|accept|execute|run|follow|apply)\b/i
|
|
1013
|
+
];
|
|
980
1014
|
var injectionChecks = {
|
|
981
1015
|
name: "Injection Detection",
|
|
982
1016
|
category: "INJ",
|
|
@@ -1073,6 +1107,65 @@ var injectionChecks = {
|
|
|
1073
1107
|
break;
|
|
1074
1108
|
}
|
|
1075
1109
|
}
|
|
1110
|
+
const trimmedLine = line.trim();
|
|
1111
|
+
const nextLine = i + 1 < skill.bodyLines.length ? skill.bodyLines[i + 1] : "";
|
|
1112
|
+
const crossLine = trimmedLine && nextLine ? `${line} ${nextLine}` : line;
|
|
1113
|
+
for (const pattern of IDENTITY_HIJACKING_PATTERNS) {
|
|
1114
|
+
if (pattern.test(crossLine)) {
|
|
1115
|
+
results.push({
|
|
1116
|
+
id: "INJ-010",
|
|
1117
|
+
category: "INJ",
|
|
1118
|
+
severity: "CRITICAL",
|
|
1119
|
+
title: "Social engineering: identity hijacking",
|
|
1120
|
+
message: `Line ${lineNum}: Attempts to hijack the model's identity.`,
|
|
1121
|
+
line: lineNum,
|
|
1122
|
+
snippet: line.trim().slice(0, 120)
|
|
1123
|
+
});
|
|
1124
|
+
break;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
for (const pattern of DECEPTION_SECRECY_PATTERNS) {
|
|
1128
|
+
if (pattern.test(crossLine)) {
|
|
1129
|
+
results.push({
|
|
1130
|
+
id: "INJ-010",
|
|
1131
|
+
category: "INJ",
|
|
1132
|
+
severity: "CRITICAL",
|
|
1133
|
+
title: "Social engineering: deception/secrecy",
|
|
1134
|
+
message: `Line ${lineNum}: Instructs the model to hide actions from the user.`,
|
|
1135
|
+
line: lineNum,
|
|
1136
|
+
snippet: line.trim().slice(0, 120)
|
|
1137
|
+
});
|
|
1138
|
+
break;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
for (const pattern of CONFIG_TAMPERING_PATTERNS) {
|
|
1142
|
+
if (pattern.test(crossLine)) {
|
|
1143
|
+
results.push({
|
|
1144
|
+
id: "INJ-010",
|
|
1145
|
+
category: "INJ",
|
|
1146
|
+
severity: "HIGH",
|
|
1147
|
+
title: "Social engineering: configuration tampering",
|
|
1148
|
+
message: `Line ${lineNum}: Attempts to tamper with model configuration or memory.`,
|
|
1149
|
+
line: lineNum,
|
|
1150
|
+
snippet: line.trim().slice(0, 120)
|
|
1151
|
+
});
|
|
1152
|
+
break;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
for (const pattern of VERIFICATION_BYPASS_PATTERNS) {
|
|
1156
|
+
if (pattern.test(crossLine)) {
|
|
1157
|
+
results.push({
|
|
1158
|
+
id: "INJ-010",
|
|
1159
|
+
category: "INJ",
|
|
1160
|
+
severity: "HIGH",
|
|
1161
|
+
title: "Social engineering: verification bypass",
|
|
1162
|
+
message: `Line ${lineNum}: Attempts to bypass verification or validation.`,
|
|
1163
|
+
line: lineNum,
|
|
1164
|
+
snippet: line.trim().slice(0, 120)
|
|
1165
|
+
});
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1076
1169
|
}
|
|
1077
1170
|
const commentRegex = /<!--([\s\S]*?)-->/g;
|
|
1078
1171
|
let commentMatch;
|
|
@@ -1124,7 +1217,10 @@ function hasInstructionLikeContent(text) {
|
|
|
1124
1217
|
/\brm\s+-rf\b/i,
|
|
1125
1218
|
/\bcurl\b.*\bsh\b/i,
|
|
1126
1219
|
/\beval\b/i,
|
|
1127
|
-
/\bexec\b/i
|
|
1220
|
+
/\bexec\b/i,
|
|
1221
|
+
/\bdo\s+not\s+tell\s+(the\s+)?(user|human)/i,
|
|
1222
|
+
/\bpretend\s+(you\s+are|to\s+be)/i,
|
|
1223
|
+
/\bsilently\s+(execute|run|install)/i
|
|
1128
1224
|
];
|
|
1129
1225
|
return instructionPatterns.some((p) => p.test(text));
|
|
1130
1226
|
}
|
|
@@ -1280,6 +1376,79 @@ var PERMISSION_PATTERNS = [
|
|
|
1280
1376
|
/\bsetuid\b/,
|
|
1281
1377
|
/\bsetgid\b/
|
|
1282
1378
|
];
|
|
1379
|
+
var PERSISTENCE_GROUPS = [
|
|
1380
|
+
{
|
|
1381
|
+
title: "Scheduled task persistence (cron)",
|
|
1382
|
+
patterns: [
|
|
1383
|
+
/\bcrontab\b/,
|
|
1384
|
+
/\/etc\/cron\.(?:d|hourly|daily|weekly|monthly)\b/,
|
|
1385
|
+
/\/var\/spool\/cron\b/
|
|
1386
|
+
]
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
title: "System service persistence (launchd)",
|
|
1390
|
+
patterns: [
|
|
1391
|
+
/\bLaunchAgents?\b/,
|
|
1392
|
+
/\bLaunchDaemons?\b/,
|
|
1393
|
+
/\blaunchctl\s+(?:load|bootstrap|submit)\b/i
|
|
1394
|
+
]
|
|
1395
|
+
},
|
|
1396
|
+
{
|
|
1397
|
+
title: "System service persistence (systemd/init.d)",
|
|
1398
|
+
patterns: [
|
|
1399
|
+
/\bsystemctl\s+(?:enable|daemon-reload)\b/i,
|
|
1400
|
+
/\/etc\/systemd\/system\b/,
|
|
1401
|
+
/\.config\/systemd\/user\b/,
|
|
1402
|
+
/\/etc\/init\.d\b/,
|
|
1403
|
+
/\/etc\/rc\.local\b/,
|
|
1404
|
+
/\bupdate-rc\.d\b/,
|
|
1405
|
+
/\bchkconfig\b.*\b(?:--add|on)\b/
|
|
1406
|
+
]
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
title: "Shell profile modification",
|
|
1410
|
+
patterns: [
|
|
1411
|
+
/\.(?:bashrc|bash_profile|bash_login|profile|zshrc|zshenv|zprofile|zlogin)\b/,
|
|
1412
|
+
/\/etc\/(?:profile(?:\.d)?|bash\.bashrc|zshrc|zshenv)\b/,
|
|
1413
|
+
/\.config\/fish\/config\.fish\b/
|
|
1414
|
+
]
|
|
1415
|
+
},
|
|
1416
|
+
{
|
|
1417
|
+
title: "Autostart / login item persistence",
|
|
1418
|
+
patterns: [
|
|
1419
|
+
/\.config\/autostart\b/,
|
|
1420
|
+
/\/etc\/xdg\/autostart\b/,
|
|
1421
|
+
/\bosascript\b[^\n]*\blogin\s+item\b/i
|
|
1422
|
+
]
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
title: "SSH key persistence",
|
|
1426
|
+
patterns: [
|
|
1427
|
+
/\.ssh\/authorized_keys2?\b/
|
|
1428
|
+
]
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
title: "Library injection persistence",
|
|
1432
|
+
patterns: [
|
|
1433
|
+
/\/etc\/ld\.so\.preload\b/,
|
|
1434
|
+
/\bLD_PRELOAD\b/,
|
|
1435
|
+
/\bDYLD_INSERT_LIBRARIES\b/
|
|
1436
|
+
]
|
|
1437
|
+
},
|
|
1438
|
+
{
|
|
1439
|
+
title: "Git hooks manipulation",
|
|
1440
|
+
patterns: [
|
|
1441
|
+
/\.git\/hooks\/(?:pre-commit|post-commit|pre-push|post-checkout|post-merge|pre-rebase)\b/,
|
|
1442
|
+
/\bgit\s+config\b[^\n]*\bcore\.hooksPath\b/
|
|
1443
|
+
]
|
|
1444
|
+
},
|
|
1445
|
+
{
|
|
1446
|
+
title: "macOS periodic script persistence",
|
|
1447
|
+
patterns: [
|
|
1448
|
+
/\/etc\/periodic\/(?:daily|weekly|monthly)\b/
|
|
1449
|
+
]
|
|
1450
|
+
}
|
|
1451
|
+
];
|
|
1283
1452
|
var codeSafetyChecks = {
|
|
1284
1453
|
name: "Code Safety",
|
|
1285
1454
|
category: "CODE",
|
|
@@ -1388,16 +1557,27 @@ var codeSafetyChecks = {
|
|
|
1388
1557
|
lineNum,
|
|
1389
1558
|
source
|
|
1390
1559
|
});
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1560
|
+
const isDoc = isInDocumentationContext(lines, i);
|
|
1561
|
+
if (!isDoc) {
|
|
1562
|
+
checkPatterns(results, line, PERMISSION_PATTERNS, {
|
|
1563
|
+
id: "CODE-012",
|
|
1564
|
+
severity: "HIGH",
|
|
1565
|
+
title: "Permission escalation",
|
|
1566
|
+
loc,
|
|
1567
|
+
lineNum,
|
|
1568
|
+
source
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
if (!isDoc) {
|
|
1572
|
+
for (const group of PERSISTENCE_GROUPS) {
|
|
1573
|
+
checkPatterns(results, line, group.patterns, {
|
|
1574
|
+
id: "CODE-016",
|
|
1396
1575
|
severity: "HIGH",
|
|
1397
|
-
title:
|
|
1576
|
+
title: group.title,
|
|
1398
1577
|
loc,
|
|
1399
1578
|
lineNum,
|
|
1400
|
-
source
|
|
1579
|
+
source,
|
|
1580
|
+
codeBlockCtx: cbCtx
|
|
1401
1581
|
});
|
|
1402
1582
|
}
|
|
1403
1583
|
}
|
|
@@ -2526,7 +2706,7 @@ function deduplicateResults(results) {
|
|
|
2526
2706
|
};
|
|
2527
2707
|
for (const r of results) {
|
|
2528
2708
|
const sourceKey = r.source ?? `_no_source_:${r.category}:${r.line ?? ""}`;
|
|
2529
|
-
const key = `${r.id}::${sourceKey}`;
|
|
2709
|
+
const key = `${r.id}::${r.title}::${sourceKey}`;
|
|
2530
2710
|
const group = groups.get(key);
|
|
2531
2711
|
if (group) {
|
|
2532
2712
|
group.push(r);
|