Security and Privacy¶
Failed SSH logins by IP and user¶
kelora examples/sshd_auth.log --input-year 2024 \
--filter 'e.msg.starts_with("Failed password")' \
-e 'e.ip = e.msg.extract_ip(); e.user = e.msg.extract_regex("for (?:invalid user )?(\\S+)", 1)' \
--freq ip --freq user
ip (3 values):
value count
203.0.113.77 4
198.51.100.23 2
192.0.2.200 1
user (4 values):
value count
root 3
admin 2
oracle 1
test 1
Read JWT claims¶
parse_jwt() decodes a token without verifying the signature — for
debugging, not for trusting:
kelora examples/auth-logs.jsonl \
-e 'let t = e.token.parse_jwt(); e.sub = t.claims.sub; e.role = t.claims.role; e.expires = t.expires_at' \
-k timestamp,sub,role,expires
timestamp='2024-01-15T10:00:00Z' sub='user123' role='admin'
expires='2024-11-21T01:46:40+00:00'
timestamp='2024-01-15T10:05:00Z' sub='user456' role='user'
expires='2024-11-21T02:46:40+00:00'
timestamp='2024-01-15T10:10:00Z' sub='user789' role='guest'
expires='2023-11-14T22:13:20+00:00'
timestamp='2024-01-15T10:15:00Z' sub='user111' role='moderator'
expires='2024-11-21T03:46:40+00:00'
Requests from one network¶
ip='198.51.100.77' path='/api/reports' status=500
ip='198.51.100.88' path='/api/upload' status=413
ip='198.51.100.99' path='/api/analytics?date=2025-01-15&metric=views' status=200
Mask addresses inside free text¶
kelora examples/email_logs.log -f 'cols:ts level *msg' -e 'e.msg = e.msg.normalized(["email", "ipv4"])' -n 3
ts='2025-01-15T10:23:45Z' level='INFO'
msg='Email sent from <email> to <email> subject="Welcome"'
ts='2025-01-15T10:24:12Z' level='INFO'
msg='Email received from <email> to <email> subject="Support Request"'
ts='2025-01-15T10:24:33Z' level='WARN'
msg='Bounced email to <email> reason="Domain not found"'
Consistent pseudonyms¶
The same input gives the same alias as long as KELORA_SECRET stays the
same, so you can still count, join, and follow a user across files:
KELORA_SECRET=change-me kelora examples/user-data.jsonl \
-e 'e.user = pseudonym(e.email, "user"); e.email = (); e.ip = e.ip.mask_ip(1)' -k user,action,ip
user='g8tM8VSw0JPXBMVPhDpsj0Zf' action='login' ip='192.168.1.0'
user='VBFT1D7bynhXWHogMn2-JsRh' action='purchase' ip='10.0.5.0'
user='MaUceTZy9kaE5V2HOavznCDY' action='view' ip='172.16.88.0'
user='Tq9oFjjc-1WvdC9mCHqAC5YQ' action='logout' ip='192.168.1.0'
user='4q0StVl3bHi6gqkOSXZzOA8f' action='login' ip='10.0.5.0'
Drop sensitive fields¶
-K token,password hides fields from the output; e.token = () in --exec
removes them before later stages and summaries see them.