Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Deployment Assessment Agent

Assess a newly deployed system on submission, identify what needs fixing, and open a single Jira ticket for it — automatically.

This is the intake-and-triage layer over the existing security agents. Someone submits a system that just went live; the agent routes it to the right engine, normalizes the findings, and files a ticket the owning team can act on.


Request flow

flowchart TD
    A[Manual submission<br/>name · type · target · owner] --> B{Route by system_type}
    B -->|code_repo| C[sast-agent<br/>static analysis]
    B -->|web_app| D[dast-agent<br/>dynamic pentest]
    B -->|kubernetes| E[kubernetes-audit-agent<br/>cluster audit]
    B -->|saas · extension · mcp · other| F[Control checklist<br/>type-specific]
    C --> G[Normalize findings]
    D --> G
    E --> G
    F --> G
    G --> H[Build one summary ticket]
    H --> I{Jira configured?}
    I -->|no| J[Dry-run:<br/>render ticket to disk]
    I -->|yes| K[Create Jira issue]
Loading

Submit a system, get an assessment and a ticket. Nothing is created in Jira unless you configure it — the default is a dry run that writes the exact ticket it would file.


How it assesses each system type

The design principle for v1 is reuse, not reinvention. The three scanning agents already do the hard part; this agent orchestrates them.

System type Engine What runs
code_repo sast sast-agent over the source path
web_app dast dast-agent against the URL (auth notes via --notes)
kubernetes k8s kubernetes-audit-agent against the kube-context
saas checklist SSO, token scope, data residency, vendor assurance, audit logging
browser_extension checklist permission scope, remote code, CSP, update channel
mcp checklist tool least-privilege, injection→tool escalation, auth/TLS, secret exposure
other checklist authn/authz, network exposure, logging baseline

The sibling agents run as subprocesses, not imports — each is a separate application with its own virtualenv and credentials. The boundary is a process, and it's injectable, so the orchestration is tested without spawning anything.

The checklist is honest

A purchased SaaS product has no code to scan and a browser extension needs review of its bundle, not a live pentest. For those, the agent emits a type-specific control checklist: each item is a control to verify, surfaced at low/medium/informational severity with the control as its remediation. Nothing in a checklist result claims a confirmed vulnerability — it flags what a human must check before the system is trusted.


Jira: dry-run by default

Ticketing is behind a small interface with two implementations:

  • DryRunJiraClient (default) — renders the exact ticket (summary, priority, full finding body) and writes it to outputs/<system>/jira-ticket-*.txt. Creates nothing. This is what runs with no configuration, so the pipeline is safe to demo and nothing appears in Jira by surprise.
  • HttpJiraClient — files a real issue via the Jira REST API. Enabled only when JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN, and JIRA_PROJECT_KEY are all set. Set JIRA_LIVE=1 to require it — the run fails loudly rather than silently dry-running if Jira is half-configured.

One ticket per assessment. Each assessed system produces one summary ticket; every finding is listed in the body, sorted worst-first, and the ticket priority tracks the highest severity found.


Usage

uv sync --locked

# SaaS product — runs a control checklist, renders a dry-run ticket
uv run --no-sync python main.py \
  --name "acme-analytics" --type saas --target "acme.com" --owner it-sec

# Web app — orchestrates dast-agent (needs dast-agent configured next door)
uv run --no-sync python main.py \
  --name "billing-ui" --type web_app --target "http://localhost:5173" \
  --notes "test account: user@example.com / <password>"

# Or submit a JSON file
uv run --no-sync python main.py --submission-file submission.json

submission.json:

{
  "name": "billing-ui",
  "system_type": "web_app",
  "target": "http://localhost:5173",
  "owner": "payments",
  "environment": "staging",
  "notes": "auth notes for the test account"
}

To file real tickets, copy .env.example to .env and set the JIRA_* variables. To orchestrate the scanning agents, check them out next to this repo (or set SAST_AGENT_DIR / DAST_AGENT_DIR / K8S_AGENT_DIR); each sibling needs its own .env to run.


Why uv and a committed lockfile

Dependencies are managed with uv and uv.lock is committed. The lockfile pins every transitive dependency to an exact version and a SHA-256 hash per artifact, so uv sync --locked installs the identical graph every time and refuses to run if the lockfile and pyproject.toml have drifted. Hash verification is on by default; CI fails if anything disables it. This is supply-chain hygiene: a re-resolved dependency graph is an unreviewed change, and the lockfile turns that into a diff you have to approve.


Security model

  • Least privilege. This agent files a ticket and shells out to the scanning agents; it holds no cluster or cloud credentials of its own. The sibling agents own their own scopes and secrets.
  • No secrets in tickets. The ticket body carries findings and remediation, never credentials. Jira auth uses an API token read from the environment.
  • Dry-run by default. Ticket creation is opt-in. The agent will not write to Jira unless you configure it.
  • Findings are advisory. Output is automated and must be validated by a human before it drives remediation — the summary and every ticket say so.

Tests

uv run --no-sync ruff check .
uv run --no-sync pytest -q

Covers severity normalization and result aggregation, report parsing for all three sibling formats, subprocess orchestration (mocked runner), the checklist assessors, routing, ticket construction, dry-run/HTTP client selection, and an end-to-end run through the checklist path.


Limitations

  • v1 orchestrates; it does not deep-scan SaaS/extensions/MCP itself. Those fall back to a control checklist. A later drop-in could add a static analyzer for extension bundles or an MCP tool-permission scanner behind the same Assessor interface.
  • Sibling agents must be runnable. Orchestrating sast/dast/k8s requires each to be checked out and configured (API keys, targets). Where one isn't available, that assessment fails with a clear error rather than a silent pass.
  • Manual submission only. The trigger is a CLI submission. A CI/deploy webhook or discovery scan would be a thin layer over the same run() entry point.
  • Jira only. Ticketing targets Jira. Another tracker would be a new JiraClient-shaped implementation behind the same interface.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages