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
19
plugins/llm-security-copilot/hooks/scripts/lib/cache-dir.mjs
Normal file
19
plugins/llm-security-copilot/hooks/scripts/lib/cache-dir.mjs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// cache-dir.mjs — Cross-platform cache directory resolution.
|
||||
// Windows: %LOCALAPPDATA%/llm-security or %APPDATA%/llm-security
|
||||
// macOS/Linux: ~/.cache/llm-security (XDG_CACHE_HOME fallback)
|
||||
|
||||
import { homedir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
||||
export function getCacheDir() {
|
||||
if (process.platform === 'win32') {
|
||||
const localAppData = process.env.LOCALAPPDATA;
|
||||
if (localAppData) return join(localAppData, 'llm-security');
|
||||
const appData = process.env.APPDATA;
|
||||
if (appData) return join(appData, 'llm-security');
|
||||
return join(homedir(), '.cache', 'llm-security');
|
||||
}
|
||||
const xdg = process.env.XDG_CACHE_HOME;
|
||||
if (xdg) return join(xdg, 'llm-security');
|
||||
return join(homedir(), '.cache', 'llm-security');
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// windows-paths.mjs — Additional path patterns for Windows environments.
|
||||
// Loaded by copilot-hook-runner.mjs when running on Windows.
|
||||
//
|
||||
// The original pre-write-pathguard.mjs has Unix-specific SYSTEM_PATTERNS
|
||||
// that won't match on Windows. This module exports additional patterns
|
||||
// for Windows system directories.
|
||||
|
||||
export const WINDOWS_SYSTEM_PATTERNS = [
|
||||
/^[A-Z]:\\Windows\\/i,
|
||||
/^[A-Z]:\\Program Files/i,
|
||||
/^[A-Z]:\\Program Files \(x86\)/i,
|
||||
/^[A-Z]:\\ProgramData\\/i,
|
||||
/^[A-Z]:\\System Volume Information/i,
|
||||
];
|
||||
|
||||
export const WINDOWS_CREDENTIAL_PATHS = [
|
||||
/[\\/]\.docker[\\/]config\.json$/i,
|
||||
/[\\/]\.kube[\\/]config$/i,
|
||||
/[\\/]\.azure[\\/]/i,
|
||||
/[\\/]\.aws[\\/]/i,
|
||||
/[\\/]\.ssh[\\/]/i,
|
||||
/[\\/]\.gnupg[\\/]/i,
|
||||
/[\\/]AppData[\\/]Local[\\/]Google[\\/]Chrome[\\/]User Data/i,
|
||||
/[\\/]AppData[\\/]Local[\\/]Microsoft[\\/]Edge[\\/]User Data/i,
|
||||
];
|
||||
Loading…
Add table
Add a link
Reference in a new issue