Skip to the content.

AppSec Agent (TypeScript)

A TypeScript package that provides AI-powered agents for Application Security (AppSec) tasks, built on top of the Claude Agent SDK. It helps automate mundane application security operations and streamline workflows.

πŸ“¦ Available on npm: Install with npm install appsec-agent

🌐 Looking for a full web dashboard? Check out AI Threat Modeler β€” the parent application that bundles appsec-agent into a Dockerized Next.js + Express stack with authentication, an interactive threat-aware Data Flow Diagram canvas, risk registry exports (PDF/CSV/JSON), and a chat UI. It’s the easiest way to use this agent without writing code.

πŸš€ Features

πŸ“‹ Table of Contents

πŸ›  Installation

Prerequisites

Step 1: Install appsec-agent

Note on Claude Code: @anthropic-ai/claude-agent-sdk bundles its own native claude binary for every supported (platform, arch, libc), so the standalone @anthropic-ai/claude-code CLI is not required to run this package. Install it globally only if you want the claude CLI on your PATH for manual use.

Install the package from npm:

$ npm install appsec-agent

Or if you prefer global installation (to use the CLI command directly):

$ npm install -g appsec-agent

The package includes pre-built JavaScript files, so no build step is required for usage.

⚑ Quick Start

1. Set Up Environment Variables

Add these to your shell profile (.bashrc, .zshrc, etc.):

# Anthropic API Configuration
export ANTHROPIC_API_KEY="your-anthropic-api-key"
export ANTHROPIC_BASE_URL="https://api.anthropic.com"

2. Run Your First Agent

You can run the agent using the CLI command:

# If installed globally
$ agent-run

# If installed locally, use npx
$ npx agent-run

# Or run with specific options
$ npx agent-run -r simple_query_agent

πŸ”§ Configuration

The agents can be configured through environment variables and configuration files. Key configuration options include:

Configuration file: conf/appsec_agent.yaml

πŸ€– Available Agents

Simple Query Agent (simple_query_agent)

A general-purpose AppSec assistant that can:

Code Review Agent (code_reviewer)

A specialized agent for automated code analysis that can:

Code Fixer Agent (code_fixer)

A specialized agent for generating precise security fixes that can:

QA Verifier Agent (qa_verifier)

A specialized agent for verifying security fixes that can:

Threat Modeler (threat_modeler)

A specialized agent for comprehensive threat modeling that can:

πŸ“– Usage Examples

Basic Query

# Interactive query agent
$ npx agent-run

# Query agent with source code directory context
$ npx agent-run -r simple_query_agent -s /path/to/source

Code Review Example

# Review code in current directory
$ npx agent-run -r code_reviewer

# Review specific source directory
$ npx agent-run -r code_reviewer -s /path/to/source

# Custom output file and format
$ npx agent-run -r code_reviewer -o security_report.html -f html

# Review with deployment context for more targeted analysis
$ npx agent-run -r code_reviewer -s ./src \
  -c "AWS Lambda function in production VPC, handles user authentication via API Gateway, processes PII data"

# Kubernetes microservice with compliance context
$ npx agent-run -r code_reviewer -s ./payment-service \
  -c "Kubernetes microservice on GKE, PCI-DSS compliant environment, internal service mesh only"

# Internal tool with access context
$ npx agent-run -r code_reviewer -s ./admin-cli \
  -c "Internal CLI tool run by DevOps, requires VPN access, elevated AWS IAM permissions"

The -c/--context option provides deployment and environment information that helps the agent:

PR-Focused Code Review (Diff Context Mode)

For Pull Request reviews, use the -d/--diff-context option to provide a JSON file containing only the changed code. This significantly reduces token usage by focusing the review on actual changes rather than the entire codebase.

# Review a PR using diff context
$ npx agent-run -r code_reviewer -d pr-diff.json

# Combine with source directory for full file access when needed
$ npx agent-run -r code_reviewer -d pr-diff.json -s ./src

# With additional deployment context
$ npx agent-run -r code_reviewer -d pr-diff.json -c "Production API, handles PII"

The diff context JSON file should follow this structure:

{
  "prNumber": 123,
  "baseBranch": "main",
  "headBranch": "feature/auth",
  "headSha": "abc123def456",
  "owner": "your-org",
  "repo": "your-repo",
  "files": [
    {
      "filePath": "src/auth/login.ts",
      "language": "typescript",
      "fileType": "modified",
      "imports": "import bcrypt from 'bcrypt';",
      "hunks": [
        {
          "startLine": 42,
          "endLine": 55,
          "beforeContext": "// Previous context",
          "changedCode": "+const password = req.body.password;",
          "afterContext": "// Following context",
          "containingFunction": "async function login(req, res)"
        }
      ]
    }
  ],
  "totalFilesChanged": 1,
  "totalLinesAdded": 10,
  "totalLinesRemoved": 5
}

Note: If --diff-context is provided without the code_reviewer role, a warning will be displayed as the option is only applicable to code reviews.

PR chunking (large PRs)

When a PR diff exceeds the model’s context limit, chunking splits the diff into batches, reviews each batch, then merges the reports into a single output file.

When chunking is used, the merged report may include a Skipped section listing files that were excluded or that exceeded the batch limit. Total API cost is logged per batch and as a total, and (for JSON reports) included in meta.total_cost_usd.

# pr_reviewer has chunking on by default when using -d
$ npx agent-run -r pr_reviewer -d pr-diff.json

# Or enable chunking via CLI when using code_reviewer (overrides config)
$ npx agent-run -r code_reviewer -d pr-diff.json --diff-max-tokens 150000 --diff-max-batches 3

Adversarial second pass (pr_adversary)

After a pr_reviewer run, the parent app can invoke a second pass that drops findings without a concrete failure/exploit path. Input is a JSON file listing candidate findings; output is a filtered security_review_report (same schema as the main PR report).

# Filter candidate findings (JSON in β†’ JSON out). Optional: same PR diff for context.
$ npx agent-run -r pr_adversary --adversarial-context candidates.json -s ./repo -f json \
  -o adversarial_code_review_report.json

# Optional: include diff context (large diffs are truncated for the prompt)
$ npx agent-run -r pr_adversary --adversarial-context candidates.json --diff-context pr-diff.json -s ./repo -f json

Full-repo adversarial false-positive filter (fp_adversary, v2.8.0)

The Lane-2 counterpart to pr_adversary: where pr_adversary re-filters PR-scoped findings, fp_adversary operates over a whole repository’s first-pass code_reviewer findings and emits a per-finding verdict (confirm or dismiss) with a numeric 0–1 confidence and a concrete rationale. The output shape is a dedicated fp_adversary_report (distinct from security_review_report) so the parent app can route low-confidence dismissals to a β€œpre-dismissed” UI state and auto-dismiss only above an operator-configured confidence threshold.

# Full-repo false-positive filter β€” same --adversarial-context flag, distinct input/output schema.
$ npx agent-run -r fp_adversary --adversarial-context fp_in.json -s ./repo -f json \
  -o fp_adversary_report.json

Input shape (findings[].fingerprint is the round-trip key; the four posture fields and similar_dismissed precedent array are all optional but recommended):

{
  "findings": [
    {
      "fingerprint": "fp-sha256-of-cwe-file-snippet-line",
      "id": "SEC-001",
      "title": "SQL injection",
      "file": "src/db.ts",
      "description": "…",
      "severity": "HIGH",
      "confidence": "MEDIUM",
      "cwe_id": "CWE-89"
    }
  ],
  "project_summary": "A Next.js SaaS app",
  "security_context": "Prisma ORM with parameterized queries",
  "deployment_context": "Vercel, multi-tenant",
  "developer_context": "PHI handling rules apply to user_data",
  "similar_dismissed": [
    { "fingerprint": "fp-old", "file": "src/db.ts", "cwe": "CWE-89", "dismissal_reason": "Prisma parameterized query" }
  ],
  "metadata": { "project_name": "parent-app" }
}

Output shape:

{
  "fp_adversary_report": {
    "verdicts": [
      {
        "fingerprint": "fp-sha256-of-cwe-file-snippet-line",
        "verdict": "dismiss",
        "confidence": 0.92,
        "rationale": "Prisma parameterized query mitigates; no concrete bypass path observed.",
        "cost_usd_estimate": 0.001
      }
    ]
  }
}

fp_adversary is MCP-aware: passing --mcp-server-url exposes queryFindingsHistory, queryImportGraph, queryCodebaseGraph, and queryRuntimeEnrichment at runtime so the agent can verify reachability before confirming.

Input file shape (minimum per finding: id, title, file, description):

{
  "findings": [
    {
      "id": "SEC-001",
      "title": "…",
      "file": "src/a.ts",
      "description": "…",
      "severity": "HIGH",
      "confidence": "HIGH",
      "recommendation": "…"
    }
  ],
  "pr_number": 123,
  "head_sha": "abc123"
}

Code Fixer Example

# Fix a vulnerability described in a fix context JSON file
$ npx agent-run -r code_fixer --fix-context fix_context.json

# With source directory for additional context
$ npx agent-run -r code_fixer --fix-context fix_context.json -s ./src

# Custom output file
$ npx agent-run -r code_fixer --fix-context fix_context.json -o my_fix.json

The fix context JSON file should follow this structure:

{
  "finding": {
    "title": "SQL Injection",
    "severity": "HIGH",
    "cwe": "CWE-89",
    "owasp": "A03:2021",
    "file": "src/db.ts",
    "line": 42,
    "description": "User input directly concatenated into SQL query",
    "recommendation": "Use parameterized queries",
    "category": "Injection"
  },
  "code_context": {
    "language": "typescript",
    "imports": "import { db } from './database';",
    "vulnerable_section": "const result = db.query(`SELECT * FROM users WHERE id = ${userId}`);",
    "vulnerable_section_start": 40,
    "vulnerable_section_end": 44,
    "full_file_with_line_numbers": "  40| const result = db.query(...);",
    "indentation_guidance": "Use 2-space indentation"
  },
  "security_guidance": "Use parameterized queries to prevent SQL injection.",
  "learned_examples": "",
  "negative_examples": "",
  "custom_instructions": "",
  "chain_of_thought": false
}

The agent returns a structured FixOutput:

{
  "fixed_code": "const result = db.query('SELECT * FROM users WHERE id = ?', [userId]);",
  "start_line": 42,
  "end_line": 42,
  "explanation": "Replaced string interpolation with parameterized query to prevent SQL injection",
  "confidence": "high",
  "breaking_changes": false
}

QA Verifier Example

# Verify a security fix by running the project's tests
$ npx agent-run -r qa_verifier --qa-context qa_context.json

# With source directory for additional context
$ npx agent-run -r qa_verifier --qa-context qa_context.json -s ./src

# Custom output file
$ npx agent-run -r qa_verifier --qa-context qa_context.json -o qa_verdict.json

The QA context JSON file should follow this structure:

{
  "pr_url": "https://github.com/owner/repo/pull/42",
  "test_command": "npm test",
  "test_framework": "jest",
  "setup_commands": "npm ci",
  "timeout_seconds": 120,
  "block_on_failure": true,
  "deployment_context": "Production Kubernetes cluster",
  "environment_variables": {
    "NODE_ENV": "test"
  }
}

The agent returns a structured QaVerdict:

{
  "pass": true,
  "test_exit_code": 0,
  "failures": [],
  "logs": "All 235 tests passed",
  "analysis": "All tests pass after the security fix.",
  "suggestions": []
}

Threat Modeler Example

# Run threat modeler on current directory
$ npx agent-run -r threat_modeler

# Run threat modeler on specific source directory
$ npx agent-run -r threat_modeler -s /path/to/source

List Available Roles

$ npx agent-run -l

Version Information

$ npx agent-run -v

Note: If you installed the package globally, you can use agent-run directly instead of npx agent-run.

🌐 Web Application Usage

This package is designed to be thread-safe for use in web applications where multiple requests may be processed concurrently.

Key Thread-Safety Features

Best Practices for Web Applications

  1. Create New Instances Per Request: Always create a new AgentActions instance for each HTTP request:
import { AgentActions, AgentArgs, loadYaml } from 'appsec-agent';

app.post('/api/query', async (req, res) => {
  const confDict = loadYaml('conf/appsec_agent.yaml');
  const args: AgentArgs = {
    role: 'simple_query_agent',
    environment: 'default',
    verbose: false
  };
  
  // Create new instance per request
  const agentActions = new AgentActions(confDict, 'default', args);
  
  // Use agentActions for this request only
  const result = await agentActions.simpleQueryClaudeWithOptions(req.body.query);
  
  res.json({ result });
});
  1. Clear Tool Usage Logs: If reusing AgentOptions instances, clear logs between requests:
