

<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
  <id>https://blog.nedtechie.com/</id>
  <title>NedTechie</title>
  <subtitle>Hands-on writeups on cloud security, DevSecOps, Linux, and pentesting — real curl commands, real vulnerabilities, real production stories from Nedim, a DevOps engineer who got security-paranoid and never stopped.</subtitle>
  <updated>2026-08-17T01:14:55+07:00</updated>
  <author>
    <name>Nedim Hadzimahmutovic</name>
    <uri>https://blog.nedtechie.com/</uri>
  </author>
  <link rel="self" type="application/atom+xml" href="https://blog.nedtechie.com/feed.xml"/>
  <link rel="alternate" type="text/html" hreflang="en"
    href="https://blog.nedtechie.com/"/>
  <generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator>
  <rights> © 2026 Nedim Hadzimahmutovic </rights>
  <icon>https://blog.nedtechie.com/assets/img/favicons/favicon.ico</icon>
  <logo>https://blog.nedtechie.com/assets/img/favicons/favicon-96x96.png</logo>


  
  <entry>
    <title>I Wrote Ruby and the Compiler Made It 10x Faster</title>
    <link href="https://blog.nedtechie.com/posts/i-wrote-ruby-and-the-compiler-made-it-10x-faster/" rel="alternate" type="text/html" title="I Wrote Ruby and the Compiler Made It 10x Faster" />
    <published>2026-05-23T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/i-wrote-ruby-and-the-compiler-made-it-10x-faster/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/i-wrote-ruby-and-the-compiler-made-it-10x-faster/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="development" />
    
    <category term="ruby" />
    
    <category term="compilers" />
    
    <category term="performance" />
    
  
  
    
    <category term="aot" scheme="tag" />
    
    <category term="ruby" scheme="tag" />
    
    <category term="spinel" scheme="tag" />
    
    <category term="compilers" scheme="tag" />
    
    <category term="native-binaries" scheme="tag" />
    
    <category term="log-analysis" scheme="tag" />
    
    <category term="type-inference" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/ruby-10x-faster-compiler.svg" medium="image">
      <media:title type="plain">Terminal showing Spinel compiling Ruby to native binary with 10x speedup benchmark</media:title>
      <media:description type="plain">Terminal showing Spinel compiling Ruby to native binary with 10x speedup benchmark</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/ruby-10x-faster-compiler.svg" />
  

  <summary>I wrote a log analyzer in Ruby. Then I compiled it to a native binary. It ran 10 times faster than the same algorithm in CRuby, and 3 times faster than idiomatic Ruby with regex and each.

The part that surprised me most was that the idiomatic Ruby version, the one with regex parsing and sort_by and Hash.new(0), was already 4.7x faster than the while-loop version running in CRuby. The interpret...</summary>

  </entry>

  
  <entry>
    <title>Your S3 Bucket Is an Open Directory and You Probably Don&amp;apos;t Know It</title>
    <link href="https://blog.nedtechie.com/posts/your-s3-bucket-is-an-open-directory/" rel="alternate" type="text/html" title="Your S3 Bucket Is an Open Directory and You Probably Don&amp;apos;t Know It" />
    <published>2026-04-24T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/your-s3-bucket-is-an-open-directory/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/your-s3-bucket-is-an-open-directory/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="aws" />
    
    <category term="devsecops" />
    
  
  
    
    <category term="s3" scheme="tag" />
    
    <category term="bucket-listing" scheme="tag" />
    
    <category term="cloud-security" scheme="tag" />
    
    <category term="terraform" scheme="tag" />
    
    <category term="pentesting" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/s3-bucket-listing-one-curl.svg" medium="image">
      <media:title type="plain">curl command listing S3 bucket contents with no credentials</media:title>
      <media:description type="plain">curl command listing S3 bucket contents with no credentials</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/s3-bucket-listing-one-curl.svg" />
  

  <summary>One curl command can enumerate every file in your S3 bucket. No credentials. No login. Just an HTTP GET. Here is how to find it, why it matters more than you think, and the Terraform fix.</summary>

  </entry>

  
  <entry>
    <title>Breaking My Own Infrastructure: 12 Days, 19 Findings, 3 False Positives</title>
    <link href="https://blog.nedtechie.com/posts/breaking-my-own-infrastructure-what-i-found/" rel="alternate" type="text/html" title="Breaking My Own Infrastructure: 12 Days, 19 Findings, 3 False Positives" />
    <published>2026-04-23T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/breaking-my-own-infrastructure-what-i-found/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/breaking-my-own-infrastructure-what-i-found/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="devsecops" />
    
    <category term="pentesting" />
    
    <category term="retrospective" />
    
  
  
    
    <category term="pentesting" scheme="tag" />
    
    <category term="devsecops" scheme="tag" />
    
    <category term="retrospective" scheme="tag" />
    
    <category term="aws" scheme="tag" />
    
    <category term="api-security" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/breaking-infrastructure-wrapup.svg" medium="image">
      <media:title type="plain">A terminal showing a completed pentest with findings summary</media:title>
      <media:description type="plain">A terminal showing a completed pentest with findings summary</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/breaking-infrastructure-wrapup.svg" />
  

  <summary>Twelve days ago I opened a terminal, pointed curl at our staging API, and started breaking things. I didn’t have a plan. I didn’t have a timeline. I just had coffee, paranoia, and a vague sense that “it probably works fine” wasn’t good enough anymore.

