As an IT Support & SecOps engineer, I paste sensitive data into tools all day. A few years ago I watched a teammate drop a live bearer token into a random JWT decoder during an incident. Nobody on that call asked where the token went next, and that question has stayed with me since.

This post covers that risk first. Then it walks through the math I use most often: small cloud subnets, Linux permission bits, and cron schedules that collide.

Why is pasting production data into web calculators an OpSec risk?

Every server-side calculator receives your input as a request body, and you have no control over what happens to it after that. It can land in access logs, WAF logs, APM traces, error trackers, or third-party analytics scripts. You are trusting an unknown retention policy with data your own team would never email in plain text.

The three worst offenders I see in real incidents:

  • Production JWTs. A token stays valid until its exp claim passes. Anyone who reads it from a log can replay it against your API, and most teams cannot revoke a single JWT.
  • Obfuscated PowerShell from an incident. Those logs contain hostnames, usernames, internal paths and often the attacker's C2 address. Sending them to an unknown server leaks your internal layout and can tip off whoever is watching that infrastructure.
  • Internal VPC subnet maps. A list of CIDR blocks with labels like prod-db or vpn-pool is a reconnaissance gift. It tells an attacker exactly where to pivot after the first foothold.

The fix is simple: use tools that compute in the browser and never send the input anywhere. You can verify this yourself in a minute. Open DevTools, switch to the Network tab, paste your input, and confirm that no request carries it.

That test is why I built LocalSecTools, a set of browser-only security and sysadmin utilities. Every calculation there runs in JavaScript on your machine, and the Network tab stays quiet while you work.

How do you find the host bits in a 255.255.255.224 mask?

The mask 255.255.255.224 equals /27, so 5 bits identify the host and 30 addresses are usable. The answer comes from counting the 1-bits in the mask and subtracting from 32. Here is the full working, step by step.

Step 1: Convert the mask to binary. The first three octets are 255, which is eight 1-bits each. Only the last octet needs real work.

255.255.255.224 11111111.11111111.11111111.11100000 

Step 2: Read the last octet. The value 224 equals 128 + 64 + 32, so the top three bits are set and the bottom five are zero.

128 64 32 16 8 4 2 1 1 1 1 0 0 0 0 0 = 224 

Step 3: Count network bits. That gives 8 + 8 + 8 + 3 = 27 network bits, so the prefix is /27.

Step 4: Subtract from 32. The host portion is whatever remains of the 32-bit address.

host bits h = 32 - prefix = 32 - 27 = 5 total addrs = 2^h = 2^5 = 32 usable (RFC) = 2^h - 2 = 32 - 2 = 30 

We subtract two because the first address names the subnet itself and the last one is reserved for broadcast. You can confirm the result from any Linux shell without installing anything:

python3 -c "import ipaddress as i; n=i.ip_network('10.20.30.64/27'); print(n.netmask, n.num_addresses, n.num_addresses-2)" # 255.255.255.224 32 30 

If ipcalc is installed, ipcalc 10.20.30.64/27 prints the same mask, host range and broadcast address. For a longer walkthrough of each prefix, I wrote up the /30 vs /29 vs /28 vs /27 host bits breakdown with worked examples.

Why do /27 to /30 subnets give fewer hosts in AWS and Azure?

AWS and Azure reserve five addresses in every subnet, so the usable count is 2^h - 5 instead of 2^h - 2. That difference is small on a /24 but painful on tiny subnets. Both clouds also refuse prefixes that are too small to be useful.

The five reserved addresses follow the same pattern in both clouds. The network address and broadcast address are blocked like on-prem. The cloud also keeps .1 for the router, .2 for DNS, and .3 for future use.

Prefix Subnet mask Host bits (h) Total (2^h) RFC usable (2^h - 2) AWS / Azure usable (2^h - 5) Cloud allows it?
/27 255.255.255.224 5 32 30 27 AWS and Azure
/28 255.255.255.240 4 16 14 11 AWS and Azure (smallest on AWS)
/29 255.255.255.248 3 8 6 3 Azure only (smallest on Azure)
/30 255.255.255.252 2 4 2 -1 (impossible) Neither

The /30 row is the one that catches people. It is the classic point-to-point mask on physical routers, but in a VPC it leaves negative space. AWS rejects it outright:

aws ec2 create-subnet --vpc-id vpc-0example --cidr-block 10.20.30.0/30 # An error occurred (InvalidSubnet.Range) ... 

My rule for cloud planning: never go below /28 for anything that might scale. Load balancers, NAT gateways and managed endpoints each consume addresses you did not plan for. A /27 with 27 usable addresses costs you nothing extra and saves a painful re-IP later.

Before I commit a VPC layout, I split the parent block in the CIDR subnet splitter that runs in your browser. It shows network, broadcast and usable ranges for each child, and my internal ranges never leave the laptop. If you need a refresher on which blocks are safe for internal use, see this guide to RFC 1918 private IP ranges and mask-to-CIDR conversion.

How does chmod octal math work?

Each octal digit is the sum of three bits: read is 4, write is 2 and execute is 1. Reading left to right, the digits cover the file owner, the owning group, and everyone else. So a mode like 750 is really a 9-bit mask.

value = (r ? 4 : 0) + (w ? 2 : 0) + (x ? 1 : 0) 7 = 111 = rwx 6 = 110 = rw- 5 = 101 = r-x 4 = 100 = r-- 0 = 000 = --- chmod 750 -> 111 101 000 -> rwx r-x --- 

Once you see the bits, the production modes stop being magic numbers. Each one removes exactly the access a given file type should not have.

Mode Bits Symbolic Where I use it Why
600 110 000 000 rw------- SSH private keys, .env files Owner reads and writes, nobody else sees it
400 100 000 000 r-------- AWS .pem key pairs Read-only, even the owner cannot overwrite by accident
750 111 101 000 rwxr-x--- Service directories like /opt/app Service group can enter and read, others are locked out
555 101 101 101 r-xr-xr-x Shipped binaries and scripts Everyone runs it, nobody edits it
000 000 000 000 --------- Temporary user-space lockout No access until the owner or root restores the mode
666 110 110 110 rw-rw-rw- Never on servers Any local user can rewrite the file
777 111 111 111 rwxrwxrwx Never on servers Any local user can replace code that someone else executes

Two notes from real tickets. OpenSSH refuses a private key that group or others can read, and prints a loud "UNPROTECTED PRIVATE KEY FILE" warning. The fix is one command:

chmod 600 ~/.ssh/id_ed25519 chmod 400 ~/keys/prod-bastion.pem stat -c '%a %A %n' ~/.ssh/id_ed25519 # 600 -rw------- /home/asad/.ssh/id_ed25519 

Also, 000 and 555 are not protection against root. Root bypasses read and write checks, and the file owner can always run chmod again. Treat these modes as guardrails against mistakes, not as a security boundary.

The 666 and 777 modes are the ones I hunt for during audits. A world-writable script that a cron job runs as root is a straight path to privilege escalation. This sweep finds them on a single filesystem:

find / -xdev -type f -perm -0002 -ls 2>/dev/null # world-writable files find / -xdev -type d -perm -0002 ! -perm -1000 -ls 2>/dev/null # world-writable dirs without sticky bit 

When I need to translate between octal and symbolic quickly, I use this client-side chmod calculator with octal and symbolic sync. For a deeper look at each mode, read my breakdown of restrictive Linux file modes from 000 to 770.

Why replace overlapping crontabs with systemd timers?

Cron starts a new copy of a job on schedule, even if the previous run is still going, while a systemd service will not start twice while it is active. That single difference removes a whole class of overlap bugs. It matters most when two schedules land on the same minute.

Take two common entries on one host:

*/5 * * * * /usr/local/bin/sync-inventory.sh 0 */4 * * * /usr/local/bin/full-backup.sh 

At 00:00, 04:00, 08:00 and every fourth hour, both fire in the same minute. If the backup locks the same database the sync job reads, the sync stretches past five minutes. Cron then launches another sync on top of it, and the pile-up grows until something times out.

The quick fix keeps cron and adds a non-blocking lock. With flock -n, a second copy exits right away instead of queuing:

*/5 * * * * flock -n /run/lock/sync-inventory.lock /usr/local/bin/sync-inventory.sh 

The better fix moves the job to a systemd timer. The timer only triggers the service, and systemd skips the trigger if the service is still active. You also get journald logs and a clear view of the next run.

# /etc/systemd/system/sync-inventory.timer [Unit] Description=Inventory sync every 5 minutes  [Timer] OnCalendar=*:0/5 Persistent=true RandomizedDelaySec=30  [Install] WantedBy=timers.target 
systemd-analyze calendar '*:0/5' # preview the next trigger time systemd-analyze calendar '00/4:00' # the 0 */4 * * * equivalent sudo systemctl enable --now sync-inventory.timer systemctl list-timers sync-inventory.timer 

The RandomizedDelaySec line spreads the start by up to 30 seconds, which also breaks the exact-minute collision with the backup. Persistent=true runs a missed trigger after a reboot, which plain cron never does.

Converting cron syntax to OnCalendar by hand is where I make mistakes. Weekday ranges and day-of-month rules differ in subtle ways. I paste the expression into this cron visualizer that previews next runs and outputs systemd OnCalendar units, then copy the generated .timer and .service pair.

What should you check before trusting any online security tool?

Check whether your input leaves the browser, and assume anything that does is stored somewhere. The DevTools Network tab answers that in seconds. If the tool still works with Wi-Fi turned off, the math happens locally.

My short checklist before I paste anything sensitive:

  1. Open DevTools, then the Network tab, and clear it.
  2. Paste the input and run the tool.
  3. Look for any POST or fetch request that contains your data.
  4. If in doubt, disconnect from the network and run it again.

None of the math in this post needs a server. Subnet masks are bit shifts, chmod is addition, and cron parsing is string matching. Keeping that work local is the easiest OpSec win I know.

Asad Ali is an IT Support & SecOps engineer, Microsoft SC-200 and ISC2 CC certified. You can find more of my work at asadali.tech. If this post saved you a re-IP or a 3 a.m. cron pile-up, try the 10 client-side utilities on LocalSecTools, from JWT inspection to log deobfuscation, and tell me which tool you want next.