Skip to content

Krishcalin/SAP-Code-Vulnerability-Analyzer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SAP ABAP Code Vulnerability Analyzer

SAP ABAP Code Vulnerability Analyzer

tests

A comprehensive, dual-mode security scanner for SAP ABAP code and SAP BTP environments. Inspired by SAP's Code Vulnerability Analyzer (CVA), this tool performs passive SAST analysis of ABAP source files and active API scanning of live SAP BTP sub-accounts — all from a single, zero-dependency Python file.

124 security checks across 14 SAST categories and 9 BTP API check groups. Detects SQL injection, code injection, missing AUTHORITY-CHECK (with block-aware analysis of whole function modules), hardcoded credentials, weak cryptography, RFC security issues, backdoor / malicious-code patterns, UI5/JavaScript XSS, and more — purpose-built for SAP security teams, ABAP developers, and compliance auditors.


Table of Contents


Why This Scanner?

Traditional security tools often miss SAP-specific vulnerabilities. ABAP has unique security constructs — AUTHORITY-CHECK, OPEN DATASET, CALL FUNCTION ... DESTINATION, GENERATE SUBROUTINE POOL — that require specialised detection rules:

  • Dynamic Open SQLSELECT ... WHERE (variable) bypasses parameterisation, enabling SQL injection in ways generic scanners don't detect
  • ABAP code injectionINSERT REPORT and GENERATE SUBROUTINE POOL allow runtime code generation, a pattern unique to ABAP
  • Missing AUTHORITY-CHECK — RFC-enabled function modules without proper authorization checks are a top SAP attack vector
  • RFC lateral movement — Dynamic DESTINATION parameters allow attackers to pivot across SAP landscapes
  • BTP cloud misconfigxs-security.json scope grants, unauthenticated routes, and missing XSUAA validation are BTP-specific risks
  • SAP-specific CVEs — CommonCryptoLib, SAP_BASIS, RECON (CVE-2020-6287), and HTTP/2 Rapid Reset vulnerabilities require SAP-aware dependency checking
  • ABAP comment syntax — ABAP uses * (column 1) and " (inline) for comments, which generic scanners misparse

Features

  • 124 security checks — 94 SAST regex rules (ABAP/CDS, BTP config & UI5/JS) + 30 BTP API checks
  • Data-flow (taint) analysis (--data-flow) — intra-procedural source→sink tracking with sanitizer awareness; confirms tainted-input findings, suppresses literal/sanitized false positives, and prints the source→sink data-flow path (also emitted as SARIF codeFlows)
  • Dual-mode scanning — passive SAST for source code, active API for live BTP environments, or both simultaneously
  • ABAP-aware parsing — correctly handles ABAP comment syntax (* and "), case-insensitive keywords, and . statement terminators
  • BTP configuration analysis — deep inspection of xs-security.json, xs-app.json, mta.yaml, and CDS annotations
  • SAP dependency CVE checking — detects known vulnerabilities in CommonCryptoLib, SAP_BASIS, SAP Kernel, SAPUI5, and NetWeaver AS
  • Three output formats — colour-coded terminal, structured JSON, and interactive HTML with dark theme and filtering
  • Single portable file — entire scanner is one Python file with no pip installs needed for SAST mode
  • Scan profiles & rule selection--profile full|critical-high|quick, plus --disable/--enable-only (by rule ID or category prefix) and --list-rules
  • Security grade — weighted A–F score (CRITICAL 10 / HIGH 5 / MEDIUM 2 / LOW 1) in the console header, JSON, and an HTML grade card
  • OWASP Top 10 (2021) mapping — every finding tagged with its OWASP category; per-OWASP breakdown in console/JSON and a SARIF taxonomies block with per-rule relationships
  • Exit codes — returns 1 if CRITICAL or HIGH findings, 0 otherwise (CI/CD friendly)
  • CWE-mapped — every rule maps to a CWE identifier for compliance and risk management
  • BTP OAuth 2.0 — authenticates to SAP BTP via XSUAA client credentials flow with automatic token refresh

Dual-Mode Architecture

                    ┌─────────────────────────────────────────────┐
                    │         SAP ABAP Code Vulnerability         │
                    │              Analyzer v1.8.0                │
                    └─────────────────┬───────────────────────────┘
                                      │
                    ┌─────────────────┴───────────────────────────┐
                    │                                             │
              ┌─────┴─────┐                              ┌───────┴───────┐
              │  SAST Mode │                              │  BTP API Mode │
              │  (Passive) │                              │   (Active)    │
              └─────┬─────┘                              └───────┬───────┘
                    │                                             │
        ┌───────────┼───────────┐                    ┌────────────┼────────────┐
        │           │           │                    │            │            │
   .abap files  .cds files  BTP config          XSUAA OAuth   SCIM API   Dest. Svc
   (80 rules)   (@requires) (xs-security)       Password Pol  Role Coll  Audit Log
                                                User Access   Trust Cfg  Comm. Arr.
                    │                                             │
                    └─────────────────┬───────────────────────────┘
                                      │
                              ┌───────┴───────┐
                              │ Unified Report│
                              │ (Console/JSON │
                              │  /HTML)       │
                              └───────────────┘
Mode Trigger Dependencies What It Scans
SAST (passive) python abap_scanner.py /path None (pure stdlib) ABAP source, CDS, BTP config files
BTP API (active) --btp-url --client-id --client-secret requests Live BTP sub-account APIs
Both Provide target path + BTP credentials requests Combined SAST + API findings

SAST Rule Categories

1. SQL Injection (CWE-89)

Rule ID Severity Detection
ABAP-SQLI-001 CRITICAL Dynamic WHERE (variable) clause
ABAP-SQLI-002 CRITICAL CONCATENATE/&& into SQL condition
ABAP-SQLI-003 CRITICAL ADBC cl_sql_statement->execute_query
ABAP-SQLI-004 CRITICAL ADBC cl_sql_connection=>get_connection
ABAP-SQLI-005 HIGH OPEN CURSOR with dynamic WHERE
ABAP-SQLI-006 HIGH Dynamic ORDER BY (variable)
ABAP-SQLI-007 HIGH Dynamic GROUP BY (variable)
ABAP-SQLI-008 HIGH Dynamic HAVING (variable)
ABAP-SQLI-009 CRITICAL Prepared statement defeated by concatenation
ABAP-SQLI-010 MEDIUM Dynamic FROM (table) clause
ABAP-SQLI-011 HIGH Dynamic table name in FROM (variable) (continuation-line aware)

2. Code Injection (CWE-94)

Rule ID Severity Detection
ABAP-CINJ-001 CRITICAL INSERT REPORT ... FROM (runtime code replacement)
ABAP-CINJ-002 CRITICAL GENERATE SUBROUTINE POOL (dynamic code compilation)
ABAP-CINJ-003 HIGH CALL FUNCTION variable (dynamic FM call)
ABAP-CINJ-004 HIGH CALL TRANSACTION variable (dynamic tcode)
ABAP-CINJ-005 HIGH SUBMIT (variable) (dynamic report execution)
ABAP-CINJ-006 MEDIUM CREATE OBJECT ... TYPE (variable)
ABAP-CINJ-007 CRITICAL CALL TRANSFORMATION variable (dynamic XSLT)
ABAP-CINJ-008 HIGH READ REPORT ... INTO (source code extraction)
ABAP-CINJ-009 MEDIUM ASSIGN (variable) (dynamic field-symbol assignment)
ABAP-CINJ-010 HIGH CALL METHOD (variable) (dynamic method invocation)

3. OS Command Injection (CWE-78)

Rule ID Severity Detection
ABAP-CMDI-001 CRITICAL Kernel CALL 'SYSTEM'
ABAP-CMDI-002 HIGH SXPG_COMMAND_EXECUTE
ABAP-CMDI-003 HIGH SXPG_CALL_SYSTEM
ABAP-CMDI-004 HIGH OPEN DATASET/PIPE ... FILTER
ABAP-CMDI-005 HIGH cl_gui_frontend_services=>execute (frontend OS command)

4. Directory Traversal (CWE-22)

Rule ID Severity Detection
ABAP-PATH-001 HIGH OPEN DATASET without FILE_VALIDATE_NAME
ABAP-PATH-002 HIGH DELETE DATASET without validation
ABAP-PATH-003 HIGH TRANSFER ... TO variable without validation
ABAP-PATH-004 MEDIUM ../ path traversal in string concatenation
ABAP-PATH-005 HIGH READ DATASET without validation

5. Cross-Site Scripting (CWE-79)

Rule ID Severity Detection
ABAP-XSS-001 HIGH HTTP response set_cdata/set_data without escaping
ABAP-XSS-002 HIGH HTML tag concatenation with variable (<script>, <img>, etc.)
ABAP-XSS-003 HIGH BSP/ICF server->response->set_* unescaped
ABAP-XSS-004 MEDIUM Cookie without Secure/HttpOnly flags
ABAP-XSS-005 HIGH cl_abap_browser=>show_html with dynamic content
ABAP-XSS-006 MEDIUM CL_HTTP_UTILITY used without escape_html

6. Missing Authorization (CWE-862)

Rule ID Severity Detection
ABAP-AUTH-001 CRITICAL Function module without AUTHORITY-CHECK
ABAP-AUTH-002 HIGH AUTHORITY-CHECK with DUMMY (always passes)
ABAP-AUTH-003 HIGH SY-SUBRC not checked after AUTHORITY-CHECK
ABAP-AUTH-004 HIGH CALL FUNCTION ... DESTINATION without auth check
ABAP-AUTH-005 HIGH DELETE FROM table without auth check
ABAP-AUTH-006 HIGH UPDATE table SET without auth check
ABAP-AUTH-007 MEDIUM INSERT INTO table without auth check
ABAP-AUTH-008 HIGH CALL TRANSACTION without S_TCODE check
ABAP-AUTH-009 MEDIUM Cross-client access via CLIENT SPECIFIED

7. Hardcoded Credentials (CWE-798)

Rule ID Severity Detection
ABAP-CRED-001 CRITICAL Hardcoded PASSWORD = 'literal'
ABAP-CRED-002 CRITICAL Hardcoded API_KEY/TOKEN/SECRET
ABAP-CRED-003 HIGH RFC DESTINATION with hardcoded password
ABAP-CRED-004 HIGH Hardcoded Basic auth header
ABAP-CRED-005 MEDIUM Credentials defined as CONSTANTS
ABAP-CRED-006 HIGH RFC_*/BAPI_* with embedded USER/PASSWORD

8. Weak Cryptography (CWE-327)

Rule ID Severity Detection
ABAP-CRYP-001 HIGH MD5 hash via cl_abap_message_digest
ABAP-CRYP-002 MEDIUM SHA-1 hash usage
ABAP-CRYP-003 HIGH DES/3DES encryption
ABAP-CRYP-004 HIGH Hardcoded encryption key or IV
ABAP-CRYP-005 MEDIUM HMAC with weak hash (MD5/SHA-1)
ABAP-CRYP-006 LOW Non-cryptographic RNG (cl_abap_random) for security values

9. Information Disclosure (CWE-200)

Rule ID Severity Detection
ABAP-INFO-001 MEDIUM Overly broad CATCH cx_root
ABAP-INFO-002 LOW BREAK-POINT left in code
ABAP-INFO-003 LOW SY-UNAME/SY-MANDT/SY-HOST in output
ABAP-INFO-004 MEDIUM Exception get_text() exposed via MESSAGE
ABAP-INFO-005 HIGH Sensitive data (password, token) in WRITE

10. Insecure Configuration (CWE-16)

Rule ID Severity Detection
ABAP-CONF-001 HIGH ssl_id = 'ANONYM' (no cert validation)
ABAP-CONF-002 HIGH http:// in connection URLs
ABAP-CONF-003 MEDIUM CSRF protection disabled
ABAP-CONF-004 HIGH cl_http_client=>create_by_url with HTTP
ABAP-CONF-005 MEDIUM Wildcard ACTVT = '*' in AUTHORITY-CHECK
ABAP-CONF-006 HIGH ssl_verify = 0/false

11. RFC Security (CWE-284)

Rule ID Severity Detection
ABAP-RFC-001 HIGH Trusted RFC without validation
ABAP-RFC-002 HIGH Dynamic DESTINATION variable
ABAP-RFC-003 HIGH RFC CALLBACK pattern
ABAP-RFC-004 CRITICAL RFC_REGISTER / registered server program
ABAP-RFC-005 MEDIUM Async RFC (STARTING NEW TASK) without error handling

12. Backdoor / Malicious Code (CWE-912)

Detects the deliberate subversion of access control — the hallmark of an insider backdoor or supply-chain implant — rather than the accidental mistakes the other categories cover. (Runtime code-generation backdoors such as INSERT REPORT / GENERATE SUBROUTINE POOL are already flagged under Code Injection.)

Rule ID Severity Detection
ABAP-BKDR-001 CRITICAL Hardcoded SY-UNAME = '...' check (logic bomb / privilege bypass)
ABAP-BKDR-002 HIGH Reference to standard/superuser account (SAP*, DDIC, EARLYWATCH, ...)
ABAP-BKDR-003 CRITICAL Direct DML write to user/authorization tables (USR02, AGR_*, ...)
ABAP-BKDR-004 HIGH Programmatic user/role administration (BAPI_USER_* create/change/assign)
ABAP-BKDR-005 MEDIUM Hardcoded client SY-MANDT = '...' check (client-specific hidden logic)
ABAP-BKDR-006 CRITICAL Programmatic grant of wide profile (SAP_ALL / SAP_NEW)

13. BTP-Specific Config

Rule ID Severity Detection
ABAP-BTP-001 HIGH $ACCEPT_GRANTED_AUTHORITIES in xs-security.json
ABAP-BTP-002 HIGH Wildcard $XSAPPNAME.* scope in role template
ABAP-BTP-003 CRITICAL Hardcoded credentials in mta.yaml
ABAP-BTP-004 HIGH Missing @requires in CDS service definition
ABAP-BTP-005 HIGH authenticationType: "none" in xs-app.json
ABAP-BTP-006 MEDIUM Missing Content-Security-Policy
ABAP-BTP-007 HIGH XSUAA token validation disabled
ABAP-BTP-008 MEDIUM CORS allowedOrigin: "*"

14. Vulnerable SAP Dependencies

Package CVE Severity Impact
CommonCryptoLib < 8.5.50 CVE-2023-40309 CRITICAL Privilege escalation
SAP_BASIS 700-793 CVE-2023-49583 CRITICAL Unauthorised RFC calls
SAP_BASIS 700-789 CVE-2022-22536 CRITICAL HTTP request smuggling
SAP Kernel 700-793 CVE-2023-44487 HIGH HTTP/2 Rapid Reset DoS
SAPUI5 1.38-1.120.2 CVE-2021-21491 HIGH Stored XSS
NetWeaver AS Java 7.10-7.53 CVE-2020-6287 CRITICAL RECON — unauthenticated admin creation

BTP API Checks

When BTP credentials are provided, the scanner connects to the SAP BTP sub-account and runs 30 security checks:

# Category ID Prefix Checks What It Audits
1 Password Policy ABAP-BTP-PWD 4 Min length, complexity, expiry, lockout threshold
2 User Access ABAP-BTP-USR 4 Inactive users, admin accounts, service accounts, MFA
3 Role Management ABAP-BTP-ROLE 4 Wildcard scopes, unused roles, excessive roles, defaults
4 Service Security ABAP-BTP-SVC 3 Stale bindings, key expiry, excessive bindings
5 Trust Configuration ABAP-BTP-TRUST 3 MFA requirement, default IdP, scope mapping
6 Audit Logging ABAP-BTP-AUDIT 3 Audit enabled, retention period, event coverage
7 Communication Security ABAP-BTP-COMM 4 HTTP destinations, basic auth, proxy, user privileges
8 Security Settings ABAP-BTP-SEC 3 Session timeout, token lifetime, refresh lifetime
9 Destination Security ABAP-BTP-DEST 2 HTTP protocol, no-authentication destinations

File Types Scanned

File Type Extensions What Is Checked
ABAP Source .abap, .prog.abap, .clas.abap, .intf.abap, .fugr.abap, .func.abap, .ddls.abap, .dcls.abap, .abp SQL injection, code injection, OS command injection, directory traversal, XSS, missing authorization, hardcoded credentials, weak crypto, info disclosure, insecure config, RFC security
CDS Definitions .cds Missing @requires annotation, BTP config rules
UI5 / JavaScript .js, .ts (skips .min.js) eval, innerHTML, document.write, hardcoded secrets, http:// URLs, jQuery .html()
XSUAA Config xs-security.json Scope grants, role template wildcards, deep JSON inspection
App Router xs-app.json Unauthenticated routes, missing CSP, CORS wildcards
MTA Descriptor mta.yaml, mta.yml Hardcoded credentials, insecure bindings
BTP Config .cdsrc.json, default-env.json Hardcoded secrets, token validation
Package Config package.json BTP config patterns

Prerequisites

  • Python 3.10+ (uses match-style type hints)
  • No pip installs needed for SAST mode (pure stdlib)
  • requests library required only for BTP API mode:
    pip install requests

Installation

Option 1 — Clone the repository:

git clone https://github.com/Krishcalin/SAP-Code-Vulnerability-Analyzer.git
cd SAP-Code-Vulnerability-Analyzer
python abap_scanner.py --version

Option 2 — Download the scanner file directly:

curl -O https://raw.githubusercontent.com/Krishcalin/SAP-Code-Vulnerability-Analyzer/main/abap_scanner.py
python abap_scanner.py --version

Quick Start

1. Scan an ABAP project directory:

python abap_scanner.py /path/to/abap/project

2. Scan with verbose output and severity filter:

python abap_scanner.py /path/to/project --severity HIGH --verbose

3. Generate JSON and HTML reports:

python abap_scanner.py /path/to/project --json report.json --html report.html

4. Scan a live BTP environment:

python abap_scanner.py \
  --btp-url https://mysubaccount.authentication.eu10.hana.ondemand.com \
  --client-id <client-id> \
  --client-secret <client-secret>

5. Combined SAST + BTP API scan:

python abap_scanner.py /path/to/project \
  --btp-url https://mysubaccount.authentication.eu10.hana.ondemand.com \
  --client-id <client-id> \
  --client-secret <client-secret> \
  --json unified_report.json --html unified_report.html

Usage

CLI Reference

usage: abap_scanner [-h] [--btp-url BTP_URL] [--client-id CLIENT_ID]
                    [--client-secret CLIENT_SECRET] [--json FILE] [--html FILE]
                    [--sarif FILE] [--baseline FILE] [--write-baseline FILE]
                    [--no-suppress] [--profile {full,critical-high,quick}]
                    [--disable IDS] [--enable-only IDS] [--list-rules]
                    [--data-flow] [--severity {CRITICAL,HIGH,MEDIUM,LOW,INFO}]
                    [--verbose] [--version]
                    [target]

SAP ABAP Security Scanner v1.8.0 — passive SAST + BTP API

positional arguments:
  target                File or directory to scan (SAST mode)

options:
  -h, --help            show this help message and exit
  --btp-url BTP_URL     BTP XSUAA auth URL (API mode). Env: BTP_AUTH_URL
  --client-id CLIENT_ID OAuth 2.0 client ID. Env: BTP_CLIENT_ID
  --client-secret CLIENT_SECRET
                        OAuth 2.0 client secret. Env: BTP_CLIENT_SECRET
  --json FILE           Save JSON report to FILE
  --html FILE           Save HTML report to FILE
  --sarif FILE          Save SARIF 2.1.0 report to FILE (GitHub code scanning / IDE)
  --baseline FILE       Suppress findings present in this baseline; report only NEW
  --write-baseline FILE Write current findings as a baseline to FILE, then exit
  --no-suppress         Disable inline #NOSEC suppression comments
  --profile {full,critical-high,quick}
                        Scan profile (default: full). critical-high = only
                        CRITICAL+HIGH; quick = CRITICAL only
  --disable IDS         Comma-separated rule IDs/prefixes to turn OFF
  --enable-only IDS     Run ONLY these rule IDs/prefixes (overrides --profile)
  --list-rules          List every rule with its on/off state, then exit
  --data-flow, --taint  Enable data-flow (taint) analysis: confirm tainted
                        findings, suppress literal/sanitized ones
  --severity {CRITICAL,HIGH,MEDIUM,LOW,INFO}
                        Minimum severity to report (default: LOW)
  --verbose, -v         Verbose output
  --version             show program's version number and exit

Scan profiles & rule selection

Tune which checks run — useful for fast PR gates vs. deep audits:

# Profiles: full (default) | critical-high | quick (CRITICAL only)
python abap_scanner.py ./src --profile critical-high
python abap_scanner.py ./src --profile quick          # fastest, highest-signal

# Turn individual rules or whole categories off (exact id OR id-prefix)
python abap_scanner.py ./src --disable ABAP-XSS,ABAP-SQLI-003

# Run ONLY a focused set (e.g. hunt for backdoors); overrides --profile
python abap_scanner.py ./src --enable-only ABAP-BKDR

# Preview the catalogue and what's active under a given selection
python abap_scanner.py --list-rules --profile critical-high

Precedence: --enable-only (allow-list) overrides --profile (severity band); --disable is always applied last. Selection is enforced uniformly across SAST, block, dependency-CVE and BTP API findings.

Data-flow (taint) analysis

python abap_scanner.py ./src --data-flow      # or --taint

A pragmatic, intra-procedural approximation of SAP CVA's local data-flow analysis — the feature that drives down false positives. Per procedure (FORM/METHOD/FUNCTION; PARAMETERS/SELECT-OPTIONS treated as external input), it tracks whether each variable is tainted (from a source such as request->get_form_field, GET PARAMETER ID, a web request), sanitized (via CL_ABAP_DYN_PRG methods, FILE_VALIDATE_NAME, allow-list checks), or a literal/constant. For injection/traversal sink rules it then:

  • confirms the finding when tainted input reaches the sink (confidence: confirmed),
  • suppresses it when the argument is a literal/constant or has been sanitized,
  • leaves it tentative when there's no evidence either way (nothing is dropped on a guess).

confidence appears in the console line, the JSON confidence field, and SARIF result properties. It is off by default, so standard runs (and baselines) are unaffected; turn it on for high-signal, low-noise results.

For a confirmed finding the scanner also prints the data-flow path — where the external input entered, how it propagated, and the sink it reached:

[CRITICAL] ABAP-SQLI-001 — Dynamic WHERE clause from variable [data-flow: confirmed]
      Data flow:
            -> L10  source       lv_where = request->get_form_field( 'q' ).
            => L11  sink         SELECT * FROM mara WHERE (lv_where) INTO TABLE @DATA(lt1).

The same path is emitted in the JSON flow array and as a SARIF codeFlows / threadFlows structure, so GitHub code scanning and SARIF viewers render the source→sink trace inline (as SAP CVA does in-system).

Suppressing false positives

Two complementary mechanisms:

" Inline — suppress on a single line (a comment on the offending line):
SELECT * FROM scarr WHERE (lv_w) INTO TABLE @DATA(t).  "#NOSEC ABAP-SQLI-001
SELECT * FROM scarr WHERE (lv_w) INTO TABLE @DATA(t).  "#NOSEC   (blanket — any rule)
# Baseline — accept all current findings, then only fail on NEW ones (great for
# onboarding the scanner onto an existing codebase without a wall of findings):
python abap_scanner.py ./src --write-baseline .abap-baseline.json   # once
python abap_scanner.py ./src --baseline .abap-baseline.json         # every run after

Baseline fingerprints are line-number-independent (rule + file + normalized code), so edits elsewhere in a file don't resurface accepted findings.

Examples

# Scan a single ABAP file
python abap_scanner.py src/zcl_my_class.clas.abap

# Scan an entire abapGit project
python abap_scanner.py /path/to/abapgit/src --verbose

# Only show CRITICAL and HIGH findings
python abap_scanner.py /path/to/project --severity HIGH

# Scan BTP config files only
python abap_scanner.py /path/to/mta-project/

# BTP API mode with env vars
export BTP_AUTH_URL="https://subdomain.authentication.eu10.hana.ondemand.com"
export BTP_CLIENT_ID="my-client-id"
export BTP_CLIENT_SECRET="my-client-secret"
python abap_scanner.py --severity HIGH --json btp_report.json

# Full dual-mode scan with all reports
python abap_scanner.py ./src \
  --btp-url $BTP_AUTH_URL --client-id $BTP_CLIENT_ID --client-secret $BTP_CLIENT_SECRET \
  --json report.json --html report.html --verbose

Environment Variables

Variable Description
BTP_AUTH_URL BTP XSUAA authentication URL
BTP_CLIENT_ID OAuth 2.0 client ID
BTP_CLIENT_SECRET OAuth 2.0 client secret

Report Formats

Console Output

Colour-coded terminal output sorted by severity, with rule ID, file location, code snippet, CWE reference, description, and fix recommendation. The header shows a security grade (A–F).

Security grade

A weighted A–F grade summarises overall posture at a glance. The scan starts at 100 and deducts per reported finding — CRITICAL 10, HIGH 5, MEDIUM 2, LOW 1, INFO 0 — floored at 0. The score maps to a letter (≥90 A, ≥80 B, ≥70 C, ≥60 D, else F) and appears in the console header, the JSON security_grade block, and an HTML grade card. It reflects findings as reported, so #NOSEC, baseline and --severity filtering all feed into it.

JSON Report (--json)

Structured JSON with metadata, summary counts, and detailed findings array:

{
  "scanner": "SAP ABAP Security Scanner v1.8.0",
  "generated": "2026-03-14T23:00:00",
  "files_scanned": 42,
  "total_findings": 15,
  "summary": {"CRITICAL": 3, "HIGH": 7, "MEDIUM": 4, "LOW": 1, "INFO": 0},
  "owasp_summary": {"A01": 4, "A02": 1, "A03": 7, "A07": 3},
  "security_grade": {"score": 26, "grade": "C", "penalty": 74},
  "findings": [{"...": "...", "cwe": "CWE-89", "owasp": "A03:2021 - Injection"}]
}

HTML Report (--html)

Self-contained interactive HTML report with:

  • Dark theme (Catppuccin Mocha palette)
  • Severity summary cards
  • Interactive filtering by severity, category, and text search
  • Sortable table with code snippets and recommendations

SARIF Report (--sarif)

SARIF 2.1.0 for tool interoperability — upload to GitHub code scanning (findings appear inline on PRs), open in the VS Code SARIF Viewer, or ingest into Azure DevOps / other dashboards. Severity maps to SARIF levels (CRITICAL/HIGH → error, MEDIUM → warning, LOW/INFO → note) and each rule carries a security-severity score and a CWE helpUri. The run also includes an OWASP Top 10 (2021) taxonomies component, and each rule declares a relationships link to its OWASP taxon — so GitHub code scanning and SARIF viewers can group and filter findings by OWASP category.


How It Works

SAST Mode (Passive)

  1. File discovery — recursively walks the target directory, skipping .git, node_modules, etc.
  2. File dispatch — routes files to the appropriate scanner based on extension (.abap → ABAP scanner, .cds → CDS scanner, xs-security.json → config scanner)
  3. Comment-aware parsing — strips ABAP comments (* full-line, " inline) before pattern matching
  4. Regex matching — applies 94 pre-compiled case-insensitive regex patterns line-by-line
  5. Block-aware analysis — carries state across lines to flag whole FUNCTION … ENDFUNCTION blocks that lack an AUTHORITY-CHECK (a check mentioned only in a comment does not count) 5a. Data-flow refinement (optional, --data-flow) — per-procedure taint tracking confirms findings fed by external input and suppresses those with literal/constant or sanitized arguments
  6. Deep JSON inspection — parses xs-security.json to check scope grants and role template wildcards structurally
  7. Version checking — scans for SAP package version references and cross-references against known CVEs
  8. Finding collection — each match creates a Finding with rule ID, severity, CWE, location, and recommendation

BTP API Mode (Active)

  1. OAuth 2.0 authentication — obtains access token from XSUAA using client credentials flow
  2. API enumeration — queries 9 BTP API endpoints (SCIM, role collections, destinations, audit log, etc.)
  3. Policy evaluation — checks settings against security baselines (e.g., min password length ≥ 12, session timeout ≤ 30 min)
  4. User access review — identifies inactive accounts (>90 days), excessive admin privileges, missing MFA
  5. Automatic token refresh — re-authenticates transparently when tokens expire during long scans

Testing with Sample Files

# Run against the intentionally vulnerable test file
python abap_scanner.py tests/samples/vulnerable_abap.abap --verbose

# Expected: 46 findings (15 CRITICAL, 26 HIGH, 4 MEDIUM, 1 LOW)

# Unit tests (no SAP system / network needed)
PYTHONPATH=. python -m pytest tests/ -q
Test File Purpose Expected Findings
tests/samples/vulnerable_abap.abap Intentionally vulnerable ABAP code covering the SAST categories 46
tests/samples/auth_check_blocks.abap Block-level AUTHORITY-CHECK detection (positive + safe + comment-only cases) ABAP-AUTH-001
tests/samples/vulnerable_extra.abap v1.2 extra rules (SQLI-011, AUTH-009, CINJ-009/010, CMDI-005, CRYP-006) 6× extra rules
tests/samples/vulnerable_ui5.js UI5 / JavaScript rules ABAP-JS-*
tests/samples/vulnerable_backdoor.abap Backdoor / malicious-code patterns (hardcoded user checks, auth-table writes, ...) ABAP-BKDR-*
tests/samples/taint_flow.abap Data-flow scopes (tainted / sanitized / literal / unknown sink arguments) 5 → 2 with --data-flow

The suite (83 tests, no SAP system / network required) covers the engine, block scanner, BTP check_func coverage guard, reporting (SARIF / #NOSEC / baseline), scan profiles, the security grade, the OWASP mapping + taxonomy, and the data-flow / taint engine (incl. source→sink traces).


Project Structure

SAP-Code-Vulnerability-Analyzer/
├── abap_scanner.py              # Main scanner (single file, ~3,050 lines)
├── banner.svg                   # Project banner
├── CLAUDE.md                    # AI assistant context
├── LICENSE                      # MIT License
├── README.md                    # This file
├── .gitignore
├── .github/workflows/tests.yml  # CI: pytest matrix (Python 3.10–3.13)
└── tests/
    ├── test_block_scan.py       # block-level AUTHORITY-CHECK + BTP coverage guard
    ├── test_scanner.py          # engine regression locks (counts, rules, CVE, JSON)
    ├── test_reporting.py        # SARIF, inline #NOSEC suppression, baselining
    ├── test_btp_checks.py       # BTP pure evaluators vs synthetic API data
    ├── test_extra_rules.py      # v1.2 extra ABAP rules + UI5/JS scanning
    ├── test_backdoor_rules.py   # backdoor / malicious-code category
    ├── test_profiles.py         # scan profiles + rule selection
    ├── test_grade.py            # weighted A–F security grade
    ├── test_owasp.py            # OWASP Top 10 mapping + SARIF taxonomy
    ├── test_taint.py            # data-flow / taint analysis engine
    └── samples/
        ├── vulnerable_abap.abap       # broad intentional vulnerabilities (46 findings)
        ├── auth_check_blocks.abap     # FUNCTION blocks with/without AUTHORITY-CHECK
        ├── vulnerable_extra.abap      # v1.2 extra rules
        ├── vulnerable_ui5.js          # UI5 / JavaScript rules
        ├── vulnerable_backdoor.abap   # backdoor / malicious-code patterns
        └── taint_flow.abap            # data-flow scopes for --data-flow

CI/CD Integration

The scanner returns exit code 1 when CRITICAL or HIGH findings are detected, making it suitable for CI/CD pipeline gates:

# GitHub Actions example
- name: ABAP Security Scan
  run: |
    python abap_scanner.py ./src --severity HIGH --json abap-report.json
    # Exit code 1 fails the pipeline if CRITICAL/HIGH findings exist
# GitLab CI example
abap_security_scan:
  script:
    - python abap_scanner.py ./src --severity HIGH --json abap-report.json --html abap-report.html
  artifacts:
    paths:
      - abap-report.json
      - abap-report.html
    when: always

Contributing

Adding New SAST Rules

  1. Add the rule dict to the appropriate ABAP_*_RULES list in abap_scanner.py
  2. Follow the ID pattern: ABAP-{CATEGORY}-{NNN}
  3. Include all required fields: id, category, severity, name, pattern, description, cwe, recommendation
  4. Test with: python abap_scanner.py tests/samples/vulnerable_abap.abap --verbose

Adding New BTP API Checks

  1. Add the check definition to BTP_API_CHECKS
  2. Implement the _check_* method in AbapBtpScanner
  3. Follow the ID pattern: ABAP-BTP-{CATEGORY}-{NNN}

License

This project is licensed under the MIT License.

Releases

No releases published

Packages

 
 
 

Contributors