GitHub - shinydrift/salesforce-security-audit: Modular Salesforce org security audit tool — generates an HTML report across 6 security categories · GitHub
Skip to content

About

Modular Salesforce org security audit tool — generates an HTML report across 6 security categories

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

8 Commits

Folders and files

Repository files navigation

Salesforce Security Audit

A modular, extensible Python tool that audits a Salesforce org for security misconfigurations and generates a self-contained HTML report.

Features

  • 6 audit categories covering the most common Salesforce security risks
  • Two modes: live org (SOQL via Salesforce CLI) and offline metadata XML parsing
  • Single-file HTML report — severity scorecard, filterable findings, remediation guidance, print-friendly
  • Plugin architecture — add a new audit category by dropping one file into sf_audit/checkers/
  • No external dependencies — Python 3.9+ stdlib only
  • Standalone checkers — run any category in isolation, output as text or JSON

Prerequisites

Installation

git clone https://github.com/shinydrift/salesforce-security-audit.git
cd salesforce-security-audit
# No pip install needed — stdlib only

Quick Start

# Authenticate with Salesforce CLI (one-time)
sf org login web --alias my-sandbox

# Run a full audit against a connected org
python sf_security_audit.py --org my-sandbox

# Run against previously retrieved metadata
python sf_security_audit.py --metadata-dir ./force-app

# Best coverage: live org data + metadata XML
python sf_security_audit.py --org my-sandbox --metadata-dir ./force-app

The report is saved to audit-report.html by default.

Usage

usage: sf_security_audit [-h] [--org ORG] [--metadata-dir DIR] [--output FILE]
                         [--categories KEYS] [--list-categories]

options:
  --org, -o           Salesforce org alias or username
  --metadata-dir, -m  Path to retrieved Salesforce metadata XML
  --output, -r        Output HTML report path (default: audit-report.html)
  --categories, -c    Comma-separated category keys to run (default: all)
  --list-categories   List available audit categories and exit

Examples

# Audit specific categories only
python sf_security_audit.py --org my-sandbox --categories user_permissions,api_login

# List all available categories
python sf_security_audit.py --list-categories

# Run a single checker in isolation — text output
python -m sf_audit.checkers.sharing --org my-sandbox

# Run a single checker — JSON output (pipe into jq, CI scripts, etc.)
python -m sf_audit.checkers.connected_apps --metadata-dir ./force-app --format json

# Extract metadata first, then audit offline
sf project retrieve start \
  --metadata Profile,PermissionSet,SharingRules,ConnectedApp,SecuritySettings \
  --output-dir ./metadata --target-org my-sandbox
python sf_security_audit.py --metadata-dir ./metadata --output report.html

Audit Categories

Key Category Live Org Metadata XML
user_permissions User Permissions & Profiles ✓ ✓
sharing Sharing Rules & Org-Wide Defaults ✓ ✓
connected_apps Connected Apps & OAuth ✓ ✓
field_security Field-Level Security ✓ ✓
api_login API Access & Login History ✓ —
password_session Password & Session Policies ✓ ✓

What each category checks

User Permissions & Profiles

  • Profiles and custom permission sets with dangerous permissions: ModifyAllData, ViewAllData, ManageUsers, ManageEncryptionKeys, AuthorApex, and 15 others
  • Active users with no login in ≥90 days (stale accounts)
  • Permission set assignments granting elevated access

Sharing Rules & Org-Wide Defaults

  • Objects with Public Read/Write internal OWD (any user can edit any record)
  • Objects with Public Read/Write external sharing (exposes to guest users — critical)
  • Sharing rules that grant access to all internal users

Connected Apps & OAuth

  • Apps not restricted to admin-approved users
  • OAuth scopes including Full (complete API access) or RefreshToken (persistent offline access)
  • Missing IP range restrictions on OAuth callbacks

Field-Level Security

  • Fields with sensitive names (ssn, salary, password, credit_card, bank_account, dob, health, etc.) readable by many profiles or permission sets

API Access & Login History (live org only)

  • Standard users with API access enabled
  • Failed login attempts — 10+ per user flagged as possible brute force
  • MFA enforcement coverage across active users
  • Unusually high API call volumes (>5,000 calls/7 days)

Password & Session Policies

  • Minimum password length < 10
  • Weak complexity (NoRestriction or AlphaNumeric)
  • Non-expiring passwords or max age > 90 days
  • Session timeout > 4 hours
  • Sessions not locked on timeout
  • Profiles without IP login restrictions

Severity Levels

Level Meaning
🔴 Critical Immediate risk — data exposure, encryption key access, guest read/write
🟠 High Significant risk — privilege escalation, broad data access, no MFA
🟡 Medium Moderate risk — policy weaknesses, overly broad access
🔵 Low Minor risk — informational, best-practice gaps
⚪ Info No direct risk — items requiring manual verification

HTML Report

The generated report is a single self-contained HTML file with:

  • Severity scorecard at the top (Critical / High / Medium / Low / Info counts)
  • Filter buttons to show only findings of a given severity
  • Collapsible sections per audit category
  • Remediation guidance on every finding
  • Print-friendly layout (no external CDN dependencies)

Project Structure

sf_audit/
  base.py              ← Finding dataclass + BaseChecker ABC with shared helpers
  report.py            ← HTML report generator
  cli.py               ← Auto-discovers checkers, runs them, writes report
  checkers/
    __init__.py        ← pkgutil-based auto-discovery (discover())
    user_permissions.py
    sharing.py
    connected_apps.py
    field_security.py
    api_login.py
    password_session.py

sf_security_audit.py   ← Entry point (3 lines)
tests/
  test_checkers.py     ← 28 unit tests
.claude/skills/        ← AgentOS skill definitions

Adding a New Audit Category

  1. Create sf_audit/checkers/<name>.py:
from sf_audit.base import BaseChecker, Finding

class MyChecker(BaseChecker):
    category_key   = "my_category"     # used in --categories filter
    category_name  = "My Category"     # shown in the report
    category_emoji = "&#128270;"
    order          = 7                 # controls report section order

    def run(self) -> list[Finding]:
        if self.org_alias:
            # self._sf_query(soql) for live SOQL
            # self._sf_query(soql, tooling=True) for Tooling API
            pass
        if self.metadata_dir:
            # self._metadata_files("subdir", ".ext") + self._parse_xml(path)
            pass
        return self.findings
  1. (Optional) Create .claude/skills/sf-audit-<name>.md for direct AgentOS invocation.

  2. Done — discover() picks it up automatically. No changes to the orchestrator needed.

Running Tests

pip install pytest
pytest tests/ -v

28 tests covering: Finding validation, BaseChecker helpers (deduplication, Salesforce ID format), all 6 XML-mode checkers, auto-discovery, and --categories validation.

Security Notes

  • The tool is read-only — it never modifies org data
  • In --org mode, it issues SOQL queries and Tooling API reads only
  • Credentials are managed entirely by the Salesforce CLI (sf) — no secrets are stored by this tool
  • Salesforce IDs interpolated into SOQL are validated against the expected 15/18-character alphanumeric format before use

License

MIT

About

Modular Salesforce org security audit tool — generates an HTML report across 6 security categories

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages