Whatiftheattackerneverknewtheworldchanged?

Every session sandboxed, continuously scored, and converted in place . They keep the session, and lose the world behind it.

L2 · Session risk over timeRISK 0–100
0255075100THRESHOLD T = 70T1552.005 T1090 → CONVERTRECON → ENUMERATION → EXPLOITDECEPTION24 observations over 257s · half-life 180s

The score decays. Evidence has to keep arriving.

L2 · score field at conversion
100%of inbound sessions sandboxed

The management path is never touched. The session survives.

Egress after conversionDENY

Ten layers, L0 ingress through L9 console

asyncioDocker SDKRedis StreamsPostgresasyncsshJA4 / HASSHMITRE ATT&CKGeoLite2

Risk is a surface, not a switch.

A session's score is a point moving over a field of weighted behavioural evidence. Early on the field is noise, because nothing has converged and nothing should. As recon turns into enumeration and enumeration into exploitation, the surface deepens into a basin, and the trajectory falls into it.

NORMALt+40s · risk 12
$ cat /etc/passwd

Broadband noise, no basin. Weak passive priors only: GeoIP, JA4, HASSH, reputation. None of it is a verdict.

SUSPICIOUSt+130s · risk 45
$ grep -rIl 'PASSWORD\|SECRET' /srv /opt

Evidence accumulating faster than it decays. A minimum is forming, but the session keeps full backend reachability.

DECEPTIONt+195s · risk 98
$ cat /etc/shadow

The basin is decisive and the trajectory has crossed T. Conversion fires, and scoring carries on afterwards.

Watch it happen.

One recorded session, replayed against the live scoring rule. The commands, the weights and the moment the score crosses T are all read from the model. The playback only controls when each observation appears. Watch the right-hand column at the crossing: the backend swaps, and nothing about the session does.

CONNECTRECONENUMERATIONEXPLOITDECEPTION
L5 · live PTYSSH ACTIVE
000s$ssh deploy@10.0.4.19
L2 · session risk0
0T = 70100
L4 · reachable backendsbackend_net
mysql.internalReal MySQL
redis.internalReal Redis
api.internalReal REST API
/run/secretsMounted
egressPermitted

Same container, real internal services. Nothing has crossed the threshold yet.

t+0sREAL BACKENDS REACHABLE

Mostsystemsblocktheattacker,ormovethemsomewhereelse.SentinelXmovestheworldinstead.Samecontainer,samePIDs,sameshellhistory,butadifferentnetworktoreach.

Relocation leaks. ls, uptime, /proc, the process tree, the files they already dropped: any one of them gives away the move to a honeypot. Staying put is the deception.

What happens behind the session?

L1 · UNIVERSAL SANDBOXING10.0.0.17sx-7f3a9110.0.1.30sx-7f4b0410.0.2.43sx-7f5b7710.0.3.56sx-7f6bea10.0.4.69sx-7f7c5d10.0.5.82sx-7f8cd0PRODUCTION / UNREACHEDcontainerise first, decide later

Every inbound session is containerised before anything is known about it. The safe boundary is not something switched on once a connection starts to look bad.

asyncioDocker SDKRedis StreamsPostgresasyncsshJA4 / HASSHMITRE ATT&CKGeoLite2

Continuity you can inspect.

Every conversion is written to the event log with the network state before and after. None of it is reconstructed later for the timeline.

Preserved
PID 412

The same shell process, either side of conversion

Backend reachability

At threshold T
SWAPPED

backend_net detached, deception_net attached, container untouched

session containersx-7f3a91cunchanged

Real secrets reachable after conversion

NONE
Read the conversion spec

Same container. Different world.

Nothing about the attacker's local state changes. The management network is deliberately untouched, so the live SSH session never drops.

BEFOREmgmt_net + backend_net
mysql.internalReal MySQL
redis.internalReal Redis
api.internalReal REST API
/run/secretsMounted
egressPermitted
  1. 01docker network disconnect backend_net
  2. 02docker network connect deception_net
  3. 03umount /run/secrets
  4. 04egress policy default-deny
AFTERmgmt_net + deception_net
mysql.internalSynthetic MySQL
redis.internalSynthetic Redis
api.internalSynthetic REST API
/run/secretsUnmounted
egressDefault-deny
SSH session never drops

Everything else is identical either side: PID 412 bash and PID 431 curl are the same processes, cwd is still /home/deploy, shell history, env vars, dropped files and uptime in /proc all read exactly as they did a second earlier.

Four breaches, and where the session would have gone instead.

Each of these had a live session doing observable things inside someone's network. The left column is public post-incident reporting. The right is what this design is built to do against the same behaviour.

A server-side request forgery reached the cloud metadata service, and the credentials it returned were real.

What happened
  1. 01A misconfigured web application firewall on an EC2 instance could be induced to make requests on the attacker's behalf.
  2. 02Those requests reached the instance metadata service at 169.254.169.254 and returned temporary IAM credentials.
  3. 03The credentials were used to list and copy customer data out of S3, around a hundred million records.
  4. 04Discovery came months later from an external tip, not from internal telemetry.
What SentinelX is built to do
  1. 01SSRF and a cloud metadata request are two of the heaviest single heuristics in the set, at w11 and w12, and they fire together here. Combined with the enumeration that precedes them, that is a threshold crossing, not a warning.
  2. 02A fake metadata service at 169.254.169.254 is one of the four deception backends by design. After conversion the same request to the same address still answers; the IAM credentials it returns are synthetic.
  3. 03Default-deny egress is applied in the same sequence. The bulk copy out has somewhere to read from and nowhere to send.

The request still succeeds. What comes back is fabricated, and what leaves is nothing.

Where it would not have helped

SentinelX does not fix the WAF misconfiguration that made the SSRF reachable. It changes what the SSRF is worth.

Design claims, not measured results. SentinelX does not patch vulnerabilities and would not have prevented these breaches. It contains the session that exploits one, and keeps the record. Each case states where it would not have helped.

Read the threat model

The three mechanisms

All ten layers
L5 · PTY TRANSCRIPTRISK083s$systemctl list-units --type=servi…+527096s$for p in 3306 6379 8080; do nc -z…+733112s$find / -perm -4000 -type f 2>/dev…+839128s$grep -rIl 'PASSWORD\|SECRET' /srv…+945141s$cat /srv/app/.env+952152s$find /home -name 'id_*' -o -name …+1060166s$curl -s 169.254.169.254/latest/me…+2380178s$curl 'api.internal/report?id=1%20…+1490189s$cat /etc/shadow+1198
L2 · Risk engineContinuous + request-level

A score that decays

Suspicious evidence raises the score; time and benign behaviour lower it again. Cumulative scoring catches the slow campaign, synchronous request checks catch the single shot.

~30weighted behavioural heuristics
Read the layer spec
L4 · IN-PLACE CONVERSIONmgmt_netnever modifiedsx-7f3a91cPID 412 · cwd /home/deploybackend_netmysql.internalredis.internalapi.internaldeception_netmysql.internalredis.internalapi.internalegress: default-denysame hostnames
L4 · ConversionIn place, mid-session

The backend swap

Four ordered operations inside one running container. The management network is not one of them, which is exactly why the terminal on the attacker's screen never so much as stutters.

0sessions relocated or disconnected
Read the layer spec

The shape of the system

0%

Of inbound sessions sandboxed before any verdict is formed

~0

Weighted heuristics scoring every live session, continuously

0

LLM call per session, downstream, and never an actuator

Some attacks never climb the curve.

A single-shot injection can finish before cumulative behaviour has moved the score at all. Those are caught synchronously, per request, alongside the continuous score. Each surface below is the same score field with only one tactic's heuristics active. Discovery is wide and shallow. Execution is a narrow spike.

Execution

7 rules · peak T1190 w14

Credential access

5 rules · peak T1552.005 w12

Discovery

10 rules · peak T1046 w7

Persistence

4 rules · peak T1098.004 w12

Privilege escalation

3 rules · peak T1068 w13

Exfil & evasion

4 rules · peak T1041 w12

How conversion runs.

Four ordered operations, inside one container that stays exactly where it is.

EVENT STORE · REDIS STREAMS → POSTGRES{"type":"DECEPTION_CONVERSION""phase":"DECEPTION""session_id":"sx-7f3a91c""risk_before":74.0"risk_after":74.0"network_before":["mgmt_net","backend_net"]"network_after":["mgmt_net","deception_net"]"secrets_unmounted":true"egress_policy":"default-deny"}risk unchanged, conversion is a state transition
0

Ordered operations in the sequence. The management network is deliberately not one of them.

Conversion sequence
01

Detach

docker network disconnect backend_net. The real MySQL, Redis and internal API stop being reachable from inside the session.

Relocation leaves fingerprints.

Redirect to a honeypot
SentinelX

New host, fresh PIDs, an empty process tree

uptime, /proc and disk identity all reset

Shell history and dropped files left behind

The TCP/TTY session breaks or has to be re-established

Same container, so PID 412 is still PID 412

uptime, /proc and local state continue uninterrupted

History, cwd and dropped files stay exactly where they were

mgmt_net is never modified, so the live session is never touched

Relocation is detectable. Continuity is the deception. The attacker keeps the session and quietly loses the world behind it.
Design noteL4 · In-place conversion

Security invariants

Invariant 01 / 03
The LLM is strictly downstream. It writes the narrative once the session is over and can never trigger a conversion, a block, or a rule promotion. Logs are attacker-controlled, and a model with the power to act would be prompt injection wired straight into containment.
Prompt-injection boundaryL6 · Extraction and narrative
Non-negotiable