feat(llm-security-copilot): port llm-security v5.1.0 to GitHub Copilot CLI
Full port of llm-security plugin for internal use on Windows with GitHub Copilot CLI. Protocol translation layer (copilot-hook-runner.mjs) normalizes Copilot camelCase I/O to Claude Code snake_case format — all original hook scripts run unmodified. - 8 hooks with protocol translation (stdin/stdout/exit code) - 18 SKILL.md skills (Agent Skills Open Standard) - 6 .agent.md agent definitions - 20 scanners + 14 scanner lib modules (unchanged) - 14 knowledge files (unchanged) - 39 test files including copilot-port-verify.mjs (17 tests) - Windows-ready: node:path, os.tmpdir(), process.execPath, no bash Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
901bf0ae12
commit
f418a8fe08
169 changed files with 37631 additions and 0 deletions
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env node
|
||||
// copilot-adapter.mjs — Normalizes GitHub Copilot hook I/O to internal format.
|
||||
//
|
||||
// Copilot CLI hooks receive JSON on stdin with camelCase field names
|
||||
// (toolName, toolArgs, toolResult) and signal blocking via exit code 2
|
||||
// or stdout JSON with permissionDecision: "deny".
|
||||
//
|
||||
// This adapter provides a consistent interface so hook logic stays
|
||||
// platform-agnostic. If Copilot changes field names, only this file
|
||||
// needs updating.
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
/**
|
||||
* Parse hook input from stdin. Returns normalized object or null on failure.
|
||||
* Supports both Copilot (camelCase) and Claude Code (snake_case) field names.
|
||||
*/
|
||||
export function parseInput() {
|
||||
try {
|
||||
const raw = readFileSync(0, 'utf-8');
|
||||
const input = JSON.parse(raw);
|
||||
return {
|
||||
toolName: input.toolName ?? input.tool_name ?? '',
|
||||
toolInput: input.toolArgs ?? input.tool_input ?? {},
|
||||
toolOutput: input.toolResult ?? input.tool_output ?? '',
|
||||
message: input.message ?? {},
|
||||
sessionId: input.sessionId ?? input.session_id ?? '',
|
||||
raw: input,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Block the tool call with a reason message.
|
||||
*/
|
||||
export function block(reason) {
|
||||
process.stderr.write(reason + '\n');
|
||||
process.stdout.write(JSON.stringify({
|
||||
permissionDecision: 'deny',
|
||||
reason,
|
||||
}));
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the tool call, optionally with an advisory message.
|
||||
*/
|
||||
export function allow(message) {
|
||||
if (message) {
|
||||
process.stdout.write(JSON.stringify({
|
||||
permissionDecision: 'allow',
|
||||
message,
|
||||
}));
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a warning to stderr without blocking. Exit 0.
|
||||
*/
|
||||
export function warn(message) {
|
||||
process.stderr.write(message + '\n');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fail-open: exit 0 silently. Used when input can't be parsed.
|
||||
*/
|
||||
export function failOpen() {
|
||||
process.exit(0);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue