4 Commits

Author SHA1 Message Date
Chris Farhood a96bd1065a fix(api): use trebuchet-* names + dedicated worker SA in Job spec
CI / Build & push worker image (pull_request) Has been skipped
CI / Type-check & lint (pull_request) Failing after 2m9s
CI / Build & push API image (pull_request) Has been skipped
The app was renamed hightower → trebuchet but the worker Job spec still
referenced hightower-workspaces PVC, hightower-temporal Service, and used
the default ServiceAccount.  These break at runtime (the hightower-*
resources don't exist) and block tightening the Istio ambient
AuthorizationPolicies in farhoodlabs/infra.

- PVC claimName: hightower-workspaces → trebuchet-workspaces
- TEMPORAL_ADDRESS env: hightower-temporal:7233 → trebuchet-temporal:7233
- serviceAccountName: default → trebuchet-worker
- config.ts default: hightower-temporal:7233 → trebuchet-temporal:7233

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-23 16:06:42 +00:00
Hugh Commit 70af2b12db Merge pull request 'feat: backport Opus 4.7 + adaptive thinking, remove scan tools, add --help to scripts' (#4) from far-136/backport-phase-1 into main
CI / Type-check & lint (push) Successful in 18s
CI / Build & push API image (push) Successful in 58s
CI / Build & push worker image (push) Successful in 3m35s
feat: backport Opus 4.7 + adaptive thinking, remove scan tools, add --help to scripts (#4)
2026-05-20 00:41:19 +00:00
Chris Farhood 800afbfefb feat(cli): block running with sudo or as root
CI / Type-check & lint (pull_request) Successful in 16s
CI / Build & push API image (pull_request) Has been skipped
CI / Build & push worker image (pull_request) Has been skipped
Backport upstream Shannon PR #323. Adds privilege check at CLI startup
that prevents execution via sudo or as the root user.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-20 00:30:58 +00:00
Chris Farhood 085624b287 feat: backport Opus 4.7 + adaptive thinking, remove scan tools, add --help to scripts
CI / Build & push API image (pull_request) Has been skipped
CI / Type-check & lint (pull_request) Successful in 18s
CI / Build & push worker image (pull_request) Has been skipped
Backport upstream Shannon PRs #325, #327, #328:

- Update large model default to claude-opus-4-7, add adaptive thinking
  configuration (auto-enabled on Opus 4.6/4.7, opt-out via
  CLAUDE_ADAPTIVE_THINKING=false), filter thinking blocks from message
  content, bump claude-agent-sdk to ^0.2.114
- Remove unused scan tools (nmap, subfinder, whatweb, schemathesis) from
  Dockerfile, prompts, and docs; remove dead 'tool' error type from
  PentestErrorType; redact URLs in preflight info logs
- Add --help flag to save-deliverable and generate-totp CLI scripts

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-20 00:26:25 +00:00
22 changed files with 243 additions and 279 deletions
-1
View File
@@ -135,7 +135,6 @@ shannon <URL> <REPO> --pipeline-testing
|-------------------|---------|------------|
| `config` | Configuration file issues | No |
| `network` | Connection/timeout issues | Yes |
| `tool` | External tool (nmap, etc.) failed | Yes |
| `prompt` | Claude SDK/API issues | Sometimes |
| `filesystem` | File read/write errors | Sometimes |
| `validation` | Deliverable validation failed | Yes (via retry) |
+6 -3
View File
@@ -4,6 +4,9 @@
# Recommended output token configuration for larger tool outputs
CLAUDE_CODE_MAX_OUTPUT_TOKENS=64000
# Adaptive thinking is enabled automatically on Opus 4.6/4.7. Set to false to disable.
# CLAUDE_ADAPTIVE_THINKING=false
# =============================================================================
# OPTION 1: Direct Anthropic
# =============================================================================
@@ -26,7 +29,7 @@ ANTHROPIC_API_KEY=your-api-key-here
# Optional for direct Anthropic and custom base URL modes. Required for Bedrock/Vertex.
# ANTHROPIC_SMALL_MODEL=... # Small tier (default: claude-haiku-4-5-20251001)
# ANTHROPIC_MEDIUM_MODEL=... # Medium tier (default: claude-sonnet-4-6)
# ANTHROPIC_LARGE_MODEL=... # Large tier (default: claude-opus-4-6)
# ANTHROPIC_LARGE_MODEL=... # Large tier (default: claude-opus-4-7)
# =============================================================================
# OPTION 3: AWS Bedrock
@@ -36,7 +39,7 @@ ANTHROPIC_API_KEY=your-api-key-here
# Example Bedrock model IDs for us-east-1:
# ANTHROPIC_SMALL_MODEL=us.anthropic.claude-haiku-4-5-20251001-v1:0
# ANTHROPIC_MEDIUM_MODEL=us.anthropic.claude-sonnet-4-6
# ANTHROPIC_LARGE_MODEL=us.anthropic.claude-opus-4-6
# ANTHROPIC_LARGE_MODEL=us.anthropic.claude-opus-4-7
# CLAUDE_CODE_USE_BEDROCK=1
# AWS_REGION=us-east-1
@@ -52,7 +55,7 @@ ANTHROPIC_API_KEY=your-api-key-here
# Example Vertex AI model IDs:
# ANTHROPIC_SMALL_MODEL=claude-haiku-4-5@20251001
# ANTHROPIC_MEDIUM_MODEL=claude-sonnet-4-6
# ANTHROPIC_LARGE_MODEL=claude-opus-4-6
# ANTHROPIC_LARGE_MODEL=claude-opus-4-7
# CLAUDE_CODE_USE_VERTEX=1
# CLOUD_ML_REGION=us-east5
+1 -1
View File
@@ -57,7 +57,7 @@ Durable workflow orchestration with crash recovery, queryable progress, intellig
### Five-Phase Pipeline
1. **Pre-Recon** (`pre-recon`) — External scans (nmap, subfinder, whatweb) + source code analysis
1. **Pre-Recon** (`pre-recon`) — Source code analysis to build the architectural baseline
2. **Recon** (`recon`) — Attack surface mapping from initial findings
3. **Vulnerability Analysis** (5 parallel agents) — injection, xss, auth, authz, ssrf
4. **Exploitation** (5 parallel agents, conditional) — Exploits confirmed vulnerabilities
+2 -49
View File
@@ -13,44 +13,12 @@ RUN apk update && apk add --no-cache \
curl \
wget \
ca-certificates \
# Network libraries for Go tools
libpcap-dev \
linux-headers \
# Language runtimes
go \
nodejs-22 \
npm \
python3 \
py3-pip \
ruby \
ruby-dev \
# Security tools available in Wolfi
nmap \
# Additional utilities
bash
# Set environment variables for Go
ENV GOPATH=/go
ENV PATH=$GOPATH/bin:/usr/local/go/bin:$PATH
ENV CGO_ENABLED=1
# Create directories
RUN mkdir -p $GOPATH/bin
# Install Go-based security tools
RUN go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@v2.13.0
# Install WhatWeb from release tarball (Ruby-based tool)
RUN curl -sL https://github.com/urbanadventurer/WhatWeb/archive/refs/tags/v0.6.3.tar.gz | tar xz -C /opt && \
mv /opt/WhatWeb-0.6.3 /opt/whatweb && \
chmod +x /opt/whatweb/whatweb && \
gem install addressable -v 2.8.9 && \
echo '#!/bin/bash' > /usr/local/bin/whatweb && \
echo 'cd /opt/whatweb && exec ./whatweb "$@"' >> /usr/local/bin/whatweb && \
chmod +x /usr/local/bin/whatweb
# Install Python-based tools
RUN pip3 install --no-cache-dir schemathesis==4.13.0
# Install pnpm
RUN npm install -g pnpm@10.33.0
@@ -84,12 +52,11 @@ RUN apk add --no-cache \
curl \
ca-certificates \
shadow \
libpcap \
nmap \
# Language runtimes (minimal)
nodejs-22 \
npm \
python3 \
ruby \
# Chromium browser and dependencies for Playwright
chromium \
nss \
freetype \
@@ -104,20 +71,6 @@ RUN apk add --no-cache \
fontconfig \
|| true
# Copy Go binaries from builder
COPY --from=builder /go/bin/subfinder /usr/local/bin/
# Copy WhatWeb from builder
COPY --from=builder /opt/whatweb /opt/whatweb
COPY --from=builder /usr/local/bin/whatweb /usr/local/bin/whatweb
# Install WhatWeb Ruby dependencies in runtime stage
RUN gem install addressable -v 2.8.9
# Copy Python packages from builder
COPY --from=builder /usr/lib/python3.*/site-packages /usr/lib/python3.12/site-packages
COPY --from=builder /usr/bin/schemathesis /usr/bin/
# Create non-root user
RUN addgroup -g 1001 pentest && \
adduser -u 1001 -G pentest -s /bin/bash -D pentest
+1 -2
View File
@@ -147,7 +147,7 @@ This phase informs everything downstream. If the codebase uses an ORM with param
## Phase 2: Reconnaissance
Bridges static and dynamic analysis using browser automation. The recon agent correlates code findings with the live application, validating that endpoints actually exist, mapping authentication flows, inventorying input vectors (URL parameters, POST fields, headers, cookies), and documenting the real authorization architecture. This phase may also integrate with infrastructure discovery tools including Nmap, Subfinder, and WhatWeb for network perimeter mapping.
Bridges static and dynamic analysis using browser automation. The recon agent correlates code findings with the live application, validating that endpoints actually exist, mapping authentication flows, inventorying input vectors (URL parameters, POST fields, headers, cookies), and documenting the real authorization architecture.
## Phase 3: Vulnerability Analysis
@@ -194,7 +194,6 @@ This correlation means that a data flow vulnerability identified in static analy
- **Fully Autonomous Operation:** Shannon Pro handles complex workflows including 2FA/TOTP logins and SSO (e.g., Sign in with Google) without human intervention. TOTP is handled via a dedicated MCP server tool.
- **White-Box Awareness:** Unlike black-box scanners, Shannon Pro reads the source code to intelligently guide its attack strategy, combining code-level insight with runtime validation.
- **Parallel Processing:** Vulnerability analysis and exploitation phases run concurrently across attack domains, with pipelined parallelism minimizing total execution time.
- **Tool Orchestration:** Shannon Pro orchestrates existing security tools (e.g., Schemathesis for API testing, Nmap for network discovery) while adding LLM reasoning to interpret results.
- **Configurable Login Flows:** Authentication configuration specifies login procedures and credentials, which are interpolated into agent prompts for authenticated testing.
---
+1 -1
View File
@@ -30,7 +30,7 @@ export function loadConfig(): Config {
return {
port: Number(process.env.PORT) || 3000,
mcpPort: Number(process.env.MCP_PORT) || 3100,
temporalAddress: process.env.TEMPORAL_ADDRESS || 'hightower-temporal:7233',
temporalAddress: process.env.TEMPORAL_ADDRESS || 'trebuchet-temporal:7233',
apiKey,
k8sNamespace: process.env.K8S_NAMESPACE || 'hightower',
workerImage,
+3 -3
View File
@@ -43,7 +43,7 @@ export function buildJobSpec(params: JobParams): k8s.V1Job {
// 2. Build volumes and mounts
const volumes: k8s.V1Volume[] = [
{ name: 'workspaces', persistentVolumeClaim: { claimName: 'hightower-workspaces' } },
{ name: 'workspaces', persistentVolumeClaim: { claimName: 'trebuchet-workspaces' } },
{ name: 'shm', emptyDir: { medium: 'Memory', sizeLimit: '2Gi' } },
];
@@ -96,7 +96,7 @@ export function buildJobSpec(params: JobParams): k8s.V1Job {
}
// 4. Env vars
const env: k8s.V1EnvVar[] = [{ name: 'TEMPORAL_ADDRESS', value: 'hightower-temporal:7233' }];
const env: k8s.V1EnvVar[] = [{ name: 'TEMPORAL_ADDRESS', value: 'trebuchet-temporal:7233' }];
// 5. Construct the Job
return {
@@ -123,7 +123,7 @@ export function buildJobSpec(params: JobParams): k8s.V1Job {
},
spec: {
restartPolicy: 'Never',
serviceAccountName: 'default',
serviceAccountName: 'trebuchet-worker',
securityContext: {
seccompProfile: { type: 'Unconfined' },
// Claude Code refuses --allow-dangerously-skip-permissions as root.
+21
View File
@@ -26,6 +26,25 @@ import { displaySplash } from './splash.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
function blockSudo(): void {
const isSudo = !!process.env.SUDO_USER;
const isRoot = process.geteuid?.() === 0;
if (!isSudo && !isRoot) return;
if (isSudo) {
console.error('ERROR: Shannon must not be run with sudo.');
console.error('Re-run this command as your normal user.');
} else {
console.error('ERROR: Shannon must not be run as the root user.');
console.error('Switch to a regular user account and re-run this command.');
}
if (process.platform === 'linux') {
console.error('Configure Docker to run without sudo first:');
console.error('https://docs.docker.com/engine/install/linux-postinstall');
}
process.exit(1);
}
function getVersion(): string {
try {
const pkgPath = path.join(__dirname, '..', 'package.json');
@@ -179,6 +198,8 @@ function parseStartArgs(argv: string[]): ParsedStartArgs {
// === Main Dispatch ===
blockSudo();
const args = process.argv.slice(2);
// Parse --backend flag before command dispatch
+2 -3
View File
@@ -180,17 +180,16 @@ For each root vulnerability in your plan, you will follow this systematic, four-
## **Strategic Tool Usage**
Use the right tool for the job to ensure thoroughness.
- **Use `curl` (Manual Probing) for:** Initial confirmation, simple UNION/Error-based injections, and crafting specific WAF bypasses.
- **Use `sqlmap` (Automation) for:** Time-consuming blind injections, automating enumeration **after** manual confirmation, and as a final step to try a wide range of payloads when manual techniques are failing.
## **Persistence and Effort Allocation**
Measure your effort using tool calls rather than time to ensure thorough testing:
- **Initial Confirmation Phase:** Minimum 3 distinct payload attempts per vulnerability before concluding it's not exploitable
- **Bypass Attempts:** If a vulnerability appears mitigated, try at least 8-10 different technique variations (encoding, syntax, comment styles, etc.) before concluding it's properly defended
- **Escalation Trigger:** If manual testing exceeds 10-12 tool calls without progress on a single vulnerability, escalate to automated tools (`sqlmap`) or Task Agent scripting
- **Escalation Trigger:** If manual testing exceeds 10-12 tool calls without progress on a single vulnerability, escalate to Task Agent scripting
- **Termination Criteria:** After systematic attempts with multiple different techniques → classify as appropriate level
## **Using the Task Agent for Custom Scripting**
You must delegate every injection automation task to the Task Agent. Use manual `curl` or `sqlmap` runs for spot checks, then escalate to scripted payload loops handled by the Task Agent.
You must delegate every injection automation task to the Task Agent. Use manual `curl` runs for spot checks, then escalate to scripted payload loops handled by the Task Agent.
**TEMPLATE FOR SCRIPTING TASKS (REQUIRED):**
"
+1 -2
View File
@@ -36,7 +36,7 @@ Read `.gitignore` and run `git ls-files --others --ignored --exclude-standard --
**Phase Sequence:** **PRE-RECON (You)** → RECON → VULN ANALYSIS (5 agents) → EXPLOITATION (5 agents) → REPORTING
**Your Input:** External scan results from pre-recon tools (nmap, subfinder, whatweb)
**Your Input:** Target application source code in the working directory
**Your Output:** `.shannon/deliverables/pre_recon_deliverable.md` (feeds all subsequent analysis phases)
**Shared Intelligence:** You create the foundational intelligence baseline that all other agents depend on
@@ -71,7 +71,6 @@ You are the **Code Intelligence Gatherer** and **Architectural Foundation Builde
<starting_context>
- You are the **ENTRY POINT** of the comprehensive security assessment - no prior deliverables exist to read
- External reconnaissance tools have completed and their results are available in the working environment
- The target application source code has been cloned and is ready for analysis in the current directory
- You must create the **foundational intelligence baseline** that all subsequent agents depend on
- **CRITICAL:** This is the ONLY agent with full source code access - your completeness determines whether vulnerabilities are found
+6 -8
View File
@@ -1,5 +1,5 @@
<role>
You are a world-class Reconnaissance Analyst and Attack Surface Mapper. Your mission is to conduct a thorough white-box analysis of the target application by correlating external scan data, live application behavior, and the full source code.
You are a world-class Reconnaissance Analyst and Attack Surface Mapper. Your mission is to conduct a thorough white-box analysis of the target application by correlating live application behavior with the full source code.
</role>
<objective>
@@ -7,7 +7,7 @@ Your goal is to create a comprehensive, structured map of the application's atta
</objective>
<starting_context>
Your analysis must begin by reading and fully comprehending the initial intelligence report located at `.shannon/deliverables/pre_recon_deliverable.md`. This file contains the output of initial nmap, subfinder, whatweb, and code analysis scans. This is your only starting information.
Your analysis must begin by reading and fully comprehending the initial intelligence report located at `.shannon/deliverables/pre_recon_deliverable.md`. This file contains the initial source code analysis. This is your only starting information.
</starting_context>
<target>
@@ -80,13 +80,13 @@ Please use these tools for the following use cases:
**Phase Sequence:** PRE-RECON (Complete) → **RECONNAISSANCE (You)** → VULN ANALYSIS (5 agents) → EXPLOITATION (5 agents) → FINAL REPORT (next phase)
**Your Input:** `.shannon/deliverables/pre_recon_deliverable.md` (external scan data, initial code analysis)
**Your Input:** `.shannon/deliverables/pre_recon_deliverable.md` (initial code analysis)
**Your Output:** `.shannon/deliverables/recon_deliverable.md` (comprehensive attack surface map)
**Shared Intelligence:** None (you are the first analysis specialist)
**WHAT HAPPENED BEFORE YOU:**
- Pre-reconnaissance agent performed external scans (nmap, subfinder, whatweb) and initial code analysis
- All attack surfaces, technologies, and entry points were catalogued from external perspective
- Pre-reconnaissance agent performed initial source code analysis
- Attack surfaces, technologies, and entry points were catalogued from the codebase
**WHAT HAPPENS AFTER YOU:**
- Injection Analysis specialist will analyze SQL injection and command injection vulnerabilities using your attack surface map
@@ -112,7 +112,7 @@ You must follow this methodical four-step process:
1. **Synthesize Initial Data:**
- Read the entire `.shannon/deliverables/pre_recon_deliverable.md`.
- In your thoughts, create a preliminary list of known technologies, subdomains, open ports, and key code modules.
- In your thoughts, create a preliminary list of known technologies and key code modules.
2. **Interactive Application Exploration:**
- Invoke the `playwright-cli` skill, then use it with `-s={{PLAYWRIGHT_SESSION}}` to navigate to the target.
@@ -166,8 +166,6 @@ A brief overview of the application's purpose, core technology stack (e.g., Next
- **Frontend:** [Framework, key libraries, authentication libraries]
- **Backend:** [Language, framework, key dependencies]
- **Infrastructure:** [Hosting provider, CDN, database type]
- **Identified Subdomains:** [List from subfinder and any others discovered]
- **Open Ports & Services:** [List from nmap and their purpose]
## 3. Authentication & Session Management Flow
- **Entry Points:** [e.g., /login, /register, /auth/sso]
+2 -14
View File
@@ -12,7 +12,7 @@ Technical leadership (CTOs, CISOs, Engineering VPs) who need both technical accu
The orchestrator has already concatenated all specialist reports into `comprehensive_security_assessment_report.md`.
Your task is to:
1. Read this existing concatenated report
2. Add Executive Summary (vulnerability overview) and Network Reconnaissance (security-relevant scan findings) sections at the top
2. Add an Executive Summary (vulnerability overview) at the top
3. Clean up ALL exploitation evidence sections by removing hallucinated content
4. Save the modified version back to the same file
@@ -72,19 +72,10 @@ MODIFY the existing file `.shannon/deliverables/comprehensive_security_assessmen
**Server-Side Request Forgery (SSRF) Vulnerabilities:**
{Check for "SSRF Exploitation Evidence" section. Include actually exploited vulnerabilities and those blocked by security controls. Exclude theoretical vulnerabilities requiring internal network access. If vulnerabilities exist, summarize their impact and severity. If section is missing or empty, state: "No SSRF vulnerabilities were found."}
## Network Reconnaissance
{Extract security-relevant findings from automated scanning tools:
- Open ports and exposed services from nmap
- Subdomain discoveries from subfinder that could expand attack surface
- Security headers or misconfigurations detected by whatweb
- Any other security-relevant findings from the automated tools
SKIP stack details - technical leaders know their infrastructure}
2. KEEPING the existing exploitation evidence sections but CLEANING them according to the rules below
3. The final structure should be:
- Executive Summary (new)
- Network Reconnaissance (new)
- All existing exploitation evidence sections (cleaned)
IMPORTANT: Do NOT reorder the existing exploitation evidence sections. Maintain the exact order they appear in the concatenated report. Only remove sections that do not match the defined criteria above.
@@ -93,15 +84,12 @@ IMPORTANT: Do NOT reorder the existing exploitation evidence sections. Maintain
<instructions>
1. Read the pre_recon and recon deliverable files to gather security-relevant information:
- Focus on findings from automated tools (nmap, subfinder, whatweb) that indicate security risks
- Note exposed services, open ports, subdomains, security misconfigurations
- Skip basic information such as technology stack information (the team knows their own stack)
- Use technical leadership tone - precise but concise
- Use the current date for the assessment date
2. Create the Executive Summary and Network Reconnaissance content:
2. Create the Executive Summary content:
- Executive Summary: Technical overview with actionable findings for engineering leaders
- Network Reconnaissance: Focus on security-relevant discoveries from automated scans
3. Clean the exploitation evidence sections from `.shannon/deliverables/comprehensive_security_assessment_report.md` by applying these rules:
- KEEP these specific section headings:
+3 -1
View File
@@ -18,7 +18,7 @@ import { formatTimestamp } from '../utils/formatting.js';
import { Timer } from '../utils/metrics.js';
import { createAuditLogger } from './audit-logger.js';
import { dispatchMessage } from './message-handlers.js';
import { type ModelTier, resolveModel } from './models.js';
import { type ModelTier, resolveModel, supportsAdaptiveThinking } from './models.js';
import { detectExecutionContext, formatCompletionMessage, formatErrorOutput } from './output-formatters.js';
import { createProgressManager } from './progress-manager.js';
@@ -218,6 +218,7 @@ export async function runClaudePrompt(
// 4. Configure SDK options
// Model override from providerConfig takes precedence over env-based resolveModel
const model = providerConfig?.modelOverrides?.[modelTier] ?? resolveModel(modelTier);
const adaptiveThinking = supportsAdaptiveThinking(model) && process.env.CLAUDE_ADAPTIVE_THINKING !== 'false';
const options = {
model,
maxTurns: 10_000,
@@ -226,6 +227,7 @@ export async function runClaudePrompt(
allowDangerouslySkipPermissions: true,
settingSources: ['user'] as ('user' | 'project' | 'local')[],
env: sdkEnv,
...(adaptiveThinking && { thinking: { type: 'adaptive' as const } }),
...(outputFormat && { outputFormat }),
};
+4 -1
View File
@@ -39,7 +39,10 @@ function extractMessageContent(message: AssistantMessage): string {
const messageContent = message.message;
if (Array.isArray(messageContent.content)) {
return messageContent.content.map((c: ContentBlock) => c.text || JSON.stringify(c)).join('\n');
return messageContent.content
.filter((c: ContentBlock) => c.type !== 'thinking' && c.type !== 'redacted_thinking')
.map((c: ContentBlock) => c.text || JSON.stringify(c))
.join('\n');
}
return String(messageContent.content);
+6 -1
View File
@@ -21,7 +21,7 @@ export type ModelTier = 'small' | 'medium' | 'large';
const DEFAULT_MODELS: Readonly<Record<ModelTier, string>> = {
small: 'claude-haiku-4-5-20251001',
medium: 'claude-sonnet-4-6',
large: 'claude-opus-4-6',
large: 'claude-opus-4-7',
};
/** Resolve a model tier to a concrete model ID. */
@@ -35,3 +35,8 @@ export function resolveModel(tier: ModelTier = 'medium'): string {
return process.env.ANTHROPIC_MEDIUM_MODEL || DEFAULT_MODELS.medium;
}
}
/** Whether a model supports adaptive thinking. Opus 4.6 and 4.7 only. */
export function supportsAdaptiveThinking(model: string): boolean {
return /opus-4-[67]/.test(model);
}
+2
View File
@@ -52,6 +52,8 @@ export interface ToolResultData {
export interface ContentBlock {
type?: string;
text?: string;
thinking?: string;
data?: string;
}
export interface AssistantMessage {
+25
View File
@@ -82,6 +82,26 @@ function generateTOTP(secret: string, timeStep: number = 30, digits: number = 6)
return generateHOTP(secret, counter, digits);
}
// === Help ===
function printHelp(): void {
console.log(
`generate-totp - emit a current 6-digit TOTP code for a base32-encoded secret.
Usage:
generate-totp --secret <BASE32>
generate-totp --help
Options:
--secret Base32-encoded TOTP shared secret (characters A-Z, 2-7).
-h, --help Show this help and exit.
Output:
JSON to stdout. On success: {"status":"success","totpCode":"123456","expiresIn":<sec>}.
On error: {"status":"error","message":"...","retryable":false} (exit 1).`,
);
}
// === Argument Parsing ===
function parseSecret(argv: string[]): string {
@@ -97,6 +117,11 @@ function parseSecret(argv: string[]): string {
// === Main ===
function main(): void {
if (process.argv.includes('--help') || process.argv.includes('-h')) {
printHelp();
return;
}
const secret = parseSecret(process.argv);
if (!secret) {
@@ -19,6 +19,31 @@ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { join, resolve } from 'node:path';
import { DELIVERABLE_FILENAMES, type DeliverableType } from '../types/deliverables.js';
// === Help ===
function printHelp(): void {
const types = Object.keys(DELIVERABLE_FILENAMES).join(', ');
console.log(
`save-deliverable - save a Shannon pentest deliverable under its canonical filename.
Usage:
save-deliverable --type <TYPE> --file-path <path>
save-deliverable --type <TYPE> --content '<text>'
save-deliverable --help
Options:
--type Deliverable type (required). One of:
${types}
--file-path Path of a file whose contents to save (preferred for large content).
--content Inline content string to save.
-h, --help Show this help and exit.
Output:
JSON to stdout. On success: {"status":"success","filepath":"..."}.
On error: {"status":"error","message":"...","retryable":true|false} (exit 1).`,
);
}
// === Argument Parsing ===
interface ParsedArgs {
@@ -69,6 +94,11 @@ function saveDeliverableFile(targetDir: string, filename: string, content: strin
// === Main ===
function main(): void {
if (process.argv.includes('--help') || process.argv.includes('-h')) {
printHelp();
return;
}
const args = parseArgs(process.argv);
// 1. Validate --type
+2 -2
View File
@@ -210,7 +210,7 @@ async function validateCredentials(
// 1. Custom base URL — validate endpoint is reachable via SDK query
if (process.env.ANTHROPIC_BASE_URL && process.env.ANTHROPIC_AUTH_TOKEN) {
const baseUrl = process.env.ANTHROPIC_BASE_URL;
logger.info(`Validating custom base URL: ${baseUrl}`);
logger.info('Validating custom base URL');
try {
for await (const message of query({ prompt: 'hi', options: { model: resolveModel('small'), maxTurns: 1 } })) {
@@ -394,7 +394,7 @@ function httpHead(url: string, timeoutMs: number): Promise<number> {
/** Check that the target URL is reachable from inside the container. */
async function validateTargetUrl(targetUrl: string, logger: ActivityLogger): Promise<Result<void, PentestError>> {
logger.info('Checking target URL reachability...', { targetUrl });
logger.info('Checking target URL reachability...');
// 1. Parse URL
let parsed: URL;
+2 -10
View File
@@ -11,7 +11,7 @@
/**
* Specific error codes for reliable classification.
*
* ErrorCode provides precision within the coarse 8-category PentestErrorType.
* ErrorCode provides precision within the coarse 7-category PentestErrorType.
* Used by classifyErrorForTemporal for code-based classification (preferred)
* with string matching as fallback for external errors.
*/
@@ -47,15 +47,7 @@ export enum ErrorCode {
BILLING_ERROR = 'BILLING_ERROR',
}
export type PentestErrorType =
| 'config'
| 'network'
| 'tool'
| 'prompt'
| 'filesystem'
| 'validation'
| 'billing'
| 'unknown';
export type PentestErrorType = 'config' | 'network' | 'prompt' | 'filesystem' | 'validation' | 'billing' | 'unknown';
export interface PentestErrorContext {
[key: string]: unknown;
+122 -176
View File
@@ -7,8 +7,8 @@ settings:
catalogs:
default:
'@anthropic-ai/claude-agent-sdk':
specifier: ^0.2.38
version: 0.2.76
specifier: ^0.2.114
version: 0.2.140
importers:
@@ -77,7 +77,7 @@ importers:
dependencies:
'@anthropic-ai/claude-agent-sdk':
specifier: 'catalog:'
version: 0.2.76(zod@4.3.6)
version: 0.2.140(zod@4.3.6)
'@temporalio/activity':
specifier: ^1.11.0
version: 1.15.0
@@ -115,12 +115,65 @@ importers:
packages:
'@anthropic-ai/claude-agent-sdk@0.2.76':
resolution: {integrity: sha512-HZxvnT8ZWkzCnQygaYCA0dl8RSUzuVbxE1YG4ecy6vh4nQbTT36CxUxBy+QVdR12pPQluncC0mCOLhI2918Eaw==}
'@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.140':
resolution: {integrity: sha512-zEbDsDKeoDO4DzbyX6wBVlcPhLy/gYiCrKzKnxmkOhyNtJBeshgiOTdr+M7WX1xcuI/M/UhEY+B9U6oo884lAQ==}
cpu: [arm64]
os: [darwin]
'@anthropic-ai/claude-agent-sdk-darwin-x64@0.2.140':
resolution: {integrity: sha512-BFJGeZEksvERy7mMJ0mkNAWoMrZOgl6XN/mKPaunGnaC/i+1ykx7xih7e58bRhsrzKzo2mnUrwtjiFyF3MFNRQ==}
cpu: [x64]
os: [darwin]
'@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.2.140':
resolution: {integrity: sha512-nG7xLL0nKb4ymFVnX0QhSGLoyhh9fuuDpBR+TYz5O4ZQc2RVUMSMqGusqcCNEIGxAKQSVKWCf0WgpCG/edAO9Q==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@anthropic-ai/claude-agent-sdk-linux-arm64@0.2.140':
resolution: {integrity: sha512-FauGGg3zikxrjAUnu+Pso6zD9Qv4Z2+QBiTiZqc12U+x4uoikNsplymUnsJ7MYD9VaTGmLJuZ9pCch0IiKrseQ==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.2.140':
resolution: {integrity: sha512-EZ7VzOGmvft/1ymh2rwts5v3yPnsGGlGrTJlY2Dqnr1ABF43JIhEm1NFYrLnXQWSN74s5Pj8tgkPbYS9x4BhFA==}
cpu: [x64]
os: [linux]
libc: [musl]
'@anthropic-ai/claude-agent-sdk-linux-x64@0.2.140':
resolution: {integrity: sha512-7f627Tq2mIiwFoBYfCKTdEeZSP90r8UOWu/I5DezudTtwtoVl2zRaRCnJ8c4rW+Tzw+xWSfP/pHvR9bTQGXaOw==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@anthropic-ai/claude-agent-sdk-win32-arm64@0.2.140':
resolution: {integrity: sha512-9EOozRF+LTt3UedeJtjJXC8pj9VTAFtPBuB+/YUmcpmDAEH9qcWWknWhf7NDKTapKtBWkNP/387x+18L15MLqg==}
cpu: [arm64]
os: [win32]
'@anthropic-ai/claude-agent-sdk-win32-x64@0.2.140':
resolution: {integrity: sha512-puQyWoYiqosjDEYULWAS/lBJse1vzib0NmQj/bYTirWCbtiUcu6ixKMd4NmLbE+Si/DKTB8XNz6hVZ/KckqeoQ==}
cpu: [x64]
os: [win32]
'@anthropic-ai/claude-agent-sdk@0.2.140':
resolution: {integrity: sha512-Zq2L7YCoTdbxTUi3/soN1axrTqbG7GoKuc6Im8EpkBRdwaY0D1W9+Ux3vAbV/cX8Qk31Vck7DQLZz1lGEArdoQ==}
engines: {node: '>=18.0.0'}
peerDependencies:
zod: ^4.0.0
'@anthropic-ai/sdk@0.81.0':
resolution: {integrity: sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw==}
hasBin: true
peerDependencies:
zod: ^3.25.0 || ^4.0.0
peerDependenciesMeta:
zod:
optional: true
'@babel/generator@8.0.0-rc.2':
resolution: {integrity: sha512-oCQ1IKPwkzCeJzAPb7Fv8rQ9k5+1sG8mf2uoHiMInPYvkRfrDJxbTIbH51U+jstlkghus0vAi3EBvkfvEsYNLQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -138,6 +191,10 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
'@babel/runtime@7.29.2':
resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==}
engines: {node: '>=6.9.0'}
'@babel/types@8.0.0-rc.2':
resolution: {integrity: sha512-91gAaWRznDwSX4E2tZ1YjBuIfnQVOFDCQ2r0Toby0gu4XEbyF623kXLMA8d4ZbCu+fINcrudkmEcwSUHgDDkNw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -229,105 +286,6 @@ packages:
peerDependencies:
hono: ^4
'@img/sharp-darwin-arm64@0.34.5':
resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [darwin]
'@img/sharp-darwin-x64@0.34.5':
resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [darwin]
'@img/sharp-libvips-darwin-arm64@1.2.4':
resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
cpu: [arm64]
os: [darwin]
'@img/sharp-libvips-darwin-x64@1.2.4':
resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
cpu: [x64]
os: [darwin]
'@img/sharp-libvips-linux-arm64@1.2.4':
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-arm@1.2.4':
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-x64@1.2.4':
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-linux-arm64@0.34.5':
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-arm@0.34.5':
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-linux-x64@0.34.5':
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.34.5':
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-linuxmusl-x64@0.34.5':
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-win32-arm64@0.34.5':
resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [win32]
'@img/sharp-win32-x64@0.34.5':
resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [win32]
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
@@ -1345,6 +1303,10 @@ packages:
json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
json-schema-to-ts@3.1.1:
resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==}
engines: {node: '>=16'}
json-schema-traverse@1.0.0:
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
@@ -1744,6 +1706,9 @@ packages:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
ts-algebra@2.0.0:
resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==}
tsdown@0.21.5:
resolution: {integrity: sha512-TlgNhfPioAD6ECCUnZsxcUsXXuPPR4Rrxz3az741kL/M3oGIET4a9GajSNRNRx+jIva73TYUKQybrEPkDYN+fQ==}
engines: {node: '>=20.19.0'}
@@ -1933,19 +1898,53 @@ packages:
snapshots:
'@anthropic-ai/claude-agent-sdk@0.2.76(zod@4.3.6)':
'@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.140':
optional: true
'@anthropic-ai/claude-agent-sdk-darwin-x64@0.2.140':
optional: true
'@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.2.140':
optional: true
'@anthropic-ai/claude-agent-sdk-linux-arm64@0.2.140':
optional: true
'@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.2.140':
optional: true
'@anthropic-ai/claude-agent-sdk-linux-x64@0.2.140':
optional: true
'@anthropic-ai/claude-agent-sdk-win32-arm64@0.2.140':
optional: true
'@anthropic-ai/claude-agent-sdk-win32-x64@0.2.140':
optional: true
'@anthropic-ai/claude-agent-sdk@0.2.140(zod@4.3.6)':
dependencies:
'@anthropic-ai/sdk': 0.81.0(zod@4.3.6)
'@modelcontextprotocol/sdk': 1.29.0(zod@4.3.6)
zod: 4.3.6
optionalDependencies:
'@img/sharp-darwin-arm64': 0.34.5
'@img/sharp-darwin-x64': 0.34.5
'@img/sharp-linux-arm': 0.34.5
'@img/sharp-linux-arm64': 0.34.5
'@img/sharp-linux-x64': 0.34.5
'@img/sharp-linuxmusl-arm64': 0.34.5
'@img/sharp-linuxmusl-x64': 0.34.5
'@img/sharp-win32-arm64': 0.34.5
'@img/sharp-win32-x64': 0.34.5
'@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.2.140
'@anthropic-ai/claude-agent-sdk-darwin-x64': 0.2.140
'@anthropic-ai/claude-agent-sdk-linux-arm64': 0.2.140
'@anthropic-ai/claude-agent-sdk-linux-arm64-musl': 0.2.140
'@anthropic-ai/claude-agent-sdk-linux-x64': 0.2.140
'@anthropic-ai/claude-agent-sdk-linux-x64-musl': 0.2.140
'@anthropic-ai/claude-agent-sdk-win32-arm64': 0.2.140
'@anthropic-ai/claude-agent-sdk-win32-x64': 0.2.140
transitivePeerDependencies:
- '@cfworker/json-schema'
- supports-color
'@anthropic-ai/sdk@0.81.0(zod@4.3.6)':
dependencies:
json-schema-to-ts: 3.1.1
optionalDependencies:
zod: 4.3.6
'@babel/generator@8.0.0-rc.2':
dependencies:
@@ -1964,6 +1963,8 @@ snapshots:
dependencies:
'@babel/types': 8.0.0-rc.2
'@babel/runtime@7.29.2': {}
'@babel/types@8.0.0-rc.2':
dependencies:
'@babel/helper-string-parser': 8.0.0-rc.2
@@ -2045,68 +2046,6 @@ snapshots:
dependencies:
hono: 4.12.12
'@img/sharp-darwin-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.2.4
optional: true
'@img/sharp-darwin-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-darwin-x64': 1.2.4
optional: true
'@img/sharp-libvips-darwin-arm64@1.2.4':
optional: true
'@img/sharp-libvips-darwin-x64@1.2.4':
optional: true
'@img/sharp-libvips-linux-arm64@1.2.4':
optional: true
'@img/sharp-libvips-linux-arm@1.2.4':
optional: true
'@img/sharp-libvips-linux-x64@1.2.4':
optional: true
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
optional: true
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
optional: true
'@img/sharp-linux-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm64': 1.2.4
optional: true
'@img/sharp-linux-arm@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm': 1.2.4
optional: true
'@img/sharp-linux-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-x64': 1.2.4
optional: true
'@img/sharp-linuxmusl-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
optional: true
'@img/sharp-linuxmusl-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
optional: true
'@img/sharp-win32-arm64@0.34.5':
optional: true
'@img/sharp-win32-x64@0.34.5':
optional: true
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -3103,6 +3042,11 @@ snapshots:
json-parse-even-better-errors@2.3.1: {}
json-schema-to-ts@3.1.1:
dependencies:
'@babel/runtime': 7.29.2
ts-algebra: 2.0.0
json-schema-traverse@1.0.0: {}
json-schema-typed@8.0.2: {}
@@ -3530,6 +3474,8 @@ snapshots:
tree-kill@1.2.2: {}
ts-algebra@2.0.0: {}
tsdown@0.21.5(typescript@5.9.3):
dependencies:
ansis: 4.2.0
+1 -1
View File
@@ -2,4 +2,4 @@ packages:
- "apps/*"
catalog:
"@anthropic-ai/claude-agent-sdk": ^0.2.38
"@anthropic-ai/claude-agent-sdk": ^0.2.114