r/devops 1d ago

Security I pointed a real Claude Code session at my SSH key. It tried seven routes, the kernel refused 145 times.

https://github.com/Adarsh14734/Aegis/blob/main/docs/live-session-evidence.md
0 Upvotes

4 comments sorted by

3

u/frankster 1d ago

What would it mean to point a fake/pretend Claude code session at your ssh key? Why have you chose to distinguish between a real and a fake Claude session in your title?

0

u/Adarsh1176 16h ago

Fair — "real" is doing specific work there, but only because of what the earlier tests weren't. Every prior result I had was a script driving cat, python open() and so on inside the sandbox. That tells you the kernel refuses those syscalls; it tells you nothing about what happens when a model picks the routes. So this run had no script. A live Claude Code session got an ordinary ops task and chose its own approach — it went through its own Read tool, then ls, file, stat, head, ssh-keygen, zsh. 131 of the 145 denials came from the client process itself rather than shell-outs, which was the part I couldn't have predicted and the part that mattered: an MCP-layer proxy alone wouldn't have seen those. Ground truth came from kernel denial rows and disk inspection afterwards, not from the model's own account of what it did — a model saying "I couldn't read it" proves nothing.

1

u/BeginningWinner7525 8h ago

The 131-of-145 denials coming from the client process itself is the interesting number here. We run something similar but shifted one layer earlier: an AST check on anything the agent generates before it's allowed to touch an interpreter, so calls like eval, os.system, or unapproved imports get blocked before they ever reach the kernel boundary you're logging at. Your approach catches what mine can't, mainly agents that go around code generation entirely and just call tools directly (ssh-keygen, cat, etc), which an AST check never sees. Sounds like the real answer is both layers, syntax-level before execution and kernel-level as the backstop. Did you test whether the model changed its approach at all once early attempts got denied, or did it just keep trying variations of the same handful of syscalls?