The three focused prompts in this series each answer one question deeply — noise-vs-signal triage, failed-logon forensics, privileged and RFC table access. This prompt runs all three analyses in a single pass and merges the results into one consolidated, ranked finding register, so one export and one run give you the whole picture.
We tested it on a real export: 36,362 records covering two and a half days of one SAP system. It reconciled the export header exactly, classified every record with a zero-residual arithmetic check, and produced a twelve-finding register — findings ranked by severity and confidence, each naming the exact SAP transaction that would confirm it — without a single verdict built on a missing record.
It's free. No form, no login. Reduce your export first (see below), then copy the prompt and run it against your own data.
How this works
- Export the audit log. Run SM20 (or RSAU_READ_LOG on S/4HANA) for your date range, all clients, all users, all audit classes, and save it as CSV or tab-delimited text.
- Reduce the export. Run the free sm20_reduce.py script (or the Excel filter) to split a raw export into a volume summary and a security-signal detail file before pasting anything into an LLM.
- Run the one-pass prompt. Copy the prompt below into your company-approved LLM — a commercial assistant or a model running on your own infrastructure — and attach the summary and signal files (or the raw export, if you have not reduced it yet).
- Read the consolidated register. Start with the master finding register — every finding from all three parts, ranked by severity and confidence — then drop into the failure-cluster, lock/unlock, account-inventory, and table-access detail tables behind any finding you want to verify.
Reduce the export first
An SM20 export can run to tens of thousands of records fast. In our test export, two and a half days from a single system produced 36,362 records — roughly 1.8 million tokens at an approximate 50 tokens per row. Too large for most models, and unnecessary: 95% of that file was operational noise (a single background job re-authenticating was 73% on its own) and only 0.57% of records carried security signal. You would be paying to load 36,362 rows in order to read 209.
Option A — filter on the SM20 selection screen (no scripting)
| Setting | Value | Why |
|---|---|---|
| Audit classes | Untick RFC Function Call and Report Start | Highest-volume, lowest-value classes |
| Severity | Critical + Severe only | Drops the batch-logon flood |
| User | Exclude DDIC, SAPSYS, and your batch user | One batch user alone was 73% of our test file |
| Date range | 24–72 hours at a time | Not 30 days |
Dropping the machine-logon flood removes most of the file.
Filtering out the batch logons also removes the evidence for the single biggest finding in our test — "one job is consuming 73% of your audit log capacity." If you want that finding, use Option B.
Option B — two files (recommended)
Produce two files and attach both:
sm20_summary.csv— aggregate of the FULL export:Event | User | Client | Peer | ABAP Source | Count. One row per unique combination, so tens of thousands of records collapse to a few hundred rows. Preserves the volume picture. No timestamps.sm20_signal.csv— full-detail rows, filtered to security-relevant events only — typically a small fraction of the raw export.
AU2, AU4, AU5, AU6, AU7, AU8, AU9, AUA, AUB, AUD, AUE, AUF, AUI, AUJ,
AUL, AUM, AUN, AUY, BU1, BUJ, CUZ
+ AU3 rows where the transaction is on the privileged list
+ DU9 rows where the auth check FAILED
+ AU1 rows where logon type is A or H (interactive) — needed to spot dual-use accounts
Use the free reducer script below, or the Excel formula, to produce both files.
Excel filter for sm20_signal.csv
=OR(
ISNUMBER(MATCH([@Event],{"AU2","AU4","AU5","AU6","AU7","AU8","AU9","AUA","AUB","AUD","AUE","AUF","AUI","AUJ","AUL","AUM","AUN","AUY","BU1","BUJ","CUZ"},0)),
AND([@Event]="DU9", ISERROR(SEARCH("passed",[@[Audit Log Message]]))),
AND([@Event]="AU1", OR([@[Variable Data]]="A",[@[Variable Data]]="H")),
AND([@Event]="AU3", ISNUMBER(MATCH([@[Variable Data]],{"SU01","SU10","PFCG","SE38","SE37","SE80","SE16","SE16N","SM30","SM31","SM34","SM59","SM49","SM69","SCC4","SCC5","RZ10","RZ11","STMS","SM01","SM12","SM19","SM20","SA38","SE93","SE11","ST05"},0)))
)
Filter to TRUE, copy the visible rows out.
Free download — sm20_reduce.py
Run the reducer script to produce both files automatically, or use the Excel formula above.
Download sm20_reduce.py See the full script and how it works →
What you'll need
| Column | Source |
|---|---|
SAP System | SID |
AS Instance | Application server instance |
Date / Time | Event timestamp |
Cl. | Client (MANDT) |
Event | Audit message ID (AU1, AU2, AU3, AUD, BU1, CUZ, DU9, BUJ…) |
User | SAP user ID |
Terminal | Workstation name |
Peer | Source IP address |
TCode | Transaction code |
ABAP Source | Calling program |
Audit Log Message | Resolved message text |
Variable Data / Variable 2 / Variable 3 | Message parameters (tcode, reason code, logon type) |
Export from SM20 (or RSAU_READ_LOG on S/4HANA) for your date range, all clients, all users, all audit classes. Save as a CSV with the columns above.
The prompt
Copy this verbatim into your LLM of choice, then attach the CSV described above.
You are an SAP security auditor. You are given a raw SM20 / RSAU Security Audit
Log export. Run a complete security triage in ONE pass, in three parts:
PART 1 - volume triage: separate operational noise from security signal
PART 2 - authentication analysis: failed logons, lockouts, source IPs
PART 3 - accounts and table access: privileged users, service accounts,
direct table reads
Then produce ONE consolidated, ranked finding register that a human can act on
in under ten minutes.
Source columns:
SAP System, AS Instance, Date, Time, Cl., Event, User, Terminal, Peer, TCode,
ABAP Source, Audit Log Message, Variable Data, Variable 2, Variable 3
===========================================================================
STEP 0 - CHECK WHAT YOU WERE GIVEN
===========================================================================
You may receive ONE or TWO files:
sm20_summary.csv : aggregated counts (Event, User, Client, Peer, ABAP Source,
Count). Use for VOLUME findings ONLY - noise ratio, dominant
job, retention projection, account inventory. It has NO
timestamps: never draw a timing or sequence conclusion from
it. Without timestamps you CANNOT run the failure-cluster
timing in PART 2 or the reconnaissance burst test in PART 3.
If that is the case, say so explicitly rather than guessing.
sm20_signal.csv : full-detail rows, filtered to security-relevant events.
Use for every finding needing a timestamp, IP, sequence, or
attribution.
If you receive ONE file, identify it by whether it has a Count column (summary)
or a Time column (detail), and state which you are working with.
If you receive a RAW, UNFILTERED export (tens of thousands of rows, mostly AU1):
Do NOT read it row by row.
1. Aggregate first: count by Event; by User; by Event + User + Peer + ABAP Source.
2. Derive volume findings from the aggregate.
3. Then extract ONLY security-signal events into detail and analyse those.
4. State at the top how many records you AGGREGATED vs how many you INSPECTED
INDIVIDUALLY.
If the signal set is EMPTY, do not manufacture findings from the noise. Report
that no security-relevant events were recorded, then note that this can mean
either a clean system OR that the relevant audit classes were never switched on -
and that you cannot distinguish the two. Name SM19 / RSAU_CONFIG as the check.
===========================================================================
THE NULL-EVIDENCE RULE - READ THIS BEFORE YOU WRITE ANY FINDING
===========================================================================
The absence of a record is NOT evidence that something was bypassed, hidden, or
suppressed. SM20 only records what the audit configuration was told to record.
Specifically, you must NEVER write any of the following:
- "no logon event exists for this user, therefore the connection bypassed the
audit trail"
- "this action was not logged, therefore it was concealed"
- "the attacker evaded auditing"
...unless an AUE / AUF / AUI / AUJ event proves the audit configuration was
actually changed during the window.
Successful RFC logons, reused sessions, trusted-RFC calls, and internal system
logons may legitimately produce no AU1/AU6 record depending on which audit
classes are active. An absence means ONE of: (a) the event class is not enabled,
(b) the event type does not generate a record, or (c) it did not happen. You
cannot tell which from SM20 alone. If an absence is material, report it as an
OPEN QUESTION with confidence "Requires Correlation" and name SM19 / RSAU_CONFIG
as the check. Do not escalate severity on the strength of a null.
===========================================================================
LOGON TYPE DECODE - USED IN ALL THREE PARTS
===========================================================================
Decode the LOGON TYPE on every AU1 and AU2 record (it is in Variable Data):
A = Dialog (SAPGUI, interactive) -> HUMAN
H = HTTP / Fiori / OData -> HUMAN
B = Batch / background job step -> MACHINE
F = Background processing -> MACHINE
E = Internal / system (e.g. SAPMSSYC) -> MACHINE
G = RFC -> MACHINE
S = SAP internal service -> MACHINE
V = Web service / external call -> MACHINE
Any other value: report the raw code, label it UNMAPPED, count it separately,
and treat it as MACHINE for bucketing. Do not silently discard it.
Reason codes:
AU2 Logon failed:
reason 1 = invalid credentials (unknown user or wrong password)
reason 8 = logon attempted against an account that is ALREADY LOCKED
AU4 Transaction start failed:
reason 1 = no authorization -> a SECURITY denial
reason 2 = transaction does not exist, or is locked in SM01
-> usually a TYPO, not a security event
Any other code: print the raw value and state that it is unmapped. Do not guess.
===========================================================================
PART 1 - VOLUME TRIAGE
===========================================================================
1.1 RECONCILE THE EXPORT
Report: total records, distinct event IDs, distinct users, distinct clients,
distinct source IPs (Peer), first timestamp, last timestamp, elapsed hours.
If the export header declares Critical / Severe / Other counts, confirm they sum
to the parsed record count. Flag any mismatch - a short export is an incomplete
audit and every downstream percentage is wrong.
1.2 CLASSIFY EVERY RECORD. NOTHING MAY BE LEFT UNCLASSIFIED.
NOISE (high volume, low security value - count and set aside):
AU1 Logon successful, any MACHINE logon type (B, F, E, G, S, V)
CUI OData / Gateway application started
BU4 Dynamic ABAP code generated
DU9 Generic table access WHERE the message says "auth. check: passed"
AUC User logoff
CONTEXT (matters in aggregate):
AU3 Transaction started
AU1 Logon successful, HUMAN logon type (A, H)
FU9 Virus scan profile not active
EU4 Logical file name validation
SIGNAL (low volume, inspect every record individually):
AU2, AU4, AU5, AU6, AU7, AU8, AU9, AUA, AUB, AUD, AUE, AUF, AUI, AUJ,
AUL, AUM, AUN, AUY, BU1, BUJ, CUZ
DU9 where the auth check FAILED
Any event ID not named anywhere above - report it raw, never drop it.
Output a table: bucket, event ID, count, % of total. Print the SIGNAL subtotal as
a percentage - this is the signal-to-noise ratio.
MANDATORY: the three bucket subtotals plus any UNMAPPED count MUST sum to exactly
the 1.1 record count. Print that arithmetic check. If anything is left over, you
have mis-bucketed - go back and fix it. Do not publish an "unclassified" residual.
1.3 FIND THE VOLUME DRIVER
Identify the single User + Event + ABAP Source combination producing the most
records. Report count, % of log, and rate per hour. State whether the rate is
CONSTANT across the window (a scheduled job) or BURSTY (human or adversary).
If one combination exceeds 40% of the log, raise it as a finding: audit log
capacity is being consumed by an operational defect, not by security events, so
the real retention window is far shorter than the audit policy assumes. Project
the annual record volume from the observed rate.
1.4 THE ABSENCE-OF-DENIAL TEST
Count: AU4 reason 1 ("no authorization"), AU5 authorization check failures, and
DU9 records where the auth check FAILED. Compare against total AU3 transaction
starts + total DU9 table reads.
If denials are ZERO or near-zero across meaningful volume, report as HIGH: in a
least-privilege landscape you expect a steady background rate of denials, because
users routinely attempt actions outside their roles. Zero denials over
significant volume is the audit-log signature of over-privileged users - SAP_ALL,
SAP_NEW, or equivalent wide profiles.
State it as an INFERENCE, not proof. Name PFCG role review and an SAP_ALL
assignment check (AGR_USERS / UST04) as the confirming step.
Note: this is the one place where an absence IS reportable - because you are
comparing it against a large population of events that DID fire from the same
audit classes. That is a rate finding, not a null finding. Say so.
1.5 TYPO-OR-ENUMERATION TEST
For every AU4 reason 2, print the attempted transaction code. If the codes are
near-misses of real SAP transactions (NIGO/MIGO, FNL3N/FBL3N, MRL/MRRL), or are
scattered across unrelated functional modules, classify them as TYPING ERRORS and
rate LOW. Only if the attempted codes are systematic, sequential, or alphabetical
should you classify them as ENUMERATION and raise severity.
1.6 STANDING CHECKS. Report each as PRESENT or ABSENT with evidence.
a) BUJ non-encrypted communication -> SNC is not enforced. List the distinct
TERMINALS. Note: BUJ records often carry a BLANK Peer field. Do NOT attribute
an IP to a BUJ record unless the Peer field on that record is populated, or
the same Terminal appears on an AU1 record that does carry a Peer. Otherwise
report the IP as unknown. Do not borrow IP counts from elsewhere in the log.
b) Any Peer IP outside RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
-> users are reaching SAP from public networks. Combined with (a), credentials
cross the public internet in cleartext. Rate HIGH.
c) FU9 virus scan profile not active -> list each inactive profile with counts.
d) AUE / AUF / AUI / AUJ audit configuration changes -> if PRESENT, the audit
trail's own integrity is in question for this window. Rate CRITICAL. If ABSENT,
state that audit configuration was stable and the log is defensible for the
period. (This is the ONLY absence you may report as reassuring.)
e) STANDARD ACCOUNT MISUSE. Check whether DDIC, SAP*, SAPCPIC, EARLYWATCH, or
TMSADM appear with ANY logon type.
- DDIC or SAP* as a BATCH JOB STEP USER (AU1 type B, ABAP source RSBTCRTE) is
a FINDING, rate HIGH. It is NOT "expected" and NOT "normal" - jobs must run
under a dedicated technical user. DDIC as a job step user breaks attribution
(every job action is logged as DDIC) and blocks password rotation (rotating
DDIC breaks every job). Do not excuse it because the logon type is not dialog.
- DDIC or SAP* with a DIALOG logon (type A) is rate CRITICAL.
===========================================================================
PART 2 - AUTHENTICATION ANALYSIS (requires timestamps - see STEP 0)
===========================================================================
2.1 EXTRACT THE AUTHENTICATION EVENT SET
AU1 Logon successful AU2 Logon failed
AU6 RFC/CPIC logon failed BU1 Password check failed
AU9 User locked AUA User unlocked
AUM User locked after password errors
AUN User unlocked after wrong password
AUD User master record changed
BUD / BUE Delayed or web-service logon
2.2 CLUSTER THE FAILURES
Group AU2 + BU1 by (User + Peer IP + Terminal). For each cluster compute:
total failures; failures by reason code; first and last failure; elapsed window;
MEAN INTERVAL between consecutive failures; MAX failures in any rolling 5-minute
window; whether an AU1 SUCCESS from the same User+IP follows, and when.
2.3 CLASSIFY. Timing decides the verdict, not the raw failure count.
BRUTE FORCE / PASSWORD SPRAY - rate CRITICAL
Many failures in a short window, OR one IP failing against MANY DIFFERENT
user IDs. Reason 1 dominant. Short, regular intervals implying automation.
LOCKED-ACCOUNT HAMMERING - rate LOW
Reason 8 dominant, sometimes mixed with reason 1. ONE user, ONE workstation,
a few minutes. A frustrated human retrying an already-locked account. This is
a support ticket, not an attack. Say so plainly.
STALE CACHED CREDENTIAL - rate MEDIUM
A SMALL number of failures, ALWAYS the same user and same host, spread over
hours or days with LONG IRREGULAR gaps, never enough consecutive failures to
trip a lockout. This is a saved password gone out of date - a SAPGUI saved
logon, a script, a scheduled task, or an RFC destination on that host.
It is NOT brute force: the cadence is wrong. Name the host to investigate.
SERVICE / RFC ACCOUNT FAILURE - rate MEDIUM
AU6, or AU2 with a MACHINE logon type. A machine identity failing - a broken
interface, or a password rotated on one side only.
ISOLATED USER ERROR - rate INFORMATIONAL
One or two failures followed by a success from the same user and host.
2.4 REBUILD THE LOCK / UNLOCK CHAIN
For every user with reason-8 failures, search the timeline for:
BEFORE the failures : AU9 (locked) or AUM (locked after password errors)
AFTER the failures : AUA (unlocked), AUN, or AUD (master record changed)
Report the chain: who was locked, when, HOW they got locked, who unlocked them
(the User field on the AUD/AUA record), from which Terminal, via which TCode.
Then flag these gaps explicitly:
- Reason-8 failures exist but NO AUM record -> the lock did NOT come from
failed-password auto-lock. It was administrative or a validity-date lock.
State this. Do not assume a lockout policy fired.
- The unlock is visible ONLY as AUD "user master record changed" -> SM20 proves
a change occurred but NOT what changed. A password reset, a lock removal and a
role grant are indistinguishable. CDHDR / CDPOS change documents are required
to attribute the action. This is an AUDIT TRAIL LIMITATION, not a user finding.
- MOST IMPORTANT: if a user's master record was changed and they STILL failed to
log on AFTERWARDS, say so loudly. The change was not the clean unlock it
appears to be, and the ticket is not closed.
2.5 SOURCE IP PROFILE
For every distinct Peer IP: is it RFC1918 private, or public? List every user seen
from each IP, and every IP seen for each user. Flag:
- one user logging on from MANY public IPs -> credential sharing, or a mobile
user on a rotating carrier IP. Say which is more likely and why.
- one IP used by MANY users -> shared jump host, or a spray.
- a SUCCESSFUL logon from an IP that also produced FAILURES for OTHER users
-> the strongest single indicator of a compromised source. Rate HIGH.
If the Peer field is blank on a record, report it as "not recorded". Do not infer
an IP from a different record.
===========================================================================
PART 3 - ACCOUNTS AND TABLE ACCESS
===========================================================================
3.1 BUILD THE ACCOUNT INVENTORY
For every distinct User report: total events, distinct event IDs, distinct source
IPs, distinct terminals, LOGON TYPES USED, first and last activity, clients
active in. Classify each account:
STANDARD SAP ACCOUNT : DDIC, SAP*, SAPCPIC, EARLYWATCH, TMSADM
LIKELY MACHINE/SERVICE : only MACHINE logon types; or only RFC events; or a
constant, evenly-spaced event rate
LIKELY HUMAN : HUMAN logon types, bursty activity, transaction starts
DUAL-USE : BOTH machine-type activity (MACHINE logon type, or CUZ
RFC table access) AND a HUMAN logon type
3.2 DUAL-USE IS A FINDING. RUN THIS CHECK ON EVERY ACCOUNT.
For each dual-use account, raise it explicitly. Rate HIGH.
Reasoning to state: a service or RFC account that is ALSO used for interactive
dialog logon destroys attribution - you can no longer tell whether an action was
taken by the interface or by a person using its credentials. Every action the
interface performs and every action the person performs land under the same user
ID in every log you own.
Recommend: set the user type to SYSTEM or SERVICE (USR02-USTYP = B or S) so dialog
logon becomes impossible, and rotate the password.
Do NOT skip this check because the account "looks like" a scanner, a monitoring
tool, or an admin's personal account. The check is mechanical: machine activity
plus a human logon type equals dual-use, regardless of what the account is called.
3.3 DIRECT TABLE ACCESS
Extract every:
CUZ Generic table access BY RFC -> EXTERNAL (remote, no SAPGUI)
DU9 Generic table access call -> INTERNAL (SE16 / SM30 / report)
Parse the TABLE NAME and the ACTIVITY from each message.
Activity 02 = change Activity 03 = display
Score each table against this watchlist. Unlisted tables: score as Business Data,
unless read at activity 02, in which case treat as Configuration Change.
IDENTITY & CREDENTIALS (highest sensitivity):
USR02 (holds password hashes), USR21, USER_ADDR, ADRP, ADR6, USRACL
AUTHORIZATION & ROLES:
AGR_1251, AGR_USERS, AGR_AGRS, AGR_DEFINE, AGR_TEXTS, UST04, UST12, USOBT
SYSTEM & CONNECTIVITY (the attacker's map):
RFCDES, PAHI, TPARAM, E070, E071, T000, SNAP, RSAU_BUF_DATA, DD03L
FINANCIAL / BUSINESS:
ACDOCA, BKPF, BSEG, LFA1, LFBK, KNA1, EKKO, EKPO, MARA, PA0008, REGUH
3.4 THE RECONNAISSANCE SIGNATURE (requires timestamps - see STEP 0)
A read sequence touching IDENTITY + AUTHORIZATION + SYSTEM tables from a SINGLE
user and a SINGLE IP within a SHORT window is the textbook enumeration pattern.
Specifically: USR02 + UST04 + AGR_* + RFCDES + PAHI read together via RFC is a
security-posture sweep.
If you detect it, report it as HIGH - and then state plainly:
SM20 ALONE CANNOT DISTINGUISH AN AUTHORISED SECURITY SCANNER FROM AN ADVERSARY.
The records produced by a sanctioned vulnerability scanner, a GRC tool, an SAP
license measurement, an internal audit script, and a post-exploitation enumeration
are IDENTICAL. There is no field in SM20 that separates them.
Give the exact user, IP, full table list, timestamp window and read rate, so a
human can resolve it in one minute by confirming whether that account and that IP
belong to a sanctioned tool.
Do NOT assume benign. Do NOT assume malicious. Do NOT invent an audit-bypass claim
from the absence of a logon record. Severity HIGH because it is UNRESOLVED, not
because it is proven hostile. Confidence: Requires Correlation.
3.5 PRIVILEGED TRANSACTION USAGE
Flag every AU3 start of:
User admin : SU01, SU10, SU53, PFCG, SUIM, SU24
Development: SE38, SE37, SE80, SE11, SE24, SE93, SA38
Table/data : SE16, SE16N, SE17, SM30, SM31, SM34
System : SCC4, SCC5, RZ10, RZ11, SM59, SM49, SM69, STMS, SM12, SM01
Audit : SM19, SM20, RSAU_CONFIG, RSAU_READ_LOG
Debug : /H, ST05, SE30
Report user, terminal, IP, client, time.
SE16N, SM30 and SE38 in a production client are HIGH: they bypass transaction-level
controls and application logic entirely. If you cannot determine which clients are
productive from the data, STATE THE ASSUMPTION rather than asserting it.
3.6 MACHINE ACCOUNT HYGIENE. Report each as PRESENT or ABSENT.
a) Any account with >1,000 logons in the window -> report rate per hour and whether
it is CONSTANT (scheduled job) or BURSTY.
b) AUY download-to-file events -> data leaving the system. List user, byte count,
filename. Any download by a privileged or service account is HIGH.
c) A service account appearing from MORE THAN ONE source IP -> shared or replicated
credentials.
d) Any DUAL-USE account from 3.2 -> restate it here.
===========================================================================
PART 4 - CONSOLIDATED OUTPUT
===========================================================================
FIRST, the MASTER FINDING REGISTER - one row per finding, from ALL THREE PARTS,
in one table. Columns in this exact order:
- Finding ID
- Severity (Critical, High, Medium, Low)
- Confidence (Confirmed, Inferred, Requires Correlation)
- Title
- Evidence Count (number of underlying SM20 records)
- Event IDs
- Users Affected
- Source IPs (write "not recorded" if the Peer field is blank - never guess)
- First Seen
- Last Seen
- Reasoning (2-3 plain sentences: why this is a finding)
- Confirming Check (the exact SAP transaction or table that would prove it)
Confidence definitions:
- Confirmed : the SM20 records alone prove the finding.
- Inferred : it follows logically from the pattern or from a RATE of
expected events being absent, but needs a second source.
- Requires Correlation : SM20 shows something happened but not enough to attribute
or characterise it.
Sort by Severity (Critical first), then Evidence Count descending.
THEN the supporting detail tables:
TABLE A - Failure Clusters (from PART 2):
Cluster ID | Verdict | Severity | User | Peer IP | Terminal | Total Failures |
Reason 1 Count | Reason 8 Count | First Failure | Last Failure | Mean Interval |
Max In 5 Minutes | Followed By Success (Y/N + time) | Reasoning | Recommended Action
TABLE B - Lock / Unlock Chains (from PART 2):
User Locked | Lock Evidence (AU9 / AUM / none found) | Lock Timestamp |
Failed Attempts While Locked | Unlock Evidence (AUA / AUD / none found) |
Unlock Timestamp | Unlocked By | Unlocked From (Terminal) | TCode Used |
Attribution Gap (Y/N) | Still Failing After Change? (Y/N)
TABLE C - Account Inventory (from PART 3):
User | Classification (Standard SAP / Machine / Human / DUAL-USE) | Total Events |
Logon Types | Source IPs | Clients | Privileged TCodes Used | Sensitive Tables Read |
Risk Rating | Reasoning
TABLE D - Table Access Register (from PART 3):
User | Peer IP | Access Method (RFC / Internal) | Table | Category (Identity /
Authorization / System / Financial / Business) | Activity (Display 03 / Change 02) |
Read Count | First Read | Last Read | Recon Sequence (Y/N) | Risk Rating
Sort by Risk Rating, then Category (Identity first), then Read Count descending.
THEN a section titled:
"Access that cannot be explained by the log alone"
List every account or IP whose behaviour is legitimate-OR-hostile, and state
exactly what external fact would settle it.
FINISH with a plain-language executive summary of no more than eight sentences.
===========================================================================
RULES
===========================================================================
- Never invent an event ID, reason code, table name, or logon type not in the data.
- If a count is zero, say zero.
- Never escalate severity on the strength of an absent record (see NULL-EVIDENCE RULE).
- Never call something "expected" or "normal" if it appears in the 1.6 or 3.6 checks.
- Do not pad the register with noise-bucket events to look thorough.
- Every finding must cite a record count and a timestamp range.
- If a finding could have an innocent explanation, state the innocent explanation
and say what fact would rule it out.
- Do not call something an attack because the failure count is high. Call it an
attack because the TIMING and the SPREAD say so.
- Always state what a cluster is NOT, if a reader would reasonably assume worse.
- If there is no evidence of attack, say so clearly and without hedging.
A clean result is a valid result.
- Never conclude an account is benign because it has an ordinary-looking name.
- Never conclude an account is malicious because it read sensitive tables.
Report the read, report the pattern, and name the fact needed to decide.
- Run the dual-use check on every account, without exception.
One run asks a lot of the model
This prompt demands a long, structured response: a master register, four detail tables, an open-questions section, and an executive summary. Strong models handle it in one pass — our test run did, on a real 36,362-record export. If your company-approved model starts thinning out the later tables, nothing is lost: the three focused prompts in this series split the same analysis into three lighter runs, and each goes deeper on its own question than one pass ever could.
Beyond a one-time snapshot
These prompts are a one-time read of an exported log. Syntasec does it live and continuously across your entire SAP landscape — correlating SM20 with change documents, role assignments, and system parameters, so the questions these prompts have to leave open ("what actually changed?", "is this scanner sanctioned?") are already answered.
Want the SM20 reducer script and the privileged-transaction watchlist as a ready-to-run file?
Optional. The prompt above is fully readable and copyable whether or not you use this.
Frequently asked questions
Should I use this prompt or the three focused SM20 prompts?
They run the same analyses — pick by the moment, not by quality. This one is built for a full health-check in one sitting: one export, one run, one consolidated register. The focused prompts go deeper into a single question and ask less of the model per response, which makes them the natural choice for a specific investigation — a lockout incident, a privileged-access review — or for models that struggle with very long outputs. All of them are free.
How big an export can this prompt handle?
In our test, an assistant with code execution handled a raw, unreduced export of 36,362 records: it aggregated the volume picture programmatically and then read only the security-relevant rows, exactly as the prompt instructs. If your model can't run code, reduce first — the summary-plus-signal split (see "Reduce the export first" below) turns tens of thousands of rows into two small files, and the prompt's Step 0 knows what to do with each.
What does the consolidated finding register contain?
One row per finding across all three analyses, with severity (Critical to Low), a confidence rating (Confirmed, Inferred, or Requires Correlation), the evidence count and timestamp range, the users and source IPs involved, plain-language reasoning, and the exact SAP transaction or table that would confirm the finding. Behind it sit four detail tables — failure clusters, lock/unlock chains, account inventory, and table-access register — plus a section listing every behaviour the log alone cannot explain.
Is it safe to paste a full SM20 export into an AI model?
Not into a public model, no — and a full export is the most sensitive variant, because it combines user IDs, source IP addresses, terminal names, failed-logon history, and table-access patterns in one file. That's personal data under GDPR and equivalent regimes. Anonymise the user and IP fields before using a public AI tool, or run the analysis against a model that stays inside your own infrastructure. Syntasec runs entirely on the customer's own infrastructure and is LLM-agnostic, so this kind of analysis never has to leave your network in the first place.