const agentOptions = new AgentOptions(confDict, environment);
// ... use agentOptions ...
agentOptions.clearToolUsageLog(); // Clear before next request
  1. Pass Working Directory Explicitly: When using file operations, pass the working directory explicitly:
import { validateOutputFilePath } from 'appsec-agent';

// In web application context
const workingDir = process.cwd(); // Capture once per request
const outputPath = validateOutputFilePath('report.md', workingDir);

Thread-Safety Guarantees

πŸ— Architecture

The AppSec AI Agent is built with a modular architecture consisting of several key components:

Core Components

File Structure

appsec-agent/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ agent_actions.ts       # Agent interaction logic
β”‚   β”œβ”€β”€ agent_options.ts       # Agent configuration management
β”‚   β”œβ”€β”€ main.ts               # Main application logic
β”‚   β”œβ”€β”€ utils.ts              # Utility functions
β”‚   β”œβ”€β”€ schemas/
β”‚   β”‚   β”œβ”€β”€ security_report.ts # JSON schema for code review reports
β”‚   β”‚   β”œβ”€β”€ threat_model_report.ts # JSON schema for threat model reports
β”‚   β”‚   └── security_fix.ts    # JSON schema for code fixer output
β”‚   β”‚   └── qa_context.ts      # JSON schema for QA verifier verdict
β”‚   β”œβ”€β”€ tools/
β”‚   β”‚   └── bash_tool.ts       # Restricted Bash tool for QA verifier
β”‚   └── __tests__/
β”‚       β”œβ”€β”€ concurrency.test.ts  # Concurrency and thread-safety tests
β”‚       └── ...                # Other test files
β”œβ”€β”€ bin/
β”‚   └── agent-run.ts          # CLI script (TypeScript source)
β”œβ”€β”€ dist/                      # Compiled output (generated)
β”‚   β”œβ”€β”€ src/                   # Compiled library code
β”‚   └── bin/
β”‚       └── agent-run.js       # Compiled CLI entry point
β”œβ”€β”€ conf/
β”‚   └── appsec_agent.yaml   # General configuration file
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
└── README.md

API Reference

AgentOptions Methods

Diff Context Functions

Path Validation Functions

πŸ›  Development

This section is for developers who want to contribute to the package or modify it locally.

Setting Up Development Environment

  1. Clone the repository:
    $ git clone <repository-url>
    $ cd appsec-agent
    
  2. Install dependencies:
    $ npm install
    
  3. Build the project:
    $ npm run build
    

This will compile the TypeScript source files to JavaScript in the dist/ directory.

Building the Package

# Build the package
$ npm run build

# Clean build artifacts
$ npm run clean

Running from Source

During development, you can run the agent directly from source:

# Using ts-node (no build needed)
$ npx ts-node bin/agent-run.ts

# Or build first, then run
$ npm run build
$ node dist/bin/agent-run.js

πŸ§ͺ Testing

The project includes comprehensive test coverage including concurrency tests for web application scenarios.

Running Tests

# Run all tests
$ npm test

# Run tests in watch mode
$ npm run test:watch

# Run tests with coverage
$ npm run test:coverage

# Run specific test file
$ npm test -- concurrency.test.ts

Test Coverage

Test Results

All tests pass including:

AI Threat Modeler β€” Parent Application

appsec-agent powers AI Threat Modeler, a full open-source web application for AppSec automation. If you’d like to use these agents through a polished UI rather than the CLI or library API, the parent app is the recommended way to get started.

Highlights:

Quick start:

git clone https://github.com/yangsec888/ai-threat-modeler.git
cd ai-threat-modeler
docker-compose up -d --build
# Then open http://localhost:3000  (default login: admin / admin)

See the AI Threat Modeler README and SETUP.md for full details.

πŸ“š References

πŸ“„ License

This project is licensed under the Apache License 2.0 β€” see the LICENSE file for details.

πŸ‘₯ Author

Sam Li - Initial work - [email protected]


Built with ❀️ for the AppSec community