Skip to main content

Python SDK for the AttackForge SSAPI

Project description

PyAttackForge

Next-generation Python SDK for the AttackForge SSAPI (Python 3.10+).

AI Documentation

DOCUMENTATION.md is written for AI coding assistants (Codex/Claude) to implement or extend the library.

Install (local)

pip install -e .

Install (PyPI)

pip install pyattackforge

Build

python -m build --sdist --wheel

Configuration

Environment variables:

  • ATTACKFORGE_BASE_URL
  • ATTACKFORGE_API_KEY
  • ATTACKFORGE_TEST_PROJECT_ID (only needed for live integration tests)
  • ATTACKFORGE_FINDINGS_VISIBLE_DEFAULT (optional, set to true to make new findings visible; default is pending/hidden)
  • ATTACKFORGE_FINDINGS_SUBSTATUS_KEY (optional, default substatus)
  • ATTACKFORGE_FINDINGS_SUBSTATUS_VALUE (optional, default Observed)
  • ATTACKFORGE_UI_BASE_URL (optional, UI base URL for project testcase uploads/verification)
  • ATTACKFORGE_UI_TOKEN (optional, UI authorization token for project testcase uploads/verification)

Example .env:

ATTACKFORGE_BASE_URL=https://demo.attackforge.com
ATTACKFORGE_API_KEY=replace-me
ATTACKFORGE_TEST_PROJECT_ID=replace-me
ATTACKFORGE_FINDINGS_VISIBLE_DEFAULT=false
ATTACKFORGE_FINDINGS_SUBSTATUS_KEY=substatus
ATTACKFORGE_FINDINGS_SUBSTATUS_VALUE=Observed
ATTACKFORGE_UI_BASE_URL=https://demo.attackforge.com
ATTACKFORGE_UI_TOKEN=replace-me

Usage (sync)

from pyattackforge import AttackForgeClient

with AttackForgeClient() as client:
    projects = client.projects.get_projects()
    print(projects)

Touch a testcase (updates last_tested and testcase_type in project_testcase_custom_fields):

from pyattackforge import AttackForgeClient

with AttackForgeClient() as client:
    client.testcases.touch_testcase("project_id", "testcase_id")

By default, the SDK merges last_tested and testcase_type into existing project testcase custom fields. Use overwrite=True to replace the list. Default format for last_tested is YYYY-MM-DD (date picker friendly). Override by supplying timestamp=. Default testcase_type is Security Test Case. Override by supplying testcase_type=.

Create a testcase note with optional deduplication (case-insensitive, trimmed):

from pyattackforge import AttackForgeClient

with AttackForgeClient() as client:
    payload = {"note": "Observed weak password policy", "note_type": "PLAINTEXT"}
    client.testcases.create_testcase_note("project_id", "testcase_id", payload, dedupe=True)

When dedupe=True, the SDK compares against notes returned by the project testcase listing. If notes are not included in that response, the check is best-effort and the note will be created. If a UI token is configured (ATTACKFORGE_UI_TOKEN), the SDK will also check the UI notes endpoint to avoid duplicates.

Upload vulnerability evidence with FIFO retention and dedupe:

from pyattackforge import AttackForgeClient

with AttackForgeClient() as client:
    client.findings.upload_vulnerability_evidence("vuln_id", "evidence.png")
    # keep_last defaults to 2 (FIFO, keep most recent). Set keep_last=None to disable.
    client.findings.upload_vulnerability_evidence("vuln_id", "evidence.png", dedupe=True)

For more reliable FIFO/dedupe, pass project_id so the SDK can use the project vulnerability listing (which contains evidence metadata):

client.findings.upload_vulnerability_evidence("vuln_id", "evidence.png", project_id="project_id")

Upload project testcase evidence with FIFO retention and dedupe:

from pyattackforge import AttackForgeClient

with AttackForgeClient() as client:
    client.testcases.upload_testcase_file("project_id", "testcase_id", "evidence.png")
    # keep_last defaults to 2 (FIFO, keep most recent). Set keep_last=None to disable.
    client.testcases.upload_testcase_file("project_id", "testcase_id", "evidence.png", dedupe=True)

When a UI token is configured, FIFO cleanup for testcase evidence uses the UI delete endpoint: /api/projects/:projectId/meta/:fileId/delete (UI expects GET/POST semantics).

Helper methods (examples):

with AttackForgeClient() as client:
    project = client.projects.find_project_by_name("Tantalum Labs Fake Pentest")
    suite = client.testsuites.find_testsuite_by_name("OWASP Web App Penetration Test")
    if suite:
        testcases = client.testsuites.get_testsuite_testcases(suite["id"])
    client.link_vulnerability_to_testcases("project_id", "vuln_id", ["testcase_id"])

Group management (examples):

from pyattackforge import AttackForgeClient

with AttackForgeClient() as client:
    group = client.groups.create_group({
        "name": "SDK Group",
        "group_owner": "Owner Name",
        "primary_contact_name": "Owner Name",
        "primary_contact_email": "owner@example.com",
        "primary_contact_number": "0000000000",
    })
    group_id = group.get("group_id") or group.get("id")
    client.projects.add_project_to_group("project_id", group_id)
    client.groups.get_group_projects(group_id)
    client.groups.get_group_vulnerabilities(group_id)

Testing

Unit tests:

python3 -m pytest

Integration tests (require env vars):

python3 -m pytest -m integration

Integration tests create and modify data in the target tenant and will attempt cleanup. They read ATTACKFORGE_BASE_URL, ATTACKFORGE_API_KEY, and ATTACKFORGE_TEST_PROJECT_ID.

Status

This is a from-scratch rewrite. See COVERAGE.md for endpoint coverage and assumptions.

Scripts

Import writeups from a JSON export:

python3 scripts/import_writeups.py --input writeups.json

By default the script will ensure custom libraries exist. If the SSAPI returns an error for a custom library key, it will create a small bootstrap writeup in that library. Use --no-ensure-library to skip.

Add missing writeup custom fields (Settings -> Writeups) based on the import file:

python3 scripts/import_writeups.py --input writeups.json --ensure-writeup-fields

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyattackforge-0.2.4.tar.gz (63.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyattackforge-0.2.4-py3-none-any.whl (53.3 kB view details)

Uploaded Python 3

File details

Details for the file pyattackforge-0.2.4.tar.gz.

File metadata

  • Download URL: pyattackforge-0.2.4.tar.gz
  • Upload date:
  • Size: 63.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for pyattackforge-0.2.4.tar.gz
Algorithm Hash digest
SHA256 1bc805cb5e530891f9c13e793a842d599172469ad94382610085ada8b20b5f20
MD5 9ec5e3ae5b81cd55d8c0ab243ea5a55e
BLAKE2b-256 3d66fed943ab7fab6655ca21e54d75b5b36a99249cf26c73ebfc2c661b87d78c

See more details on using hashes here.

File details

Details for the file pyattackforge-0.2.4-py3-none-any.whl.

File metadata

  • Download URL: pyattackforge-0.2.4-py3-none-any.whl
  • Upload date:
  • Size: 53.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for pyattackforge-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 bb1a9082d594c60b2174b4e8e92307d2194a8e276b6b9f10f1dcf003879f89df
MD5 0e06b622ea9d2b8ca1a09200404108f8
BLAKE2b-256 fed24ea227380112e61ac022c5de47aeb7109a22ccf7fcfd4071df064cbae270

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page