</>CodeWithKarani
All topics
Topic

Security

57 articles in this topic.

Security12 min read

Exactly-once over an unreliable pipe: HMAC, nonces, and a byte-exact contract

A per-request nonce and a per-content hash look like the same idea and are not. One says this request arrived twice, the other says this message arrived twice, and a payment pipeline needs both. The signing design behind a production SMS gateway.

Read
Frappe/ERPNext13 min read

Deploying Frappe apps to a client server you're not allowed to touch

The client will not give you access to their dev server, so every code change means someone on their side pulls and migrates by hand. Here is the complete fix: a self-hosted runner they install, a deploy script they own, and no credential to their environment on your side at all.

Read
Frappe/ERPNext12 min read

Bolting a phone onto ERPNext: custom routes, guest endpoints and HMAC auth in Frappe

Frappe claims every /api/* path before website routing, so a fixed third-party path 404s. Here is the before_request rewrite that fixes it, including the cached property you also have to bust, and why allow_guest endpoints can still be strongly authenticated.

Read
Security7 min read

Push access is code execution: hardening a self-hosted runner

A self-hosted runner executes whatever the workflow file says, and the workflow file lives in a repository you control. So push access to your repository is command execution on your client's server. Here is the honest risk and the layers that contain it.

Read
DevOps & Containers8 min read

Secrets, environments and required reviewers

A repository secret is readable by everyone who can push to the repository. An environment secret is not released until a gate opens. Understanding that difference is what lets you hand the client the key to their own deployments.

Read
Security8 min read

Access is a liability, not a convenience

Every SSH key you hold on a client's server is a credential you now have to defend, insure and explain. The strongest position in an enterprise procurement conversation is not having it at all.

Read
Security9 min read

Blocked by CORS Policy: Stop Reaching for Access-Control-Allow-Origin: *

The wildcard breaks the moment you send cookies, and reflecting the Origin header is worse. Here is the allowlist pattern, the nginx config and the curl test that proves it.

Read
Security8 min read

Your Cert Automation Should Default to Let's Encrypt Staging

Five test renewals can exhaust the duplicate certificate limit and block a real renewal for a week. Here is why certbot drifts to production, and the directory split that prevents it.

Read
Security10 min read

Certbot connection refused on http-01: diagnosing proxies, IPv6 and port 80

Connection refused is not the same as a timeout, and the difference tells you exactly where to look. A diagnostic order for failed Let's Encrypt http-01 challenges.

Read
AI Engineering6 min read

The agent drafts, the human commits: designing the write path for a business AI

A wrong read costs minutes. A wrong write costs a reconciliation. So the commit lives behind an HTTP endpoint the agent cannot call - and everything it can do is scoped to the requesting user, written to an audit row in the same transaction, and given a tested reversal.

Read
Security7 min read

The Security Checklist Every Kenyan SME Running Its Own Server Should Finish This Week

You do not have a security budget problem, you have a completeness problem. Ten free controls with real commands, a cost table, and the weekly rhythm that keeps a self-hosted Kenyan SME system out of trouble.

Read
Security9 min read

Kenya's Data Protection Act Is an Engineering Spec: What Sections 25, 31, 41 and 43 Demand From Your Code

The DPA 2019 is not a lawyer problem, it is a schema, retention and logging problem. Registration thresholds, the 72-hour breach clock, the encryption safe harbour, and the eight things to build this quarter.

Read
Security8 min read

How Kenyan Small Businesses Actually Get Hacked (Nobody Is Burning a Zero-Day on Your Duka)

Five real attack chains account for almost every SME breach: infostealers, credential stuffing, exposed admin panels, unpatched plugins and invoice fraud. With the log commands to check each one today.

Read
Security7 min read

Stop Committing Keys: A Secrets Workflow for Two-Person Teams Using SOPS and age

You do not need Vault. You need encrypted secrets in git, one age key per human, and a pre-commit hook that refuses the mistake. Full setup, offboarding in two commands, and when to actually upgrade.

Read
Security9 min read

Certbot http-01 Fails Behind Your Force-HTTPS Redirect: It Is Not HSTS

Let's Encrypt follows your 301 to HTTPS and ignores HSTS entirely. So the real cause of a failed http-01 renewal is one of four things, and disabling HSTS is not the fix.

Read
Security8 min read

Certbot renewal fails silently: alerting before the certificate expires

Certbot can fail twice a day for three months without telling anyone, and Let's Encrypt stopped sending expiry emails in 2025. Three independent alerts that catch it, with the tests.

Read
Security9 min read

CSP 'unsafe-inline' Is Not a Fix: Nonces That Work in Next.js

Adding 'unsafe-inline' to silence CSP violations turns the header into compliance theatre. Here is the per-request nonce setup for Next.js that keeps hydration working.

Read
Security8 min read

Surviving a Bot Flood on a $20 VPS: nginx limit_req, fail2ban and Cloudflare Free in the Right Order

Diagnose before you block. A cost-ordered defence for small servers: Cloudflare's single free rate limit rule, nginx limit_req zones that do not break real browsers, fail2ban jails, and stale-while-updating caching.

Read
DevOps & Containers8 min read

kubectl Unauthorized on EKS: Check the IAM Identity, Not RBAC

EKS returns Unauthorized when it cannot map your IAM principal to a Kubernetes user, so no ClusterRoleBinding will fix it. Here is the diagnosis order that actually resolves it.

Read
Security9 min read

Storing JWTs in localStorage Turns Any XSS Into Account Takeover

Every JWT tutorial puts the token in localStorage. Here is what that costs when XSS lands, and the in-memory access token plus HttpOnly refresh cookie setup that replaces it.

Read
DevOps & Containers8 min read

Kubernetes Has No Cross-Namespace Secrets: Why Manual Copies Always Drift

A Pod cannot reference a Secret in another namespace and Kubernetes will not sync copies for you. Here is why, and the three mechanisms that actually hold up.

Read
Security8 min read

"Too Many Certificates Already Issued": Fixing Let's Encrypt Rate Limits

The duplicate certificate limit is 5 per exact name set per week and global across all accounts, so switching clients cannot help. Here is what actually works.

Read
Security9 min read

Users Randomly Logged Out: Fixing next-auth Token Rotation

Auth.js refresh token rotation silently drops the rotated token in four distinct ways, and the popular workaround of disabling rotation is worse than the bug. Here is the real fix.

Read
Security9 min read

npm audit Noise: Triaging CVEs Without Turning Off the Alarm

npm audit tells you a version matched an advisory range, not that you are exploitable. A four-gate triage that ends in a written decision instead of a disabled CI step.

Read
Security8 min read

'Unable to get local issuer certificate': fix the chain, not the client

The site works in Chrome and fails everywhere else. That is an incomplete nginx certificate chain, and the fix is fullchain.pem, not curl -k or disabling verification.

Read
Security7 min read

ACME TLS Handshake Failure Behind a Load Balancer: When Only Some Backends Answer

Cert renewals fail intermittently behind a load balancer while normal traffic is fine. The cause is not certbot; it is inconsistent backends. Here is the diagnosis and fix.

Read
Security8 min read

Your Webhook Endpoint Trusts Anyone Who Can curl It

Skipping HMAC verification turns a webhook into an unauthenticated database write. Why verification breaks when you finally add it, and the raw-body fix for Stripe, GitHub and Shopify.

Read
Security7 min read

Auth.js v5 redirects to the wrong URL behind a reverse proxy

Set NEXTAUTH_URL and it still redirects to localhost or the container IP. In v5 the host comes from proxy headers gated by trustHost, and that is the real fix.

Read
Security6 min read

Certbot Keeps Making New Certificates Instead of Renewing: --cert-name Explained

Certbot identifies a certificate by its lineage name, not its domain list. Here is why it spawns duplicate -0001 certs and how --cert-name fixes it for good.

Read
Security8 min read

Your DDNS subdomain keeps hitting Let's Encrypt rate limits, and it is not a bug

If certificates fail on a shared DDNS suffix like duckdns.org, you are sharing one rate-limit bucket with every other customer. Here is why, and the only real fix.

Read
Security8 min read

Your fail2ban Stopped Banning Anyone and Never Told You

fail2ban fails silently: a dead filter looks exactly like a quiet internet. Here is the post-upgrade check that proves your jails still work, and how to alert on zero bans.

Read
Security8 min read

The HSTS Preload List Is Almost One-Way: Check This Before You Submit

Preloading HSTS hardcodes your domain into browsers with no server-side undo. Why every subdomain and expired cert becomes a forever problem, and the checklist to run before you commit.

Read
Security8 min read

The GitHub Actions Pwn Request: How Fork PRs Steal Your Secrets

pull_request_target plus a fork checkout hands your CI secrets to any attacker. Here is the mechanism, the tj-actions lesson, and the two-workflow fix.

Read
Security10 min read

IP Rate Limiting Won't Stop Credential Stuffing: What Actually Does

Distributed credential stuffing rotates thousands of IPs, each trying once, sliding under every per-IP limit. Here is the per-account, breached-password and MFA stack that stops it.

Read
Security9 min read

JWTs Have No Logout: Adding Expiry and Revocation Without Losing Statelessness

A JWT you cannot revoke is a password you cannot change. How to add real logout, short-lived access tokens and a revocable refresh token without throwing away statelessness.

Read
Security8 min read

JWT alg:none and RS256/HS256 Confusion: Pin Your Algorithms

A JWT verifier that reads the alg header from an untrusted token is not verifying anything. How alg:none and the RS256-to-HS256 swap work, and the pinning fix in five languages.

Read
Security8 min read

Let's Encrypt Renewal Fails Behind Cloudflare Proxy: Use DNS-01, Not http-01

Cloudflare's orange-cloud proxy breaks http-01 ACME challenges. You do not have to grey-cloud your site. Switch to DNS-01 over Cloudflare's API and renew with the proxy on.

Read
Web & JavaScript7 min read

useSession() Only Updates After a Manual Reload in the Next.js App Router

NextAuth useSession() stays stale until you reload because the App Router has two session reads. Here is why router.refresh() only fixes half, and the reliable pattern.

Read
APIs & Integrations8 min read

Webhook Signature Verification Fails Randomly? It Is Your Body Parser Order

A webhook signature check that passes on some events and fails on others is not a secret problem. Why re-serialized JSON breaks the HMAC, and how to verify the raw body before parsing.

Read
Linux & Servers6 min read

Certbot Bypasses systemd for Nginx: Why Renewals Leave Them Out of Sync

Certbot's nginx plugin signals nginx directly instead of via systemctl, so systemd's state drifts from reality after renewal. Here is the PID-file race and the fix.

Read
Linux & Servers6 min read

Stop Using chmod 777: What to Do Instead When You Get Permission Denied

chmod 777 makes a file world-writable and turns an uploads folder into a remote code execution path. Here is how to actually diagnose Permission denied and fix it with chown and 755/644.

Read
Security6 min read

When Certbot's nginx Plugin Mangles Your Server Block, Fix It by Hand

Re-running certbot --nginx to fix a broken server block usually makes duplicate, conflicting blocks. Use certonly and wire the SSL directives in yourself.

Read
Security6 min read

DNS-01 Fails but the TXT Record Is There: Delegate _acme-challenge

DNS-01 validation keeps failing with NXDOMAIN even though your TXT record exists. It is a delegation problem, not propagation. Delegate _acme-challenge via CNAME to fix it for good.

Read
Python & FastAPI6 min read

FastAPI Cross-Site Cookies Silently Not Set: SameSite and Secure

Your FastAPI set_cookie returns 200 but the browser never stores it and there is no error. Here is why cross-site cookies need SameSite=None; Secure, and how to fix it.

Read
Python & FastAPI5 min read

FastAPI CORS Silently Failing: the allow_credentials Plus Wildcard Trap

FastAPI CORS with allow_credentials=True and allow_origins=['*'] passes testing then breaks once cookies flow. The browser blocks it silently. Here is why and the fix.

Read
Security7 min read

A Valid JWT Signature Isn't Enough: Check the aud and iss Claims

A valid JWT signature proves who issued the token, not who it was for. Without aud and iss checks, one service's token works against another. Here is the fix.

Read
DevOps & Containers7 min read

Kubernetes Secrets Are base64, Not Encrypted: What Actually Protects Them

A Kubernetes Secret is base64-encoded plaintext, not a vault. Here is what actually protects it: encryption at rest, tight RBAC, and an external secrets manager.

Read
Security8 min read

Let's Encrypt Renewal Fails Behind Cloudflare Proxy: Use DNS-01, Not http-01

Cloudflare's orange-cloud proxy breaks http-01 ACME challenges. You do not have to grey-cloud your site. Switch to DNS-01 over Cloudflare's API and renew with the proxy on.

Read
Security9 min read

Laravel 419 Page Expired in Production: A Diagnostic Order, Not a Fix List

The intermittent Laravel 419 TokenMismatchException has five common causes that look identical. Here is the order to diagnose them so you fix it once.

Read
Security7 min read

Two ACME Clients, One Domain: Handling Multiple _acme-challenge Records Safely

When two ACME clients share a domain, DNS-01 renewals fail intermittently and people delete each other's TXT records. Here is why a name holds many TXT records and how to make the clients coexist.

Read
Security7 min read

Multi-tenant next-auth: fixing NEXTAUTH_URL without disabling host checks

NEXTAUTH_URL is a single value read once at boot, so multi-domain apps redirect to the wrong host. The workaround everyone posts reopens host-header injection. Here is the safe pattern.

Read
Security8 min read

Certificates for a Multi-Server Cluster: Issue Once, Distribute Everywhere

Running certbot on every node for the same domain burns your Let's Encrypt rate limit and splits your cluster's identity. Issue once with DNS-01 and distribute instead.

Read
Security7 min read

Anyone Can Forge X-Forwarded-For: Configuring nginx real_ip Correctly

A raw client request can claim any source IP in X-Forwarded-For. Here is how to scope nginx set_real_ip_from and real_ip_recursive so your rate limits and allowlists trust a verified IP.

Read
Security8 min read

Old Android and OpenSSL Clients Failing TLS After the Root CA Transition

TLS works in every browser but fails on old Android and ancient OpenSSL. It is a client trust-store issue, and the DST Root CA X3 workaround is now dead.

Read
Databases7 min read

Postgres 'no pg_hba.conf entry for host': the scoped fix, not 0.0.0.0/0

The FATAL: no pg_hba.conf entry error has a two-minute fix that also opens your database to the whole internet. Here is the scoped rule to add instead.

Read
Security7 min read

6-Day Certificates Are Here: Auditing Renewal Automation That Assumed 90 Days

Let's Encrypt short-lived certs live 160 hours, not 90 days. Your weekly cron and 30-day expiry alert are now an outage. Here is the audit that fixes both.

Read
Security6 min read

Free HTTPS on Nginx With Let's Encrypt, and the Renewal Everyone Forgets

Getting a free Let's Encrypt certificate on Nginx takes five minutes. Keeping it alive for the next three years is the part that breaks. Here is the issue, the config and the renewal.

Read