Here’s what I found.

The Series at a Glance

What started as “let me test this one form” turned into a full infrastructure security audit spann...</summary>

  </entry>

  
  <entry>
    <title>What --dryrun Taught Me About Confidence</title>
    <link href="https://blog.nedtechie.com/posts/what-dryrun-taught-me-about-confidence/" rel="alternate" type="text/html" title="What --dryrun Taught Me About Confidence" />
    <published>2026-04-22T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/what-dryrun-taught-me-about-confidence/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/what-dryrun-taught-me-about-confidence/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="aws" />
    
    <category term="devsecops" />
    
    <category term="lessons" />
    
  
  
    
    <category term="aws-cli" scheme="tag" />
    
    <category term="dryrun" scheme="tag" />
    
    <category term="false-positives" scheme="tag" />
    
    <category term="testing-methodology" scheme="tag" />
    
    <category term="pentesting" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/dryrun-false-confidence.svg" medium="image">
      <media:title type="plain">A door that looks locked from across the street but opens when you turn the handle</media:title>
      <media:description type="plain">A door that looks locked from across the street but opens when you turn the handle</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/dryrun-false-confidence.svg" />
  

  <summary>I shipped a false positive to my team. In bold. With a CRITICAL severity tag. And I was wrong.

Not “wrong about a detail” wrong. Wrong about the entire finding. The vulnerability I described didn’t exist. I had tested it with --dryrun, seen a “success,” and written it up with the confidence of someone who has never been humbled by AWS IAM.

This post covers the 48 hours between “I found someth...</summary>

  </entry>

  
  <entry>
    <title>The Load Balancer That Trusted Everyone</title>
    <link href="https://blog.nedtechie.com/posts/the-load-balancer-that-trusted-everyone/" rel="alternate" type="text/html" title="The Load Balancer That Trusted Everyone" />
    <published>2026-04-21T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/the-load-balancer-that-trusted-everyone/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/the-load-balancer-that-trusted-everyone/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="infrastructure" />
    
    <category term="devsecops" />
    
    <category term="aws" />
    
  
  
    
    <category term="rate-limiting" scheme="tag" />
    
    <category term="x-forwarded-for" scheme="tag" />
    
    <category term="trust-proxy" scheme="tag" />
    
    <category term="alb" scheme="tag" />
    
    <category term="cloudfront" scheme="tag" />
    
    <category term="brute-force" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/load-balancer-trusted-everyone.svg" medium="image">
      <media:title type="plain">An ALB accepting X-Forwarded-For headers directly from the internet</media:title>
      <media:description type="plain">An ALB accepting X-Forwarded-For headers directly from the internet</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/load-balancer-trusted-everyone.svg" />
  

  <summary>Rate limiting is supposed to stop brute-force attacks. Ours didn’t. Not because the rate limiter was broken. It worked perfectly. The problem was that it was counting the wrong IP addresses.

