import { describe, expect, it } from 'vitest';
import { matchToolCalling } from '../responsePatternUtility';
/**
* Security tests for agent response parsing
* These tests verify that malicious AI responses cannot execute arbitrary code
*/
describe('Agent Response Parsing Security', () => {
describe('Dangerous pattern detection', () => {
it('should reject parameters with require() calls', () => {
const responseText = `
{
test: require('child_process').execSync('whoami')
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
// The dangerous code should not be executed, fallback to string
expect(result.parameters).toEqual({
input: expect.stringContaining('require'),
});
});
it('should reject parameters with process.binding', () => {
const responseText = `
{
exploit: process.binding('spawn_sync').spawn({file:'/usr/bin/whoami'})
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({
input: expect.stringContaining('process.binding'),
});
});
it('should reject parameters with eval()', () => {
const responseText = `
{
code: eval('malicious code here')
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({
input: expect.stringContaining('eval'),
});
});
it('should reject parameters with Function constructor', () => {
const responseText = `
{
fn: new Function('return process')()
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({
input: expect.stringContaining('Function'),
});
});
it('should reject parameters with constructor access', () => {
const responseText = `
{
hack: ({}).__proto__.constructor('return process')()
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({
input: expect.stringContaining('constructor'),
});
});
it('should reject parameters with global object access', () => {
const responseText = `
{
test: global.process.exit(1)
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({
input: expect.stringContaining('global'),
});
});
it('should reject parameters with __dirname or __filename', () => {
const responseText = `
{
path: __dirname + '/sensitive-file.txt'
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({
input: expect.stringContaining('__dirname'),
});
});
});
describe('Length limits', () => {
it('should handle very long parameter strings safely', () => {
const longString = 'a'.repeat(15000);
const responseText = `
{
data: "${longString}"
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
// Should be parsed as JSON (safe path)
if (result.parameters?.data) {
expect(typeof result.parameters.data).toBe('string');
}
});
it('should truncate fallback input to prevent DoS', () => {
const longNonJson = 'not json '.repeat(200);
const responseText = `
${longNonJson}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
if (result.parameters?.input && typeof result.parameters.input === 'string') {
expect(result.parameters.input.length).toBeLessThanOrEqual(1000);
}
});
});
describe('Safe parsing paths', () => {
it('should safely parse valid JSON', () => {
const responseText = `
{
"name": "test",
"value": 123,
"nested": {"key": "value"}
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({
name: 'test',
value: 123,
nested: { key: 'value' },
});
});
it('should safely parse JavaScript object literals via regex conversion', () => {
const responseText = `
{ key: "value", number: 42 }
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters?.key).toBe('value');
expect(result.parameters?.number).toBe(42);
});
});
describe('Prompt injection scenarios', () => {
it('should handle AI trying to inject code via parameters', () => {
const responseText = `
{
"query": "normal query",
"filter": "[tag[test]]"
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
// Should parse safely as JSON
expect(result.parameters?.query).toBe('normal query');
expect(result.parameters?.filter).toBe('[tag[test]]');
});
it('should handle nested malicious code in valid JSON', () => {
const responseText = `
{
"normal": "value",
"nested": {
"attack": "'; require('fs').readFileSync('/etc/passwd'); '"
}
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
// Should parse as JSON, making the attack string just data
expect(result.parameters?.normal).toBe('value');
expect(result.parameters?.nested).toEqual({
attack: "'; require('fs').readFileSync('/etc/passwd'); '",
});
});
});
describe('Edge cases and robustness', () => {
it('should handle empty parameters', () => {
const responseText = `
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({});
});
it('should handle whitespace-only parameters', () => {
const responseText = `
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters).toEqual({});
});
it('should handle special characters in string values safely', () => {
const responseText = `
{
"text": "Contains 'quotes' and \\"escapes\\" and symbols @#$%"
}
`;
const result = matchToolCalling(responseText);
expect(result.found).toBe(true);
expect(result.parameters?.text).toContain('quotes');
expect(result.parameters?.text).toContain('escapes');
});
});
});