Skip to content

Add continuous autonomous security testing framework (v3.0)#35

Merged
devatsecure merged 3 commits intomainfrom
claude/add-security-testing-guide-BClsS
Mar 4, 2026
Merged

Add continuous autonomous security testing framework (v3.0)#35
devatsecure merged 3 commits intomainfrom
claude/add-security-testing-guide-BClsS

Conversation

@devatsecure
Copy link
Owner

@devatsecure devatsecure commented Mar 4, 2026

Description

This PR introduces a comprehensive continuous autonomous security testing framework that closes the gap between periodic security validation and every-deploy security coverage. It adds five new core modules and supporting infrastructure to enable diff-aware scanning, automated fix generation with PR creation, persistent findings tracking, and LLM-powered vulnerability chain discovery.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Changes Made

Core Modules Added

  1. scripts/diff_impact_analyzer.py — Diff-intelligent scanner scoping

    • DiffClassifier: Classifies changed files as security-relevant or skippable using pattern matching
    • DiffImpactAnalyzer: Expands changed files to their security blast radius via reverse dependency lookup
    • DiffScopeBuilder: Combines classification and impact analysis into scanner-ready scopes with Semgrep CLI helpers
    • Enables focused scanning on only changed files and their dependents, reducing scan time and noise
  2. scripts/autofix_pr_generator.py — Automated PR generation from remediation suggestions

    • AutoFixPRGenerator: Creates git branches, applies code fixes (diff or full-file replacement), commits with descriptive messages
    • ClosedLoopOrchestrator: Orchestrates find → fix → verify → PR cycle with confidence-based filtering
    • FixBranch, FixPR, LoopResult: Dataclasses for structured results and JSON serialization
    • Generates merge-ready PRs with formatted bodies containing vulnerability context
  3. scripts/findings_store.py — Persistent SQLite-backed findings database

    • Cross-scan deduplication via content-based fingerprinting
    • Automatic regression detection (previously fixed findings that reappear)
    • Severity trend analytics and mean-time-to-fix metrics
    • Historical context injection for LLM enrichment
    • Thread-safe write operations with reentrant locking
  4. scripts/app_context_builder.py — Unified application context model

    • Inspects project structure, dependencies, imports, and infrastructure configuration
    • Detects framework, language, auth mechanisms, API endpoints, middleware chains
    • Identifies cloud provider, IaC files, Docker/Kubernetes presence
    • Provides context to all pipeline phases for stack-aware scanning and enrichment
    • Fast detection with file-count caps and early exits
  5. scripts/agent_chain_discovery.py — LLM-powered vulnerability chain discovery

    • Complements rule-based VulnerabilityChainer with AI-driven multi-step attack reasoning
    • AgentChainDiscovery: Uses LLM to discover novel attack paths beyond static rules
    • CrossComponentAnalyzer: Identifies inter-module vulnerability combinations
    • AttackChain, CrossComponentRisk: Structured dataclasses for chain results
    • Batch processing with configurable limits to control LLM costs

Supporting Infrastructure

  • scripts/sast_dast_validator.py — SAST-to-DAST validation bridge

    • Generates targeted HTTP tests from SAST findings against live targets
    • Validates exploitability in running applications (staging/preview/dev)
    • Safety guards: blocks production by default, rejects private IP ranges, truncates responses
    • Payload libraries for SQL injection, XSS, SSRF, path traversal, command injection
  • GitHub Actions Workflows:

    • .github/workflows/argus-retest.yml: Automatically retests after fix PRs are merged
    • .github/workflows/post-deploy-scan.yml: Triggers security validation on deployment success
  • Configuration: Extended scripts/config_loader.py with toggles for all v3.0 features

    • enable_diff_scoping, enable_findings_store, enable_app_context, enable_agent_chain_discovery, etc.
  • Documentation:

    • docs/CONTINUOUS_SECURITY_TESTING_GUIDE.md: Comprehensive guide mapping current capabilities, gaps, and implementation paths
    • Updated README.md, `CHANGELOG.

https://claude.ai/code/session_017NQsm2eBxfioLrad1C7keZ


Note

Cursor Bugbot is generating a summary for commit c235c1e. Configure here.

claude added 3 commits March 4, 2026 05:39
Maps Argus's current capabilities against the emerging continuous
autonomous pentesting model (diff-aware scanning, AutoFix→PR→Retest
loops, persistent knowledge base, agent-driven attack chaining,
deployment-triggered scanning, code-to-runtime context). Includes
concrete implementation paths and priority ordering for each gap.

https://claude.ai/code/session_017NQsm2eBxfioLrad1C7keZ
Implements continuous autonomous security testing capabilities:

- diff_impact_analyzer: Diff-intelligent scanner scoping with blast radius
  expansion via reverse dependency lookup
- agent_chain_discovery: LLM-powered multi-step attack chain discovery
  with cross-component vulnerability analysis
- autofix_pr_generator: AutoFix PR generation with closed-loop
  find→fix→verify orchestration
- findings_store: SQLite-backed persistent findings with regression
  detection, MTTF, and historical context for LLM prompts
- app_context_builder: Auto-detects framework, language, auth, cloud
  provider, IaC, middleware, and entry points for context-aware scanning
- sast_dast_validator: SAST-to-DAST live validation with safety guards
  against production targets
- GitHub Actions workflows for post-deploy scanning and automated retest

Adds 13 config keys, integrates all modules into hybrid_analyzer.py
pipeline, and includes 36 passing tests.

https://claude.ai/code/session_017NQsm2eBxfioLrad1C7keZ
- README: Add v3.0 continuous security testing feature table, env vars,
  deployment-triggered scanning section, and guide doc link
- CLAUDE.md: Add v3.0 summary, 6 new key files, and guide reference
- CHANGELOG: Add v6.0.0 release notes with all 7 new modules,
  workflows, config keys, and 36 tests

https://claude.ai/code/session_017NQsm2eBxfioLrad1C7keZ
@devatsecure devatsecure merged commit ea79556 into main Mar 4, 2026
16 of 39 checks passed
@github-actions
Copy link

github-actions bot commented Mar 4, 2026

✅ Hybrid Security Scan Results

Status: No critical or high severity issues

📊 Findings Summary

Severity Count
🔴 Critical
🟠 High
🟡 Medium
🟢 Low
📈 Total ****

🛠️ Tools Used

  • ✅ Semgrep (SAST)
  • ✅ Trivy (CVE Scanning)

📈 Metrics

  • ⏱️ Scan Duration: s
  • 💰 Cost: $

🔗 Links


Powered by Argus Hybrid Analyzer

Comment on lines +32 to +41
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
# Extract vuln type and finding ID from branch name: argus/fix-{type}-{id}
VULN_TYPE=$(echo "$BRANCH" | sed 's|argus/fix-||' | sed 's|-[a-f0-9]*$||')
FINDING_ID=$(echo "$BRANCH" | grep -oP '[a-f0-9]{8}$' || echo "unknown")
echo "vuln_type=$VULN_TYPE" >> $GITHUB_OUTPUT
echo "finding_id=$FINDING_ID" >> $GITHUB_OUTPUT
# Get changed files from the PR
CHANGED_FILES=$(gh pr view ${{ github.event.pull_request.number }} --json files -q '.files[].path' || echo "")
echo "changed_files=$CHANGED_FILES" >> $GITHUB_OUTPUT

Check failure

Code scanning / Semgrep OSS

Semgrep Finding: yaml.github-actions.security.run-shell-injection.run-shell-injection Error

Using variable interpolation ${...} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
Comment on lines +100 to +124
script: |
const regression = '${{ steps.regression.outcome }}';
const rescan = '${{ steps.rescan.outcome }}';
const allPassed = regression === 'success' && rescan === 'success';

const body = `## Argus Retest Results

| Check | Status |
|-------|--------|
| Regression Tests | ${regression === 'success' ? 'Passed' : 'Failed'} |
| SAST Rescan | ${rescan === 'success' ? 'Clean' : 'Issues found'} |
| **Overall** | **${allPassed ? 'Fix Verified' : 'Needs Review'}** |

${allPassed ? 'The fix has been verified. The vulnerability is confirmed resolved.' : 'The retest found issues. Please review the scan results.'}

---
*Argus Security Retest — triggered by merge of \`${{ github.event.pull_request.head.ref }}\`*`;

// Comment on the merged PR
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ github.event.pull_request.number }},
body: body
});

Check failure

Code scanning / Semgrep OSS

Semgrep Finding: yaml.github-actions.security.github-script-injection.github-script-injection Error

Using variable interpolation ${...} with github context data in a actions/github-script's script: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
Comment on lines +42 to +55
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "target_url=${{ inputs.target_url }}" >> $GITHUB_OUTPUT
echo "environment=${{ inputs.environment }}" >> $GITHUB_OUTPUT
else
echo "target_url=${{ github.event.deployment.payload.web_url || '' }}" >> $GITHUB_OUTPUT
echo "environment=${{ github.event.deployment.environment }}" >> $GITHUB_OUTPUT
fi
# Get diff since last successful scan
PREV_SHA=$(git log --format='%H' -2 | tail -1)
echo "prev_sha=$PREV_SHA" >> $GITHUB_OUTPUT
CHANGED=$(git diff --name-only $PREV_SHA HEAD | head -100)
echo "has_changes=$( [ -n "$CHANGED" ] && echo true || echo false )" >> $GITHUB_OUTPUT

Check failure

Code scanning / Semgrep OSS

Semgrep Finding: yaml.github-actions.security.run-shell-injection.run-shell-injection Error

Using variable interpolation ${...} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
Comment on lines +618 to +622
response = urllib.request.urlopen(
request,
timeout=self.timeout,
context=ctx,
)

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected Warning

Detected a dynamic value being used with urllib. urllib supports 'file://' schemes, so a dynamic value controlled by a malicious actor may allow them to read arbitrary files. Audit uses of urllib calls to ensure user data cannot control the URLs, or consider using the 'requests' library instead.
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 4 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

max_duration=600,
)
orch = DASTOrchestrator(config=config)
results = orch.run('${{ steps.context.outputs.target_url }}')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Script injection via target URL in workflow

High Severity

The ${{ steps.context.outputs.target_url }} is interpolated directly into an inline Python string on line 86. If the URL contains a single quote (e.g., from workflow_dispatch user input or a crafted deployment payload), it breaks out of the Python string literal, enabling arbitrary code execution in the workflow runner. This value originates from ${{ inputs.target_url }} which is directly user-controlled.

Additional Locations (1)

Fix in Cursor Fix in Web

- name: Extract fix metadata
id: meta
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shell injection via branch ref in workflow

High Severity

${{ github.event.pull_request.head.ref }} is interpolated directly into a shell script. While the if condition ensures the branch starts with argus/fix-, the remainder is attacker-controlled. A branch name containing shell metacharacters like $(cmd) or backticks would execute arbitrary commands during the run step, potentially exfiltrating secrets like ANTHROPIC_API_KEY or GITHUB_TOKEN.

Fix in Cursor Fix in Web


def __init__(self, db_path: str = ".argus/findings.db") -> None:
self.db_path = db_path
self._lock = threading.Lock()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lock advertised as reentrant but uses non-reentrant Lock

Low Severity

The module docstring (line 16) states "Thread-safe write operations with a reentrant lock" but the implementation uses threading.Lock(), which is non-reentrant. If any future code path (or subclass) attempts to re-acquire the lock from within a locked section, it will deadlock. The type needs to match the documented contract — either use threading.RLock() or correct the docstring.

Fix in Cursor Fix in Web

row = cur.fetchone()
if row is None:
return False
return row["status"] == "fixed"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regression detection returns stale result after record_scan

Medium Severity

is_regression checks whether the finding's current status equals "fixed". But record_scan resets regressions' status to "open" immediately upon detection. So get_historical_context calling is_regression after record_scan will always return False for regressions, since their status was already flipped to "open". The method needs to check fix_history records rather than relying on transient status.

Additional Locations (1)

Fix in Cursor Fix in Web

devatsecure pushed a commit that referenced this pull request Mar 4, 2026
…eview

- Sanitize ${{ }} expression interpolation in post-deploy-scan.yml and
  argus-retest.yml by passing attacker-controlled values through env vars
  instead of direct shell/script interpolation (HIGH severity)
- Fix is_regression() returning stale results by checking fix_history
  records instead of transient status field (MEDIUM)
- Change threading.Lock() to threading.RLock() to match docstring (LOW)

https://claude.ai/code/session_017NQsm2eBxfioLrad1C7keZ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants