d48cda4081
CI / Test (ubuntu-latest, Node 18.x, bun) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, npm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, pnpm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, yarn) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 20.x, bun) (push) Failing after 17m13s
CI / Test (ubuntu-latest, Node 20.x, npm) (push) Failing after 18m42s
CI / Test (ubuntu-latest, Node 20.x, pnpm) (push) Failing after 15m0s
CI / Test (ubuntu-latest, Node 20.x, yarn) (push) Failing after 49m44s
CI / Test (ubuntu-latest, Node 22.x, bun) (push) Failing after 51m55s
CI / Test (ubuntu-latest, Node 22.x, pnpm) (push) Failing after 21m57s
CI / Test (ubuntu-latest, Node 22.x, npm) (push) Failing after 37m39s
CI / Test (ubuntu-latest, Node 22.x, yarn) (push) Failing after 34m7s
CI / Validate Components (push) Failing after 37m15s
CI / Python Tests (push) Failing after 10m1s
CI / Security Scan (push) Failing after 10m1s
CI / Lint (push) Failing after 17m12s
CI / Coverage (push) Failing after 20m19s
CI / Test (macos-latest, Node 18.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, yarn) (push) Has been cancelled
81 lines
2.1 KiB
JavaScript
81 lines
2.1 KiB
JavaScript
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
|
|
const MAX_STDIN = 1024 * 1024;
|
|
let raw = '';
|
|
|
|
const MODE_CONFIG = {
|
|
audit: {
|
|
fileName: 'bash-commands.log',
|
|
format: command => `[${new Date().toISOString()}] ${command}`,
|
|
},
|
|
cost: {
|
|
fileName: 'cost-tracker.log',
|
|
format: command => `[${new Date().toISOString()}] tool=Bash command=${command}`,
|
|
},
|
|
};
|
|
|
|
function sanitizeCommand(command) {
|
|
return String(command || '')
|
|
.replace(/\n/g, ' ')
|
|
.replace(/--token[= ][^ ]*/g, '--token=<REDACTED>')
|
|
.replace(/Authorization:[: ]*[^ ]*[: ]*[^ ]*/gi, 'Authorization:<REDACTED>')
|
|
.replace(/\bAKIA[A-Z0-9]{16}\b/g, '<REDACTED>')
|
|
.replace(/\bASIA[A-Z0-9]{16}\b/g, '<REDACTED>')
|
|
.replace(/password[= ][^ ]*/gi, 'password=<REDACTED>')
|
|
.replace(/\bghp_[A-Za-z0-9_]+\b/g, '<REDACTED>')
|
|
.replace(/\bgho_[A-Za-z0-9_]+\b/g, '<REDACTED>')
|
|
.replace(/\bghs_[A-Za-z0-9_]+\b/g, '<REDACTED>')
|
|
.replace(/\bgithub_pat_[A-Za-z0-9_]+\b/g, '<REDACTED>');
|
|
}
|
|
|
|
function appendLine(filePath, line) {
|
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
fs.appendFileSync(filePath, `${line}\n`, 'utf8');
|
|
}
|
|
|
|
function run(rawInput, mode = 'audit') {
|
|
const config = MODE_CONFIG[mode];
|
|
|
|
try {
|
|
if (config) {
|
|
const input = String(rawInput || '').trim() ? JSON.parse(String(rawInput)) : {};
|
|
const command = sanitizeCommand(input.tool_input?.command || '?');
|
|
appendLine(path.join(os.homedir(), '.claude', config.fileName), config.format(command));
|
|
}
|
|
} catch {
|
|
// Logging must never block the calling hook.
|
|
}
|
|
|
|
return typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput);
|
|
}
|
|
|
|
function main() {
|
|
const mode = process.argv[2];
|
|
|
|
process.stdin.setEncoding('utf8');
|
|
process.stdin.on('data', chunk => {
|
|
if (raw.length < MAX_STDIN) {
|
|
const remaining = MAX_STDIN - raw.length;
|
|
raw += chunk.substring(0, remaining);
|
|
}
|
|
});
|
|
|
|
process.stdin.on('end', () => {
|
|
process.stdout.write(run(raw, mode));
|
|
});
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main();
|
|
}
|
|
|
|
module.exports = {
|
|
run,
|
|
sanitizeCommand,
|
|
};
|