An attacker could make unlimited login attempts by adding one HTTP header to each request. No tools. No exploits. Just curl -H &amp;quot;X-Forwarded-For: random-ip&amp;quot;.

This is a story about trust proxy: 2, an ALB se...</summary>

  </entry>

  
  <entry>
    <title>I Can Read Everyone&amp;apos;s Invoices (and Found a Backdoor Inside)</title>
    <link href="https://blog.nedtechie.com/posts/i-can-read-everyones-invoices/" rel="alternate" type="text/html" title="I Can Read Everyone&amp;apos;s Invoices (and Found a Backdoor Inside)" />
    <published>2026-04-20T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/i-can-read-everyones-invoices/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/i-can-read-everyones-invoices/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="api" />
    
    <category term="devsecops" />
    
    <category term="bola" />
    
  
  
    
    <category term="bola" scheme="tag" />
    
    <category term="idor" scheme="tag" />
    
    <category term="auto-login" scheme="tag" />
    
    <category term="finance" scheme="tag" />
    
    <category term="data-exposure" scheme="tag" />
    
    <category term="typeorm" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/everyones-invoices.svg" medium="image">
      <media:title type="plain">Sequential ID enumeration revealing finance records with sensitive data</media:title>
      <media:description type="plain">Sequential ID enumeration revealing finance records with sensitive data</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/everyones-invoices.svg" />
  

  <summary>I was testing my own finance records. Checking that the API returned the right data for my user. Standard BOLA test: try accessing someone else’s record and confirm you get a 403.

I didn’t get a 403.

I got a 200. With someone else’s full accounting invoice, their billing email, their physical address, and, buried 38 fields deep in the response, a token that lets you log in as them without a p...</summary>

  </entry>

  
  <entry>
    <title>The Refresh Token That Wouldn&amp;apos;t Die</title>
    <link href="https://blog.nedtechie.com/posts/the-refresh-token-that-wouldnt-die/" rel="alternate" type="text/html" title="The Refresh Token That Wouldn&amp;apos;t Die" />
    <published>2026-04-19T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/the-refresh-token-that-wouldnt-die/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/the-refresh-token-that-wouldnt-die/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="api" />
    
    <category term="devsecops" />
    
    <category term="authentication" />
    
  
  
    
    <category term="jwt" scheme="tag" />
    
    <category term="refresh-token" scheme="tag" />
    
    <category term="session-management" scheme="tag" />
    
    <category term="authentication" scheme="tag" />
    
    <category term="token-reuse" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/refresh-token-wont-die.svg" medium="image">
      <media:title type="plain">A refresh token being used five times with all five attempts succeeding</media:title>
      <media:description type="plain">A refresh token being used five times with all five attempts succeeding</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/refresh-token-wont-die.svg" />
  

  <summary>I logged out. Then I used my old refresh token. It still worked.

I used it again. Still worked. Five times. Ten times. A week later. Still worked.

This is a story about a refresh token that refused to die, and why “we use JWTs” is not a security strategy.

How Refresh Tokens Are Supposed to Work

Quick primer for anyone who hasn’t thought about this in a while.

When you log in, the server gi...</summary>

  </entry>

  
  <entry>
    <title>It&amp;apos;s 3 AM and I&amp;apos;m Creating a Thousand Invoices</title>
    <link href="https://blog.nedtechie.com/posts/3am-and-im-creating-thousand-invoices/" rel="alternate" type="text/html" title="It&amp;apos;s 3 AM and I&amp;apos;m Creating a Thousand Invoices" />
    <published>2026-04-18T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/3am-and-im-creating-thousand-invoices/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/3am-and-im-creating-thousand-invoices/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="api" />
    
    <category term="devsecops" />
    
    <category term="pentesting" />
    
  
  
    
    <category term="race-condition" scheme="tag" />
    
    <category term="unauthenticated-api" scheme="tag" />
    
    <category term="input-validation" scheme="tag" />
    
    <category term="business-logic" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/3am-thousand-invoices.svg" medium="image">
      <media:title type="plain">Terminal generating 1000 invoices at 3 AM with no rate limiting</media:title>
      <media:description type="plain">Terminal generating 1000 invoices at 3 AM with no rate limiting</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/3am-thousand-invoices.svg" />
  

  <summary>I wasn’t supposed to be awake at 3 AM. But I’d had too much coffee and my brain wouldn’t shut off, so I figured I’d do one more test before bed.

