mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-05-17 22:54:46 +02:00
feat: add git awareness and optional description field to config
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 <filepath>` — 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.
|
||||
</critical>
|
||||
|
||||
{{DESCRIPTION}}
|
||||
|
||||
<system_architecture>
|
||||
**PENTESTING WORKFLOW - YOUR POSITION:**
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ Your analysis must begin by reading and fully comprehending the initial intellig
|
||||
|
||||
<target>
|
||||
URL: {{WEB_URL}}
|
||||
{{DESCRIPTION}}
|
||||
</target>
|
||||
|
||||
<rules>
|
||||
|
||||
@@ -21,6 +21,7 @@ IMPORTANT: You are MODIFYING an existing file, not creating a new one.
|
||||
|
||||
<target>
|
||||
URL: {{WEB_URL}}
|
||||
{{DESCRIPTION}}
|
||||
</target>
|
||||
|
||||
<context>
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user