You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Agentless security auditing for SAP S/4HANA RISE, ECS, ECC and BTP Offline by default · optional read-only connectors · nothing ever installed in the SAP system · no RFC user · nothing is ever written back
This repository is public so that the work can be read, reviewed and
evaluated. That is the whole of the permission granted.
You may: read the source, review the approach, cite it with attribution.
You may not: run, copy, fork, modify, redistribute, self-host, or use it or
any part of it in your own product or service — commercial or otherwise —
without prior written permission.
Public visibility is not a licence. Neither is the absence of a technical
barrier. If you are unsure whether what you have in mind is permitted, assume it
is not and ask — permission is usually easy to obtain and always cheaper than
the alternative.
SAP S/4HANA RISE Security Scanner analyzes exported SAP configuration data (CSV/JSON) and reports findings, severity ratings, risk prioritization, compliance mapping and actionable remediation.
It runs in two modes that share one scanner core:
CLI(stdlib only)
Server(client-server)
Input
--data-dir of exports
Browser upload, or the same directory
Output
HTML · PDF · PPTX
Interactive web console + JSON API
State
Single-shot, stateless
PostgreSQL — findings persist across uploads
Use it for
Air-gapped review, one-off assessment
Continuous tracking of the mitigation journey
No direct system connection required — offline & agentless by default. Nothing is ever installed in the SAP system and no RFC user is created, in either mode.
Connected mode is optional and separately invoked.python -m collect … reads from a system you authorise and writes the same export files the offline path consumes — read-only, enforced in the transport rather than promised. The scanner itself still connects to nothing. See Connected mode. In RISE, third-party ABAP add-ons are an Excluded Task requiring an additional SKU and a multi-week evaluation; an export bundle needs none of that.
~600 security checks across 30 audit modules — ABAP authorizations, HANA DB, BTP/Cloud, GRC Access Control, SOX financial-config controls, permission-level Segregation of Duties, and a custom-code scanner. Precisely: 363 check IDs are written as literals and 621 exist once the five runtime-generated families (profile parameters, ABAP rules, SoD risks, ATC families) resolve against their shipped rulesets.
Complete against SAP's mandatory ECS baseline — 92 of 92 profile parameters from SAP Note 3250501 (the hardening requirements SAP makes mandatory for AS ABAP in Enterprise Cloud Services), plus its configuration half. Every value is read from a recorded extract of the note, never hand-typed, because a transcription typo tells a customer they are compliant when they are not.
Deployment-aware — --deployment-mode decides what compliant means. snc/accept_insecure_gui = 1 is SAP's own mandated value in ECS, rfc/callback_security_method = 1 is a documented exception SAP permits (the ECS standard is 3), and an unlocked DDIC is explicitly not required to be locked. All three are findings on classic on-premise ABAP. A RISE-specific scanner that flags SAP's own baseline is confidently wrong on every compliant system.
Custom code (CVA) — 133 rules dispatched by file type (118 ABAP/CDS/RAP, 7 JavaScript/UI5, 8 BTP descriptor) over a statement-level lexer with intra-procedural taint analysis, so a finding is graded confirmed / tentative / pattern-only rather than asserted. ABAP statements end at a period and span lines; matching them one line at a time loses real injections and invents false ones.
A release gate, not just a report — --gate exits non-zero when a change would make things worse, so the scanner can sit in a pipeline. Judges the delta against a baseline, scopes to the objects a transport touches, never blocks on a finding the customer cannot fix, and never fails open: degraded coverage is "could not assess", never "pass".
Stable finding identity — every finding is fingerprinted from the concrete SAP objects it names, so it matches itself across re-uploads. That is what makes remediation tracking, aging and MTTR possible rather than approximate.
Risk-prioritized (P1–P4) — ranked by severity × exploitability × exposure × privilege, with the contributing factors shown. Works on findings CVSS cannot score at all.
Compliance mapping — ISO/IEC 27001:2022, NIST SP 800-53 Rev 5, NIST CSF 2.0, CIS Controls v8, DORA (EU 2022/2554), TISAX/VDA ISA, SOC 2, EU GDPR. DORA is mapped to named requirement areas, not article numbers: an auditor reading a citation expects the sub-paragraph to say what we imply it says.
Cyber-risk quantification (FAIR) — a dollar-denominated Annualised Loss Exposure and loss-exceedance curve from a bundled Monte-Carlo engine, so the board sees financial risk rather than a severity count. On the CLI via --crq; in the server it runs on every scan and lands on the dashboard. Priced on the complete, unfiltered finding set — the input count is stored beside the figure, so a display filter can never move the number — with the unattributed count disclosed rather than hidden.
RISE-aware — findings carry a remediation owner. In RISE a customer can see a bad profile parameter and cannot change it, so those findings render as a pre-drafted service request to SAP, never as "change this".
Standards-aligned — CIS SAP Benchmark, DSAG best-practice guide, SAP Security Baseline
Pipeline:LOAD CSV/JSON exports → MODULES (30 auditors) → CHECKS (~600 rules) → RANK by severity & P1–P4 priority → MAP to compliance frameworks → (optional)QUANTIFY FAIR loss exposure ($) → REPORT (HTML · PDF · PPTX) orSTORE (PostgreSQL → web console, run-over-run diff, graph nodes).
A note on dependencies. The CLI still runs on the Python standard library alone — the HTML, PDF and PPTX engines are all hand-built. The server tier deliberately ends that rule: a browser console and a durable finding store cannot be built on the stdlib. The discipline that replaces it is a single-digit runtime dependency count (currently 4 — Jinja2 left with the server-rendered console on 2026-08-09), no ORM and no graph database. The console is a React + TypeScript SPA built at build time and served as static files by the same FastAPI process at / — so it costs build-time tooling, not a runtime dependency and not a second service. The deployment is still one app container plus one PostgreSQL. See docs/PIVOT_PLAN.md.
Open http://127.0.0.1:8000 and sign in — the console is branded MonitorRisk.
--generate prints a password to the terminal, so it
now lives in scrollback and in docker compose logs — the console therefore holds that account
at Your account until it is replaced. Every JSON endpoint stays closed until then — the
console shell is a static bundle, so the gate is enforced on the data, not on the page, and
therefore cannot be scripted around.
After that, passwords are managed from inside the console: Your account (the role chip, top
right) changes your own — the current password is required even though you are already signed
in, because a stolen session should not be enough to take an account over permanently. Admins
also get a user list there, where a reset mints a new password rather than setting a chosen
one. Either way, every other session for that account is signed out; that is the point of
changing a password that may have leaked.
Locked out of every admin account, the way back in is from the host — where whoever runs the
container already has the database anyway:
The whole deployment is one app container and one PostgreSQL. That is deliberate: it is the
product's clearest structural advantage, and a third service would forfeit it.
What the server adds over the CLI
Mitigation journey — re-upload the same exports over time; each finding is classified
new · persisting · resolved · regressed, with age, assignee, due date and MTTR. A finding
that comes back re-opens the same row with its history intact rather than appearing as new.
Coverage manifest — "you supplied 105 of 123 sources; 10 modules ran with incomplete
input; 1 source is not obtainable in RISE at all." Without it a partial upload produces a
clean-looking report over a fraction of the estate.
Risk acceptance with expiry, false-positive disputes with a mandatory reason, and a
submitted_to_provider state for work handed to SAP under RISE.
Graph nodes — the SAP objects named by findings are materialised as typed nodes, the
substrate for the attack-path view.
RBAC with per-system row scoping, session auth, and an append-only audit log.
JSON API rendering from the same query layer as the console, including a
changes since run N endpoint.
Everything above assumes you produce the export. On an estate you can reach
over the network — ECC and on-premise NetWeaver typically, RISE typically not —
MonitorRisk can produce part of it itself.
The scanner still connects to nothing.collect/ is a separate, optional
program that writes the same files the offline path reads. The scanner cannot tell
which produced them, and that is the design: connected mode inherits the offline
path's entire test suite.
# Profile parameters, from the instance's SAP start service (sapstartsrv).
python -m collect sapcontrol --host ecc-prod.example.com --instance 00 --user SAPADM --out ./extract
# The ICF surface — which endpoints are active, and which answer UNAUTHENTICATED.
python -m collect icf --host ecc-prod.example.com --out ./extract
# Then scan it, exactly as if you had exported it by hand.
python sap_scanner.py --data-dir ./extract
No SDK, no add-on
sapstartsrv SOAP on 5<NN>14, and plain HTTPS. collect/ is stdlib-only, so a customer running it installs nothing.
Read-only, enforced
The same service also offers Start, Stop, Restart and OS command execution. An allowlist is checked before any byte reaches the network.
No --password
A credential in argv is visible in ps and in shell history. Prompted, piped, or SAPCONTROL_PASSWORD.
Partial by construction
Users, roles and authorisations are RFC-only, and RFC is declined (decision D3). Every run writes a manifest naming what it could not reach.
--probe-only reports what an endpoint exposes — including whether it answers
with no credentials at all — and collects nothing. Worth running first.
Full detail, including the export_completeness.json declaration that lets an
absent parameter be judged rather than merely disclosed, is in
docs/EXPORT_GUIDE.md.
Audit Modules
Module
Checks
Focus
🔐 User & Authorization
USR-001→010 (10)
Default users, SAP_ALL, dormant accounts, service accounts
🛡️ Advanced IAM
IAM-SOD/FF/EXP/XID/REV/ROLE/FED/PRIV (30)
SoD conflicts, firefighter access, role lifecycle, cross-system identity
TLS config, certificate health, SNC, HANA encryption at rest (data/log/backup), system-replication TLS, crypto library, key management
🗄️ HANA Database Security
HANADB-USER/PRIV/ROLE/AUDIT/PARAM (19)
Privileged DB users (SYSTEM, password lifetime, dormancy), PUBLIC & system-privilege grants, _SYS_BI_CP_ALL analytic bypass, DEBUG/ATTACH DEBUGGER grants, DB auditing, HANA security parameters incl. log_mode/PITR and MDC cross-database access
📰 SAP Security Notes / HotNews
HOTNEWS-000→004 (5)
Missing HotNews (Priority 1) & High (Priority 2) SAP Security Notes since 2020, actively-exploited (CISA KEV) unpatched CVEs, partially-implemented notes — diffed from your SNOTE export against a curated, verified catalog
🔓 ABAP Authorization & Critical Access
AUTH-001→016 (16)
Role-content analysis from AGR_1251: Debug&Replace (runtime auth bypass), trusted-RFC impersonation (S_RFCACL), OS command/file access (S_LOG_COM/S_DATASET), authorization forging (S_USER_AUT), broad S_RFC, generic table maintenance (S_TABU_), run-any-report (S_PROGRAM), batch impersonation, unrestricted destination authorization (S_ICF DEST=), and sensitive Basis transactions — attributed to the users who hold each role
🔗 System Trust & Standard Users
TRUST-001→008 + TRUST-010, STDUSR-001→003 (12)
Trusted/trusting RFC (inbound trust from a lower tier, self-trust, unmigrated 2020 method, trusted destination with a fixed user), SAProuter wildcard routes, message-server port separation, UCON RFC allowlist, gateway proxy ACL — plus standard users (SAP* kernel auto-logon, default passwords, unlocked SAP*/DDIC/SAPCPIC/EARLYWATCH/TMSADM)
🧱 Security Baseline Parameters
BASELINE-001→012 + BASELINE-SNC-DEFERRED (13)
SAP Security Baseline / DSAG / CIS profile parameters the other modules don't cover: RFC authorization engine (auth/rfc_authority_check, auth/no_check_in_some_cases), SNC insecure-connection fallback, SAP GUI Scripting, weak legacy password hashes (downwards compatibility) and weak password hash algorithm (login/password_hash_algorithm), sapstartsrv / Host-Agent web methods, gateway ACL mode, SSO ticket & session-cookie transport, ICM security log & error disclosure
🧩 S/4HANA & Cloud Authorization
S4AUTHZ-001→008 (8)
The cloud-era authorization layer: super-admin business-role templates (SAP_BR_ADMINISTRATOR*), business-role restrictions left 'Unrestricted', business-catalog sprawl, CDS views with @AccessControl.authorizationCheck disabled, published OData V4 service groups without S_SERVICE, Cloud Connector system mappings without principal propagation, over-assigned Cloud Foundry Org Manager / Space Developer, and birthright role collections mapped to the Default IdP group
⚖️ Access Risk Analysis (SoD)
ARA-* (27 risks + user score)
GRC-style offline Segregation-of-Duties from AGR_1251 + AGR_USERS. Resolves each user's transactions and authorization object/field/activity across all roles, then evaluates a verified ruleset at the permission level (so display-only access is not a false positive): 25 SoD conflicts across Procure-to-Pay, Order-to-Cash, Record-to-Report, Hire-to-Retire and Basis/Security, plus 2 HR critical accesses. Honours documented mitigating controls (with expiry) and produces a per-user risk profile. Extensible via a custom ruleset JSON. (Supersedes the coarse transaction-level SoD in Advanced IAM, which now defers to this module when AGR_1251 is available.)
⚙️ Basis Jobs & OS Commands
JOBCMD-CMD/JOB-* (11)
The realised host-command-execution surface: external OS-command definitions (SM69 / SXPGCOSTAB) that wrap a shell/interpreter, allow runtime argument injection (ADDPAR), resolve to an unqualified/user-writable path, or wrap a destructive/exfil utility — plus armed background jobs (TBTCO/TBTCP) whose step user (AUTHCKNAM) is SAP*/DDIC/SAP_ALL, that shell out to an OS command/program, that run RSBDCOS0 (SM69-allowlist bypass) or unreviewed custom code, whose step user is deleted/locked/dialog, or differs from the scheduler (identity borrowing). Reuses users/profiles to resolve privileged step users. Complements the ABAP Authorization module (which covers who can act) with what is actually defined and scheduled.
🚨 GRC Access Control
GRC-FF/ARM/ARA/MIT/RS (13)
The SAP GRC Access Control process layer (not just configuration): Emergency Access Management / Firefighter usage without owner review, self-owned firefighter IDs, uncontrolled Firefighter logon; Access Request Management approvals bypassing SoD risk analysis, auto-provisioned requests, missing risk analysis; GRC-native SoD violations left open past SLA; mitigating controls without a monitor or past validity; and SoD-ruleset governance (blank/critical risk levels, ruleset currency).
👔 Role Design & Governance
RG-SU24/GEN/DRV (3)
Role-build hygiene: custom Z*/Y* transactions with unmaintained SU24 authorization proposals (default-check gaps), roles whose profiles were never generated (AGR_1016) so the authorizations are inert, and derived roles whose authorization values have drifted from their parent (org-level fields excepted) — a common source of silent over-entitlement.
💰 Financial Controls (SOX)
FIN-PP/TOL/SF/DOC/NR (6)
SOX ITGC / FI configuration controls: posting-period variants left wide open (T001B), unlimited or unset posting tolerance groups (T043T), payment-relevant fields not under dual-control / four-eyes (T055F), document-change rules allowing post-posting edits to bank/payment fields (TBAER), and FI accounting-document number ranges main-memory buffered (TNRO) — which breaks gap-free, audit-defensible document numbering.
🧾 ATC / CVA Import
ATC-*
SAP's own ATC / Code Vulnerability Analyzer results, ingested rather than re-derived. Where the customer already licenses CVA, its findings are authoritative and duplicating them would only disagree with SAP about SAP's own tool.
🔎 Security Audit Log Review
LREV-FLT/PAT/RET/* (15)
Retrospective SM20 review — what the audit log actually recorded, as opposed to how it is configured. Configuration says what should be captured; this says what was.
🔒 SNC Posture
CRYPTO-SNCECS-* (7)
The 18 SNC / IGS parameters of SAP Note 3250501 as one model, not 18 comparisons. With snc/enable = 0 every accept_insecure_* setting is moot, so ten independent findings would report ten problems where the truth is one. Also checks the relationships the note itself states: igs/snc/name must match snc/identity/as, igs/snc/library must match snc/gssapi_lib, and data_protection/min may not exceed max. Critically, snc/accept_insecure_gui = 1 and snc/only_encrypted_rfc = 0 are the ECS standard — flagging them would flag every compliant RISE system.
📜 ECS Mandatory Configuration
AUTH-ECS / CRYPTO-ECS / STDUSR-ECS / LREV-ECS (5)
The configuration half of Note 3250501 — the items that are not profile parameters: password-hash tables behind authorization group SPWD, SSF_PSE_D behind SPSE, unused clients, and Security Audit Log filter coverage. Every one of the note's 18 items is accounted for in a disposition table naming who owns it, so a future note version that adds a nineteenth breaks the build rather than the report.
🧬 Custom Code (CVA)
ABAP-* (133 rules)
Our own ABAP / CDS / RAP scanner over an abapGit offline export — the one route ABAP source leaves a RISE PCE system. Statement-level lexing (ABAP statements end at a period and routinely span five lines; matching line-by-line both loses real injections and invents false ones), a mode-stack that handles string templates and their embedded expressions, SQLScript lexing for AMDP bodies, and intra-procedural taint analysis that grades each finding confirmed / tentative / pattern-only. Where the customer has SAP's own CVA, atc ingests those results instead.
📦 Custom-Code Inventory
CODE-INV-001→005 (5)
The estate picture rather than its defects: object counts by type, code nothing references (dead-code removal reduces attack surface), code that has not run in a year, and — kept deliberately separate — code whose reachability is unknown. Unknown is not unreachable.
🔁 Resilience & Recovery
RES-BCK/DR/EVD/JOB (9)
Ransomware readiness from what an export can actually evidence: backup recency and failure posture, DR-test records, recovery objectives. Scrupulously scoped — this verifies that resilience is configured, never that a restore works.
🛡️ Advanced IAM — Full Check List
Segregation of Duties (IAM-SOD-*)
Check
Description
Severity
IAM-SOD-FIN-001
SoD: Vendor Master ↔ Payment Processing
CRITICAL
IAM-SOD-FIN-002
SoD: Purchase Order ↔ Goods Receipt
HIGH
IAM-SOD-FIN-003
SoD: Journal Entry ↔ GL Account Master
HIGH
IAM-SOD-FIN-004
SoD: Customer Master ↔ Sales Order / Billing
HIGH
IAM-SOD-HR-001
SoD: HR Master Data ↔ Payroll Execution
CRITICAL
IAM-SOD-SEC-001
SoD: User Administration ↔ Role Administration
CRITICAL
IAM-SOD-BASIS-001
SoD: Transport Management ↔ Development
HIGH
SoD checks support three data strategies: pre-computed matrix (sod_matrix.csv), role resolution (user_roles.csv + role_tcodes.csv), or heuristic role-name matching.
Firefighter / Emergency Access (IAM-FF-*)
Check
Description
Severity
IAM-FF-001
Sessions exceeding max duration (default: 4h)
HIGH
IAM-FF-002
Sessions without documented justification
HIGH
IAM-FF-003
Sessions not reviewed by controller
CRITICAL
IAM-FF-004
Sessions self-approved (reviewer = requestor)
CRITICAL
IAM-FF-005
Users with excessive firefighter usage frequency
MEDIUM
Role Expiry & Validity (IAM-EXP-*)
Check
Description
Severity
IAM-EXP-001
Role assignments without expiry dates (indefinite)
MEDIUM
IAM-EXP-002
Expired role assignments still present in user master
LOW
IAM-EXP-003
Role assignments with excessive validity periods
MEDIUM
Cross-System Identity (IAM-XID-*)
Check
Description
Severity
IAM-XID-001
BTP users without corresponding S/4HANA account
MEDIUM
IAM-XID-002
S/4HANA locked users still active in BTP (incomplete offboarding)
HIGH
IAM-XID-003
BTP users with administrative role collections
HIGH
Access Review Compliance (IAM-REV-*)
Check
Description
Severity
IAM-REV-001
Overdue access review campaigns
HIGH
IAM-REV-002
Reviews marked complete but with incomplete coverage
MEDIUM
IAM-REV-003
Reviews without assigned reviewer
MEDIUM
Role Design Quality (IAM-ROLE-*)
Check
Description
Severity
IAM-ROLE-001
Custom roles without descriptions
LOW
IAM-ROLE-002
Custom roles without designated owners
MEDIUM
IAM-ROLE-003
Empty roles with no menu/transaction assignments
LOW
Other IAM Checks
Check
Description
Severity
IAM-ORPH-001
Users assigned to non-existent/deleted roles
MEDIUM
IAM-USRGRP-001
Active users in default/unassigned user groups
LOW
IAM-REF-001
Dialog users misused as reference users
HIGH
IAM-PRIV-001
Users with privilege escalation capability (self-escalation paths)
CRITICAL
🔥 BTP Cloud Attack Surface — Full Check List
Cloud Connector (BTP-CC-*)
Check
Description
Severity
BTP-CC-001
Wildcard resource mappings on backends
CRITICAL
BTP-CC-002
High-risk paths exposed (WebGUI, ADT, SOAP RFC)
HIGH
BTP-CC-003
Excessive number of backend systems
MEDIUM
BTP-CC-004
Unrestricted access control lists
HIGH
BTP-CC-005
Certificates expiring or expired
HIGH
BTP-CC-006
Certificates with weak cryptography (SHA-1, <2048 bit)
HIGH
BTP-CC-007
Stale/unused backend configurations
MEDIUM
BTP-CC-008
Cloud Connector version vulnerable to CVE-2024-25642 (improper cert validation / MITM, regression 2.15.0–2.16.1) or out-of-maintenance
HIGH/MEDIUM
Service Bindings (BTP-SB-*)
Check
Description
Severity
BTP-SB-001
Bindings not rotated in 180+ days
HIGH
BTP-SB-002
Bindings with admin-level scopes
HIGH
BTP-SB-003
Orphaned bindings (deleted instances)
MEDIUM
Destination Service (BTP-DST-*)
Check
Description
Severity
BTP-DST-001
Destinations with stored credentials
HIGH
BTP-DST-002
Destinations with TLS verification disabled
CRITICAL
BTP-DST-003
Proxy type mismatch (Internet vs OnPremise)
MEDIUM
BTP-DST-004
Stale destinations (365+ days unmodified)
LOW
Identity Authentication Service (BTP-IAS-*)
Check
Description
Severity
BTP-IAS-001
Apps without conditional authentication rules
MEDIUM
BTP-IAS-002
Apps without IP-based restrictions
MEDIUM
BTP-IAS-003
Apps without multi-factor authentication
HIGH
BTP-IAS-004
IAS password policy for local users is weak (length/complexity/lockout)
HIGH/MEDIUM
BTP-IAS-005
Corporate IdP not enforced — local password fallback allowed
HIGH
Entitlement Governance (BTP-ENT-*)
Check
Description
Severity
BTP-ENT-001
Services entitled but never provisioned
LOW
BTP-ENT-002
Security services entitled but unused (audit, credstore)
MEDIUM
Event Mesh (BTP-EM-*)
Check
Description
Severity
BTP-EM-001
Queues with wildcard topic subscriptions
HIGH
BTP-EM-002
Queues without access control policies
HIGH
BTP-EM-003
Cross-namespace event subscriptions
MEDIUM
Cloud Integration / CPI (BTP-CPI-*)
Check
Description
Severity
BTP-CPI-001
Credentials not rotated in 180+ days
HIGH
BTP-CPI-002
Credentials using basic/plaintext auth
MEDIUM
BTP-CPI-003
iFlows with hardcoded/embedded credentials
CRITICAL
BTP-CPI-004
iFlows with no sender authentication
HIGH
BTP-CPI-005
iFlows using unencrypted HTTP endpoints
HIGH
Network Isolation (BTP-NET-*)
Check
Description
Severity
BTP-NET-001
Services using public internet endpoints
MEDIUM
BTP-NET-002
Critical services without Private Link
HIGH
Subaccount Governance (BTP-GOV-*)
Check
Description
Severity
BTP-GOV-001
Subaccounts without audit logging
HIGH
BTP-GOV-002
Subaccounts using default SAP IDP only
MEDIUM
XSUAA Migration (BTP-MIG-*)
Check
Description
Severity
BTP-MIG-001
Apps still using XSUAA (not migrated to IAS)
MEDIUM
🔗 Network & Integration Layer — Full Check List
API Management (INTG-APIM-*)
Check
Description
Severity
INTG-APIM-001
API proxies missing required security policies
HIGH
INTG-APIM-002
API proxies without authentication policies
CRITICAL
INTG-APIM-003
API proxies allowing unencrypted HTTP
HIGH
INTG-APIM-004
API proxies allowing deprecated TLS versions
HIGH
INTG-APIM-005
API proxies in pass-through mode (zero policies)
CRITICAL
IDOC Port & Partner Security (INTG-IDOC-*)
Check
Description
Severity
INTG-IDOC-001
IDOC ports without encryption (TLS/SNC)
HIGH
INTG-IDOC-002
IDOC file ports with insecure directories
MEDIUM
INTG-IDOC-003
IDOC partners with wildcard message types
HIGH
INTG-IDOC-004
IDOC partners handling sensitive message types
MEDIUM
Web Services / SOAMANAGER (INTG-WS-*)
Check
Description
Severity
INTG-WS-001
High-risk BAPIs/RFCs exposed as web services
HIGH
INTG-WS-002
Excessive active web service endpoints
MEDIUM
INTG-WS-003
Web services with weak/no authentication
CRITICAL
Webhook & Callback Security (INTG-WH-*)
Check
Description
Severity
INTG-WH-001
Webhook callbacks using unencrypted HTTP
HIGH
INTG-WH-002
Webhooks without HMAC signature verification
HIGH
INTG-WH-003
Webhooks delivering to external endpoints
MEDIUM
INTG-WH-004
Stale webhook registrations
LOW
Gateway ACL Deep Analysis (INTG-GW-*)
Check
Description
Severity
INTG-GW-001
Secinfo with overly permissive permit rules
CRITICAL
INTG-GW-002
Secinfo missing deny-all default rule
HIGH
INTG-GW-003
Secinfo permits external program execution
HIGH
INTG-GW-004
Reginfo permits unrestricted RFC registration
CRITICAL
INTG-GW-005
Reginfo missing deny-all default rule
HIGH
Integration Monitoring (INTG-MON-*)
Check
Description
Severity
INTG-MON-001
Missing integration monitoring alert rules
HIGH
INTG-MON-002
Integration events not forwarded to SIEM
MEDIUM
CPI Data Stores (INTG-CPI-DS-*)
Check
Description
Severity
INTG-CPI-DS-001
Data stores with sensitive names, no encryption
HIGH
INTG-CPI-DS-002
Global variables with potentially sensitive names
MEDIUM
INTG-CPI-DS-003
Data stores with excessive entries
LOW
OAuth Client Governance (INTG-OAUTH-*)
Check
Description
Severity
INTG-OAUTH-001
OAuth clients with admin/wildcard scopes
HIGH
INTG-OAUTH-002
OAuth clients using deprecated grant types
HIGH
INTG-OAUTH-003
OAuth clients unused for 180+ days
MEDIUM
Integration Topology (INTG-TOPO-*)
Check
Description
Severity
INTG-TOPO-001
Integration connections without encryption
HIGH
INTG-TOPO-002
Hub systems with excessive connections
MEDIUM
INTG-TOPO-003
Connections to deprecated/legacy systems
MEDIUM
🔏 Data Protection & Privacy — Full Check List
Read Access Logging (DPP-RAL-*)
Check
Description
Severity
DPP-RAL-001
RAL disabled or no active configurations
CRITICAL
DPP-RAL-002
RAL missing coverage for key channels (OData, RFC, ALV)
HIGH
DPP-RAL-003
RAL log channels with insufficient retention
MEDIUM
Information Lifecycle Management (DPP-ILM-*)
Check
Description
Severity
DPP-ILM-001
Retention policies exceeding maximum period
MEDIUM
DPP-ILM-002
Policies without automatic data destruction
MEDIUM
DPP-ILM-003
Policies without end-of-purpose definitions
HIGH
DPP-ILM-004
Personal data tables without ILM retention policies
HIGH
Data Masking — Non-Production (DPP-MASK-*)
Check
Description
Severity
DPP-MASK-001
Non-production systems without PII data masking
CRITICAL
DPP-MASK-002
Production copies in non-prod without masking
CRITICAL
DPP Toolkit (DPP-TOOLKIT-*)
Check
Description
Severity
DPP-TOOLKIT-001
DPP toolkit features not configured (deletion report, consent, breach notification)
HIGH
Purpose of Processing (DPP-POP-*)
Check
Description
Severity
DPP-POP-001
Purposes without documented legal basis (GDPR Art.6)
HIGH
DPP-POP-002
Expired purposes still active
MEDIUM
Sensitive Field Inventory (DPP-FIELD-*)
Check
Description
Severity
DPP-FIELD-001
PII fields without Read Access Logging
HIGH
DPP-FIELD-002
Sensitive fields not masked in non-production
MEDIUM
DPP-FIELD-003
Known sensitive SAP fields missing from classification inventory
MEDIUM
Data Residency & Cross-Border (DPP-RES-*)
Check
Description
Severity
DPP-RES-001
Cross-border transfers without legal safeguards (SCCs/BCRs)
CRITICAL
DPP-RES-002
Special category data in cross-border transfers
HIGH
Data Subject Requests (DPP-DEL-*)
Check
Description
Severity
DPP-DEL-001
Data subject requests overdue (>30 day SLA)
CRITICAL
DPP-DEL-002
Requests marked complete but incomplete
HIGH
DPP-DEL-003
Requests without documentation
MEDIUM
System Landscape (DPP-LAND-*)
Check
Description
Severity
DPP-LAND-001
Systems without data classification assignment
MEDIUM
💻 Code & Transport Security — Full Check List
Code Injection / SQL Injection (CODE-INJ-*)
Check
Description
Severity
CODE-INJ-001
SQL injection patterns in custom code (dynamic WHERE, EXEC SQL)
Debug privileges (DEBUG / ATTACH DEBUGGER) granted to users
HIGH
Roles & Auditing (HANADB-ROLE-* / HANADB-AUDIT-*)
Check
Description
Severity
HANADB-ROLE-001
Powerful predefined roles granted to users
HIGH
HANADB-AUDIT-001
HANA database auditing is disabled
CRITICAL
HANADB-AUDIT-002
Audit trail written to a CSV text file (tamperable)
HIGH
HANADB-AUDIT-003
No active HANA audit policies
HIGH
HANADB-AUDIT-004
Audit policies do not cover critical action groups
MEDIUM
Security Parameters (HANADB-PARAM-*)
Check
Description
Severity
HANADB-PARAM-001
Weak HANA password-policy parameters
HIGH
HANADB-PARAM-002
Detailed connect errors exposed to clients
MEDIUM
HANADB-PARAM-003
TLS not enforced for HANA SQL connections
HIGH
HANADB-PARAM-004
log_mode = overwrite — no point-in-time recovery
HIGH
HANADB-PARAM-005
Cross-database (MDC) access is enabled
MEDIUM
Distinct from Cryptographic Posture's CRYPTO-HANA-* (encryption-at-rest); this module covers users, privileges, auditing and ini parameters.
📰 SAP Security Notes / HotNews — Full Check List
Check
Description
Severity
HOTNEWS-000
SAP Note implementation status not provided (no SNOTE export)
MEDIUM
HOTNEWS-001
Missing HotNews (Priority 1) SAP Security Notes
CRITICAL
HOTNEWS-002
Missing High-priority (Priority 2) SAP Security Notes
HIGH
HOTNEWS-003
Missing notes for actively-exploited SAP vulnerabilities (CISA KEV)
CRITICAL
HOTNEWS-004
Critical SAP Notes only partially implemented
HIGH
Diffs your applied_notes.csv (SNOTE export) against a built-in, verified catalog of major SAP Security Notes since 2020 — including RECON (CVE-2020-6287), ICMAD (CVE-2022-22536), and the 2025 NetWeaver VC RCE (CVE-2025-31324). Note matching is leading-zero-insensitive; not-yet-implemented statuses fail safe to "missing". Extensible via an optional sap_security_notes.json.
🔓 ABAP Authorization & Critical Access — Full Check List
Role-content analysis of the AGR_1251 export (role → object → field → value), attributing each risky role to the users who hold it.
Super-admin business-role template assigned in production (SAP_BR_ADMINISTRATOR*)
CRITICAL
S4AUTHZ-002
Business-role restriction left 'Unrestricted'
HIGH
S4AUTHZ-003
Business role bundles more than 30 business catalogs
MEDIUM
S4AUTHZ-004
CDS view exposes data with authorization checking disabled
HIGH
S4AUTHZ-005
OData V4 service group published without authorization
HIGH
S4AUTHZ-006
Cloud Connector system mapping without principal propagation
HIGH
S4AUTHZ-007
Cloud Foundry privileged platform role over-assigned
HIGH
S4AUTHZ-008
Birthright role collection auto-granted to all federated users
MEDIUM
⚖️ Access Risk Analysis (SoD) — Full Risk List
GRC-style offline, permission-level Segregation of Duties from AGR_1251 + AGR_USERS. Each risk resolves the user's transaction codes and authorization object/field/activity across all roles; a conflict fires only when the maintain activity is held (display-only access is not a false positive). Documented mitigating controls (with expiry) suppress a user/risk and are reported as residual.
External OS-command definitions (JOBCMD-CMD-*) — from SM69 / SXPGCOSTAB
Check
Description
Severity
JOBCMD-CMD-001
External OS command wraps a shell/interpreter or embeds shell metacharacters
CRITICAL
JOBCMD-CMD-002
External OS command allows runtime additional parameters (ADDPAR = X)
HIGH
JOBCMD-CMD-003
External OS command resolves to an unqualified (PATH-hijack) or user-writable path
HIGH
JOBCMD-CMD-004
Destructive / exfiltration utility defined as a standing command (rm/dd/curl/nc/…)
MEDIUM
JOBCMD-CMD-005
External OS command not bound to a specific operating system
LOW
Background jobs & step users (JOBCMD-JOB-*) — from TBTCO / TBTCP
Check
Description
Severity
JOBCMD-JOB-001
Armed job runs under SAP*/DDIC or a SAP_ALL step user
CRITICAL
JOBCMD-JOB-001B
Armed job runs under a standard/technical step user (SAPCPIC/EARLYWATCH/TMSADM)
HIGH
JOBCMD-JOB-002
Job step executes an external OS command / program
HIGH
JOBCMD-JOB-003
Job runs RSBDCOS0 (SM69-allowlist bypass) or unreviewed custom code under a privileged user
HIGH
JOBCMD-JOB-004
Armed job step user is deleted, locked, expired, or a dialog user
MEDIUM
JOBCMD-JOB-005
Job step user differs from scheduler (identity borrowing)
MEDIUM
Only armed jobs (STATUS scheduled/released/ready/active) are evaluated; finished/cancelled jobs are out of scope. Complements the ABAP Authorization module (authz), which covers who is authorized to run commands / set a foreign step user (S_LOG_COM, S_BTCH_NAM) — this module reports the actual command catalog and the actual scheduled jobs.
git clone https://github.com/Krishcalin/SAP-S4HANA-RISE-Security-Scanner.git
cd SAP-S4HANA-RISE-Security-Scanner
# Run against sample data (included)
python sap_scanner.py --data-dir ./sample_data --output report.html
# Generate the detailed PDF hand-over report, the PPTX deck, or several at once
python sap_scanner.py --data-dir ./exports --output report.pdf --format pdf
python sap_scanner.py --data-dir ./exports --output report.html --format both # HTML + PDF
python sap_scanner.py --data-dir ./exports --output report.pptx --format pptx # one slide per finding
python sap_scanner.py --data-dir ./exports --output report.pptx --format pptx --pptx-mode summary # short exec deck
python sap_scanner.py --data-dir ./exports --output report.html --format all # HTML + PDF + PPTX# Run specific modules
python sap_scanner.py --data-dir ./exports --modules btpcloud iam
python sap_scanner.py --data-dir ./exports --modules intglayer network
# Filter by severity
python sap_scanner.py --data-dir ./exports --severity HIGH
# Custom thresholds
python sap_scanner.py --data-dir ./exports --config baseline.json
# Cyber-risk quantification (FAIR): embed a dollar-denominated loss exposure in the report
python sap_scanner.py --data-dir ./exports --output report.html --format both --crq \
--crq-revenue 2000000000 --crq-industry manufacturing --crq-org-name "Acme Manufacturing"# Tell the scanner which estate this is — it changes what "compliant" means (see below)
python sap_scanner.py --data-dir ./exports --deployment-mode rise_pce
# modes: on_prem · rise_pce · rise_tailored · rise_ecc (ECC running inside RISE)# Scan custom ABAP from an abapGit offline export (the `cva` module)
python sap_scanner.py --data-dir ./exports --abap-src ./abapgit_export --modules cva
# Use it as a release gate in CI — exits 0 pass / 1 blocked / 2 could not assess
python sap_scanner.py --data-dir ./exports --gate-write-baseline gate-baseline.json # once
python sap_scanner.py --data-dir ./exports --gate --gate-baseline gate-baseline.json # every build
Available Modules
users — User & Authorization (USR-*)
iam — Advanced IAM (IAM-*)
params — Security Parameters (PARAM-*)
network — Network & Service Exposure (NET-*)
rise — RISE / BTP Core (RISE-*)
btpcloud — BTP Cloud Attack Surface (BTP-*)
intglayer — Network & Integration Layer (INTG-*)
dataprot — Data Protection & Privacy (DPP-*)
codetrans — Code & Transport Security (CODE-*)
logmon — Logging, Monitoring & IR (LOG-*)
fiori — Fiori & UI Layer (FIORI-*)
crypto — Cryptographic Posture (CRYPTO-*)
hanadb — HANA Database Security (HANADB-*)
hotnews — SAP Security Notes / HotNews (HOTNEWS-*)
authz — ABAP Authorization & Critical Access (AUTH-*)
systrust — System Trust & Standard Users (TRUST-*, STDUSR-*)
baseline — Security Baseline Parameters (BASELINE-*)
s4authz — S/4HANA & Cloud Authorization (S4AUTHZ-*)
ara — Access Risk Analysis / offline SoD (ARA-*)
jobcmd — Basis Jobs & OS Commands (JOBCMD-*)
grcac — GRC Access Control (GRC-*)
rolegov — Role Design & Governance (RG-*)
fincontrols — Financial Controls / SOX (FIN-*)
atc — SAP ATC / CVA result import (ATC-*)
cva — Custom-code ABAP/CDS/RAP scanner (ABAP-*) ← needs --abap-src
logreview — Security Audit Log retrospective review (LREV-*)
codeinv — Custom-code inventory & dead code (CODE-INV-*)
resilience— Backup / DR / recovery posture (RES-*)
snc — SNC posture as one model (CRYPTO-SNCECS-*)
ecsconfig — ECS mandatory configuration, Note 3250501 (…-ECS-*)
all — Run everything (default)
That is the complete list — all 30 keys, matching --modules exactly.
Examples with the newer modules:
# Offline Segregation-of-Duties + ABAP critical-access review
python sap_scanner.py --data-dir ./exports --modules ara authz
# HANA DB hardening + missing SAP Security Notes
python sap_scanner.py --data-dir ./exports --modules hanadb hotnews
# System trust, standard users, and Security Baseline parameters
python sap_scanner.py --data-dir ./exports --modules systrust baseline
--gate turns the scanner from something that reports into something that decides, so it can sit in a pipeline. Full adoption guidance is in docs/RELEASE_GATE.md.
Exit
Meaning
0
Pass — nothing in scope got worse
1
Blocked — the policy was violated
2
Could not assess — coverage was degraded, so no verdict is claimed
# 1. Record where you are today. Runs a full scan and writes a report as well.
python sap_scanner.py --data-dir ./exports --gate-write-baseline gate-baseline.json
# 2. Enforce on every build.
python sap_scanner.py --data-dir ./exports --gate --gate-baseline gate-baseline.json
# Optional: scope to the objects a transport actually touches, and emit machine-readable output
python sap_scanner.py --data-dir ./exports --gate --gate-baseline gate-baseline.json \
--gate-scope transport-objects.json --gate-policy gate-policy.json --gate-json gate.json
Four rules, each drawn from a specific way gates get switched off in practice:
Judge the delta, not the backlog. A gate that fails on pre-existing findings is disabled in a week.
Judge only what the transport touches.--gate-scope narrows the verdict to the objects under change.
Never block on what the customer cannot fix. In RISE, a ticket_to_sap finding is not the developer's to resolve, and failing their build for it teaches them to bypass the gate.
Never fail open. Degraded coverage is exit 2, never a pass — an unassessable build must not look like a clean one.
Two things worth knowing before you wire it up. --gate-write-baseline is evaluated before--gate, so passing both in one command writes the baseline and skips evaluation. And an empty finding set currently returns pass, not "could not assess" — if a run can collapse to zero findings for an unrelated reason, assert on the finding count in your pipeline too.
Choose the output with --format html (default), pdf, pptx, both (html+pdf), or all (html+pdf+pptx). The output path's extension is respected; companion files are written alongside it. All three engines are pure standard library — no python-pptx, no reportlab.
Format
Best for
Contents
HTML
Interactive triage
Clean, light-themed dashboard (MonitorRisk + SAP branding) with an overall risk score, the P1–P4 priority queue, severity/category breakdown, a compliance-mapping panel, a live severity filter, and collapsible findings — each with its detailed risk narrative and step-by-step remediation. Single self-contained file (logos embedded as data URIs).
PDF
Formal hand-over to the SAP Basis / security team
A multi-page assessment report ordered cover → risk-priority queue (P1–P4) → findings-by-area → compliance mapping → per-finding detail pages (fix-first order), each with the affected objects, a detailed Security Risk explanation, a numbered step-by-step Remediation procedure, and references. Running header/footer, page numbers, confidentiality banner. Built with a pure-standard-library PDF engine.
PPTX
Presenting findings in a meeting / to leadership
A PowerPoint deck. --pptx-mode full (default) = title, executive summary, priority queue, findings-by-area, recommended actions, a compliance snapshot + one slide per framework, then one slide per finding (fix-first, ~300+ slides) with severity/priority chips, exploit tags, and a summarized Security Risk + High-Level Mitigation. --pptx-mode summary = a short executive-only deck. Built with a pure-standard-library OOXML/PPTX engine.
Risk prioritization (P1–P4)
Findings are ranked P1 (fix now) → P4 (backlog) by combining severity with exploitability (actively-exploited / CISA-KEV, HotNews), internet/exposure, and privilege. The reports lead with this queue and order the detailed findings fix-first, so the highest-leverage work is unmistakable.
Compliance mapping
Every category is mapped to control frameworks and rendered as a per-framework panel (flagged controls with severity counts) in the HTML and PDF, and as dedicated slides in the PPTX deck. Eight frameworks: ISO/IEC 27001:2022 (Annex A), NIST CSF 2.0, NIST SP 800-53 Rev 5, DORA (Regulation (EU) 2022/2554), CIS Controls v8, TISAX / VDA ISA, SOC 2 (Trust Services Criteria), and EU GDPR. All control IDs are verified against the published frameworks. DORA is mapped to named requirement areas rather than article numbers — an auditor reading a citation expects the sub-paragraph to say what we imply it says.
Detailed findings — knowledge base
Every finding is rendered with an in-depth Security Risk explanation (what the weakness is, the concrete attack/abuse scenario, and the business/compliance impact) and a numbered, step-by-step remediation procedure naming the exact SAP transactions, reports, IMG paths, parameters and tables to change, how to verify the fix, and rollout cautions. This content lives in a bundled knowledge base (data/finding_details.json) keyed by check-id (with family-prefix fallback); where an entry is absent, the report falls back to the finding's own description and remediation, so the report is always complete.
Run with --crq to translate the technical findings into financial risk using the FAIR (Factor Analysis of Information Risk) model and a Monte-Carlo simulation. The report gains a Financial Risk Exposure section: the expected annual loss (mean ALE), the 1-in-10 bad year (ALE P90), a loss-exceedance curve, a per-scenario breakdown, and the dollar amount reducible by remediation (as-is posture vs. a fully-hardened target).
How it stays methodologically honest:
A finding is not a risk. Findings are treated as evidence that shifts the FAIR factors of a small set of scoped SAP loss scenarios (internet-facing RCE→ransomware, SoD/financial-controls→payment fraud, privileged/standard-user takeover, HANA data exfiltration→GDPR breach, interface/integration→lateral movement) — never assigned their own dollar figure and summed.
Calibration is range-selection, not arithmetic on CVSS. The worst open prevention finding selects a Resistance-Strength band; the scanner's existing exposed/exploited signals select the Contact-Frequency and Probability-of-Action bands. Logging/monitoring gaps aren't a scenario — they set a dwell-time loss multiplier (weak detection ⇒ longer dwell ⇒ larger loss, per FAIR-CAM).
Correct aggregation. The portfolio ALE is the element-wise Monte-Carlo sum of the independent per-scenario loss distributions — never a sum of percentiles.
Report filters never move the number. The quantification always runs on the complete finding set, so a display --severity filter can't change the dollar figure.
Honest by construction. Loss magnitudes are modelled estimates from public benchmarks (IBM Cost of a Data Breach, Verizon DBIR, ACFE, Sophos, GDPR enforcement) scaled to --crq-revenue/--crq-industry; the report says so, and the scenario input is exported alongside as *.crq.json.
The Monte-Carlo engine is bundled (modules/crq_engine.py, standard library only), so --crq produces an actual number on a plain checkout. It is deliberately last in the lookup order, so --crq-engine, the CRQ_ENGINE env var and a sibling Cyber-Risk-Quantification checkout all still take precedence. If no engine resolves at all, the scanner still exports the *.crq.json scenario input so you can quantify it standalone — there is no hard dependency on the sibling repo.
The engine was bundled because the sibling repo is absent from a normal checkout, so --crq used to degrade silently to "inputs exported, not simulated" and produce no figure at all.
Flag
Purpose
--crq
Enable FAIR quantification; write <output>.crq.json and embed the ALE + loss-exceedance curve in the HTML/PDF report
--crq-revenue
Organization annual revenue (USD) for the loss scaling (default: illustrative $1B)
--crq-industry
Industry for the loss multiplier (financial_services, healthcare, technology, retail, manufacturing, government, energy, education)
--crq-org-name
Organization name shown in the report
--crq-sims
Monte-Carlo iterations per scenario (default: 10000)
--crq-engine
Explicit path to crq_engine.py (overrides auto-detect / CRQ_ENGINE)
Reuses users.csv (USR02) and profiles.csv (USR04) to resolve whether a job step user is SAP*/DDIC or a SAP_ALL holder, locked, expired or a dialog account.
Access Risk Analysis can also be driven by a custom SoD ruleset — drop an ara_ruleset.json into your --data-dir to extend or override the built-in 27-risk ruleset (entries matching a built-in risk_id override it; new ids are added).
Python 3.8+ and nothing else. No external packages — the HTML, PDF and PPTX engines are all hand-built, and a CI job walks the AST of modules/ and sap_scanner.py to keep it that way.
Server
Python 3.12, PostgreSQL 16, and the four packages in requirements.txt (FastAPI, uvicorn, psycopg, python-multipart). DB_DSN and SESSION_SECRET have no defaults and must be set.
Building the console
Node 22 + npm, at build time only. docker compose up --build does this for you inside the image's first stage; nothing JavaScript runs at runtime.
Running the tests
pytest, plus the runtime dependencies and httpx — see Testing.
If you check the repo out and start the server without building the console, that is a defined state rather than a crash: the API keeps working and every console URL answers 503 with a message telling you to run npm run build in frontend/.
About 1,975 tests across 50 files. The suite runs every audit module against the bundled
sample_data (crafted to trigger each check) and validates the full pipeline —
no SAP system needed. It checks that each module fires, handles empty input
without crashing, honours the finding contract (field types / severities — this
catches bugs like a description accidentally being a tuple), has no cross-module
check-id collisions, renders the HTML report, and runs end-to-end via the CLI.
requirements-dev.txt on its own is not enough: it contains only pytest, and the
server-tier suites import psycopg / starlette at module level, which aborts collection
rather than skipping. httpx is in neither file but Starlette's TestClient will not
construct without it.
Nine suites need a real PostgreSQL and skip without DB_DSN — the journey, the analytics,
the HTTP layer and all of the RBAC coverage. The journey is implemented in SQL, so a mocked
database proves the Python is self-consistent and proves nothing about whether it works:
CI (GitHub Actions, .github/workflows/tests.yml) runs six jobs on every push and pull request:
Job
What it proves
cli
The suite passes on Python 3.8–3.12 with only pytest installed, plus a full sap_scanner.py smoke run — so a third-party import into the scanner core fails the build
purity
Walks the AST of modules/ and sap_scanner.py and rejects any non-stdlib import — the charter enforced mechanically rather than remembered
sap-content
Re-derives data/sap_baseline_requirements.json from SAP's published policy repository and fails on drift; the coverage page is measured against that catalogue, so a stale copy misreports coverage
brand-assets
Re-derives server/static/* from the master artwork and fails if the committed files drift
server
The full suite against PostgreSQL 16, schema applied twice (idempotency is the upgrade path), a scan seeded before pytest so data-dependent suites actually execute, and a guard that fails the build if more than one test skips
That last guard is load-bearing. Before it existed, pytest -q ran the database-backed suites,
they skipped for want of DB_DSN, and the job went green having verified none of the journey,
none of the analytics and none of the HTTP layer. A suite that silently skips is worse than one
that does not exist, because it looks verified.
⚠️docs/CHECKS_REFERENCE.md is the least current file in the repo —
it is generated from the code by tools/build_checks_reference.py and CI fails if it drifts, so it cannot fall behind the modules again.
added since. Trust the code, and the module tables above, over that document.
External code contributions are not accepted — this is source-available, not open source, and merging outside work into a proprietary codebase makes the copyright jointly held. Bug reports, corrections to SAP facts, and false positive/negative reports are genuinely welcome. See CONTRIBUTING.md.
Found a vulnerability in this tool? Do not open an issue — see SECURITY.md.
This tool is for authorized security assessments only.
The scanner itself performs offline analysis of exported data and never connects to
anything. Connected mode is an optional, separately-invoked collector (collect/) that
reads from a system you authorise and writes the same export files the offline path
consumes; the scanner cannot tell which produced them.
Nothing in this product ever writes to an SAP system, in either mode. Every connector
is read-only, and there is no remediation, provisioning or transport path — by design, not
by omission. See docs/DECISIONS.md (D2, D3) for the reasoning and its limits.
Proprietary. All rights reserved. Copyright (c) 2026 Krishnendu De.
No licence is granted to use, copy, modify or distribute this software, in whole
or in part, without prior express written permission. The repository being
publicly viewable is not a grant of any licence, and viewing it for evaluation
confers no right to execute or deploy it. See LICENSE for the full
terms and for the third-party components, which remain under their own licences.
Agentless SAP security scanner for S/4HANA RISE, ECC and BTP. Offline by default, optional read-only connectors. Source-available: proprietary, all rights reserved — reading and review are welcome, any use requires written permission.