There’s something meditative about curling endpoints at night. The house is quiet. The terminal glows. You send a request and wait for the universe to answer.

Tonight, the universe had opinions.

The Endpoint That Shouldn’t Exist

I’d found this endp...</summary>

  </entry>

  
  <entry>
    <title>I Just Sent XSS Payloads to the Support Team</title>
    <link href="https://blog.nedtechie.com/posts/xss-payloads-in-my-support-tickets/" rel="alternate" type="text/html" title="I Just Sent XSS Payloads to the Support Team" />
    <published>2026-04-17T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/xss-payloads-in-my-support-tickets/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/xss-payloads-in-my-support-tickets/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="api" />
    
    <category term="devsecops" />
    
    <category term="xss" />
    
  
  
    
    <category term="xss" scheme="tag" />
    
    <category term="input-sanitization" scheme="tag" />
    
    <category term="support-system" scheme="tag" />
    
    <category term="ticketing" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/xss-support-tickets.svg" medium="image">
      <media:title type="plain">XSS payload in a support ticket rendering on the agent dashboard</media:title>
      <media:description type="plain">XSS payload in a support ticket rendering on the agent dashboard</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/xss-support-tickets.svg" />
  

  <summary>The best part about doing security testing on your own systems is that you can be as reckless as you want. The worst part is realizing you just sent &amp;amp;lt;script&amp;amp;gt;alert(1)&amp;amp;lt;/script&amp;amp;gt; to your own support platform.

Sorry, past me. And sorry to whatever support agent has to review those tickets.

The Contact Form

I’d been poking at this contact form all morning. You know the type: name, emai...</summary>

  </entry>

  
  <entry>
    <title>When Your Internal Fields Aren&amp;apos;t Internal: The Day I Deleted My Own Account</title>
    <link href="https://blog.nedtechie.com/posts/when-your-internal-fields-arent-internal/" rel="alternate" type="text/html" title="When Your Internal Fields Aren&amp;apos;t Internal: The Day I Deleted My Own Account" />
    <published>2026-04-16T16:00:00+07:00</published>
  
    <updated>2026-08-10T02:33:57+07:00</updated>
  
    <id>https://blog.nedtechie.com/posts/when-your-internal-fields-arent-internal/</id>
    <content type="text/html" src="https://blog.nedtechie.com/posts/when-your-internal-fields-arent-internal/" />
    <author>
      <name>Nedim</name>
    </author>

  
    
    <category term="security" />
    
    <category term="api" />
    
    <category term="devsecops" />
    
    <category term="mass-assignment" />
    
  
  
    
    <category term="mass-assignment" scheme="tag" />
    
    <category term="internal-fields" scheme="tag" />
    
    <category term="user-profile" scheme="tag" />
    
    <category term="soft-delete" scheme="tag" />
    
  

  
    
    <media:content url="https://blog.nedtechie.com/assets/img/posts/internal-fields-arent-internal.svg" medium="image">
      <media:title type="plain">JSON payload with dangerous internal fields highlighted in red</media:title>
      <media:description type="plain">JSON payload with dangerous internal fields highlighted in red</media:description>
    </media:content>
    <media:thumbnail url="https://blog.nedtechie.com/assets/img/posts/internal-fields-arent-internal.svg" />
  

  <summary>I deleted my own account today.

Not on purpose. I’m not that chaotic. I was testing something, and then I couldn’t log in anymore.

The Profile Update Endpoint

I was testing the user profile update functionality. You know, the thing where you change your name or update your email. Standard stuff.

The request looks like this:

PUT /api/users/12345
{
  &amp;quot;firstName&amp;quot;: &amp;quot;Nedim&amp;quot;,
  &amp;quot;lastName&amp;quot;: &amp;quot;Hadz...</summary>

  </entry>

</feed>


