From 8f795f6dca53e9f15b8962faeed2a4fc60e589a3 Mon Sep 17 00:00:00 2001 From: ezl-keygraph Date: Sun, 22 Mar 2026 21:25:13 +0530 Subject: [PATCH] feat: add git awareness and optional description field to config --- README.md | 3 +++ apps/cli/src/home.ts | 1 - apps/worker/configs/config-schema.json | 14 +++++++++++++- apps/worker/configs/example-config.yaml | 3 +++ apps/worker/prompts/pre-recon-code.txt | 5 +++++ apps/worker/prompts/recon.txt | 1 + apps/worker/prompts/report-executive.txt | 1 + apps/worker/src/config-parser.ts | 20 ++++++++++++++++++-- apps/worker/src/services/prompt-manager.ts | 3 ++- apps/worker/src/types/config.ts | 2 ++ 10 files changed, 48 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 03ea56c..d237130 100644 --- a/README.md +++ b/README.md @@ -379,6 +379,9 @@ cp configs/example-config.yaml ./my-app-config.yaml ##### Basic Configuration Structure ```yaml +# Optional: describe your target environment (max 500 chars) +description: "Next.js e-commerce app on PostgreSQL. Local dev environment — .env files contain local-only credentials, not deployed to production." + authentication: login_type: form login_url: "https://your-app.com/login" diff --git a/apps/cli/src/home.ts b/apps/cli/src/home.ts index ed16eb4..b8c979e 100644 --- a/apps/cli/src/home.ts +++ b/apps/cli/src/home.ts @@ -37,7 +37,6 @@ export function getCredentialsPath(): string { return path.join(SHANNON_HOME, 'google-sa-key.json'); } - /** * Initialize state directories. * Local mode: creates ./workspaces/ and ./credentials/ diff --git a/apps/worker/configs/config-schema.json b/apps/worker/configs/config-schema.json index dd38eac..757f083 100644 --- a/apps/worker/configs/config-schema.json +++ b/apps/worker/configs/config-schema.json @@ -122,9 +122,21 @@ "type": "object", "description": "Deprecated: Use 'authentication' section instead", "deprecated": true + }, + "description": { + "type": "string", + "description": "Description of the target environment, its deployment context, and any information that helps guide the security assessment", + "minLength": 1, + "maxLength": 500, + "pattern": "\\S" } }, - "anyOf": [{ "required": ["authentication"] }, { "required": ["rules"] }, { "required": ["authentication", "rules"] }], + "anyOf": [ + { "required": ["authentication"] }, + { "required": ["rules"] }, + { "required": ["authentication", "rules"] }, + { "required": ["description"] } + ], "additionalProperties": false, "$defs": { "rule": { diff --git a/apps/worker/configs/example-config.yaml b/apps/worker/configs/example-config.yaml index b78d9ba..e46e8e6 100644 --- a/apps/worker/configs/example-config.yaml +++ b/apps/worker/configs/example-config.yaml @@ -1,6 +1,9 @@ # Example configuration file for pentest-agent # Copy this file and modify it for your specific testing needs +# Description of the target environment (optional, max 500 chars) +description: "Next.js e-commerce app on PostgreSQL. Local dev environment — .env files contain local-only credentials, not deployed to production." + authentication: login_type: form # Options: 'form' or 'sso' login_url: "https://example.com/login" diff --git a/apps/worker/prompts/pre-recon-code.txt b/apps/worker/prompts/pre-recon-code.txt index 29d1eb4..981b780 100644 --- a/apps/worker/prompts/pre-recon-code.txt +++ b/apps/worker/prompts/pre-recon-code.txt @@ -19,8 +19,13 @@ Objective: Your task is to analyze the provided source code to generate a securi - Include specific examples from the code when discussing security concerns - At the end of your report, you MUST include a section listing all the critical file paths mentioned in your analysis. - **MANDATORY:** You MUST save your complete analysis report using the `save-deliverable` CLI tool with --type CODE_ANALYSIS. + +**GIT AWARENESS:** +Read `.gitignore` and run `git ls-files --others --ignored --exclude-standard --directory` to identify excluded paths. To check a specific file, use `git ls-files ` — output means tracked, empty means untracked. Only flag tracked files as vulnerabilities. Untracked files relevant to security (e.g., secrets, credentials, sensitive configs) may be noted as informational. +{{DESCRIPTION}} + **PENTESTING WORKFLOW - YOUR POSITION:** diff --git a/apps/worker/prompts/recon.txt b/apps/worker/prompts/recon.txt index 15bb355..5407fcb 100644 --- a/apps/worker/prompts/recon.txt +++ b/apps/worker/prompts/recon.txt @@ -12,6 +12,7 @@ Your analysis must begin by reading and fully comprehending the initial intellig URL: {{WEB_URL}} +{{DESCRIPTION}} diff --git a/apps/worker/prompts/report-executive.txt b/apps/worker/prompts/report-executive.txt index 6dcca3a..0dddaa4 100644 --- a/apps/worker/prompts/report-executive.txt +++ b/apps/worker/prompts/report-executive.txt @@ -21,6 +21,7 @@ IMPORTANT: You are MODIFYING an existing file, not creating a new one. URL: {{WEB_URL}} +{{DESCRIPTION}} diff --git a/apps/worker/src/config-parser.ts b/apps/worker/src/config-parser.ts index acbf5be..437eefc 100644 --- a/apps/worker/src/config-parser.ts +++ b/apps/worker/src/config-parser.ts @@ -294,9 +294,9 @@ const validateConfig = (config: Config): void => { performSecurityValidation(config); - if (!config.rules && !config.authentication) { + if (!config.rules && !config.authentication && !config.description) { console.warn( - '⚠️ Configuration file contains no rules or authentication. The pentest will run without any scoping restrictions or login capabilities.', + '⚠️ Configuration file contains no rules, authentication, or description. The pentest will run without any scoping restrictions or login capabilities.', ); } else if (config.rules && !config.rules.avoid && !config.rules.focus) { console.warn('⚠️ Configuration file contains no rules. The pentest will run without any scoping restrictions.'); @@ -370,6 +370,20 @@ const performSecurityValidation = (config: Config): void => { checkForDuplicates(config.rules.focus || [], 'focus'); checkForConflicts(config.rules.avoid, config.rules.focus); } + + if (config.description) { + for (const pattern of DANGEROUS_PATTERNS) { + if (pattern.test(config.description)) { + throw new PentestError( + `description contains potentially dangerous pattern: ${pattern.source}`, + 'config', + false, + { field: 'description', pattern: pattern.source }, + ErrorCode.CONFIG_VALIDATION_FAILED, + ); + } + } + } }; const validateRulesSecurity = (rules: Rule[] | undefined, ruleType: string): void => { @@ -527,11 +541,13 @@ export const distributeConfig = (config: Config | null): DistributedConfig => { const avoid = config?.rules?.avoid || []; const focus = config?.rules?.focus || []; const authentication = config?.authentication || null; + const description = config?.description?.trim() || ''; return { avoid: avoid.map(sanitizeRule), focus: focus.map(sanitizeRule), authentication: authentication ? sanitizeAuthentication(authentication) : null, + description, }; }; diff --git a/apps/worker/src/services/prompt-manager.ts b/apps/worker/src/services/prompt-manager.ts index 70fb99d..3e629c3 100644 --- a/apps/worker/src/services/prompt-manager.ts +++ b/apps/worker/src/services/prompt-manager.ts @@ -167,7 +167,8 @@ async function interpolateVariables( .replace(/{{WEB_URL}}/g, variables.webUrl) .replace(/{{REPO_PATH}}/g, variables.repoPath) .replace(/{{PLAYWRIGHT_SESSION}}/g, variables.PLAYWRIGHT_SESSION || 'agent1') - .replace(/{{AUTH_CONTEXT}}/g, buildAuthContext(config)); + .replace(/{{AUTH_CONTEXT}}/g, buildAuthContext(config)) + .replace(/{{DESCRIPTION}}/g, config?.description ? `Description: ${config.description}` : ''); if (config) { // Handle rules section - if both are empty, use cleaner messaging diff --git a/apps/worker/src/types/config.ts b/apps/worker/src/types/config.ts index 4965e68..b117387 100644 --- a/apps/worker/src/types/config.ts +++ b/apps/worker/src/types/config.ts @@ -46,6 +46,7 @@ export interface Config { rules?: Rules; authentication?: Authentication; pipeline?: PipelineConfig; + description?: string; } export type RetryPreset = 'default' | 'subscription'; @@ -59,4 +60,5 @@ export interface DistributedConfig { avoid: Rule[]; focus: Rule[]; authentication: Authentication | null; + description: string; }