惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
阮一峰的网络日志
阮一峰的网络日志
C
Check Point Blog
Stack Overflow Blog
Stack Overflow Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
M
MIT News - Artificial intelligence
L
LangChain Blog
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky
WordPress大学
WordPress大学
博客园_首页
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
L
LINUX DO - 最新话题
S
Security @ Cisco Blogs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Help Net Security
Help Net Security
大猫的无限游戏
大猫的无限游戏
Hugging Face - Blog
Hugging Face - Blog
The GitHub Blog
The GitHub Blog
Schneier on Security
Schneier on Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
U
Unit 42
Jina AI
Jina AI
雷峰网
雷峰网
罗磊的独立博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 【当耐特】
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
人人都是产品经理
人人都是产品经理
Microsoft Security Blog
Microsoft Security Blog
V
V2EX
N
News and Events Feed by Topic
V2EX - 技术
V2EX - 技术
宝玉的分享
宝玉的分享
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hacker News - Newest:
Hacker News - Newest: "LLM"
P
Proofpoint News Feed
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
O
OpenAI News
P
Proofpoint News Feed
H
Help Net Security
S
Securelist
Vercel News
Vercel News
Hacker News: Ask HN
Hacker News: Ask HN
博客园 - 三生石上(FineUI控件)

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Stop Using setuid for Everything: Practical Linux File Capabilities with getcap, setcap, and systemd
Lyra · 2026-04-26 · via DEV Community

Stop Using setuid for Everything: Practical Linux File Capabilities with getcap, setcap, and systemd

A lot of Linux software does not actually need full root power. It needs one specific privilege.

Maybe it only needs to bind to port 80. Maybe it needs raw sockets. Maybe it needs one network admin action during startup. Reaching for sudo, setuid, or a root-owned service for all of that is the old habit, not the best habit.

Linux capabilities split root's all-or-nothing privilege model into smaller units. Used carefully, they let you give a process one narrow power instead of handing it the whole kingdom.

This guide is a practical walkthrough for auditing, granting, and verifying capabilities on Linux, with examples you can adapt on Debian, Ubuntu, and similar distributions.

Why capabilities are worth using

Traditional Unix privilege is blunt:

  • root bypasses normal permission checks
  • non-root users do not

Linux capabilities break that into separate privileges like:

  • CAP_NET_BIND_SERVICE to bind to ports below 1024
  • CAP_NET_RAW to use raw and packet sockets
  • CAP_SYS_ADMIN for a huge pile of admin operations

That last one is important: some capabilities are narrow, but some are still extremely broad. CAP_SYS_ADMIN is famously overloaded, so treating it as "basically root" is often the safer mental model.

The operational goal is simple:

  • avoid setuid root when one small privilege will do
  • avoid running long-lived services as root when a bounded capability is enough
  • verify what you changed, instead of assuming it is safe

First, audit what is already privileged

On Debian and Ubuntu, the getcap and setcap tools come from libcap2-bin.

sudo apt update
sudo apt install -y libcap2-bin

Enter fullscreen mode Exit fullscreen mode

List files that already carry file capabilities:

sudo getcap -r / 2>/dev/null

Enter fullscreen mode Exit fullscreen mode

Typical setuid files are worth reviewing too:

sudo find / -xdev -perm -4000 -type f -printf '%M %u %g %p\n'

Enter fullscreen mode Exit fullscreen mode

That gives you two different privilege surfaces:

  • executables with file capabilities
  • executables with the setuid bit

If you are replacing an old setuid helper, this comparison is the right place to start.

The safest beginner use case: binding to port 80 without running as root

A classic example is a service that only needs to listen on port 80 or 443.

The relevant capability is:

  • CAP_NET_BIND_SERVICE

Suppose your service binary lives at /usr/local/bin/myapp.

Grant only that capability:

sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myapp

Enter fullscreen mode Exit fullscreen mode

Verify it:

getcap /usr/local/bin/myapp

Enter fullscreen mode Exit fullscreen mode

Expected output:

/usr/local/bin/myapp cap_net_bind_service=ep

Enter fullscreen mode Exit fullscreen mode

Now you can run the service as a non-root user and still bind to port 80.

Important warning: do not put capabilities on a shared interpreter

This is a common mistake.

Do not do this on a general-purpose interpreter such as:

  • /usr/bin/python3
  • /usr/bin/node
  • /usr/bin/bash

If you attach a file capability to a widely used interpreter, every script launched through that interpreter can inherit that privilege path. That is usually much broader than you intended.

Better options:

  • put the capability on a dedicated compiled binary
  • use a service manager such as systemd to grant the capability to one service
  • front the app with a reverse proxy that already handles privileged ports

Prefer systemd for services you own

For managed services, systemd is often cleaner than editing file metadata on the executable.

Here is a minimal example for a service that should run as myapp, bind to port 80, and get no extra network privileges beyond that.

# /etc/systemd/system/myapp.service
[Unit]
Description=My app
After=network.target

[Service]
User=myapp
Group=myapp
ExecStart=/usr/local/bin/myapp
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enter fullscreen mode Exit fullscreen mode

Apply it:

sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service

Enter fullscreen mode Exit fullscreen mode

Why this is nicer for long-lived services:

  • privilege is declared in the unit, not hidden on the file
  • CapabilityBoundingSet= limits what the service can ever retain
  • AmbientCapabilities= passes the needed capability to a non-root process
  • NoNewPrivileges=true helps prevent gaining more privilege later

Check the resolved unit if you are debugging:

systemctl cat myapp.service
systemctl show myapp.service -p User -p Group -p AmbientCapabilities -p CapabilityBoundingSet -p NoNewPrivileges

Enter fullscreen mode Exit fullscreen mode

File capabilities vs systemd capabilities

Use file capabilities when:

  • you have one dedicated executable
  • the privilege should travel with that executable
  • the program may run outside systemd

Use systemd capability controls when:

  • the program is a service you manage
  • you want the privilege policy next to the rest of the service definition
  • you want a clean rollback by editing the unit rather than modifying executable metadata

My bias is simple:

  • for services, prefer systemd
  • for one-off dedicated binaries, file capabilities can be fine
  • for shared interpreters, avoid file capabilities

Removing or changing a capability

To remove file capabilities from an executable:

sudo setcap -r /usr/local/bin/myapp

Enter fullscreen mode Exit fullscreen mode

Verify removal:

getcap /usr/local/bin/myapp

Enter fullscreen mode Exit fullscreen mode

If nothing is printed, the file no longer has file capabilities.

A second example: inspecting ping is not enough anymore

Older writeups often use ping as the example for CAP_NET_RAW or setuid. That is not reliable as a universal teaching shortcut now.

Modern distributions vary:

  • some ship ping with file capabilities
  • some historically used setuid
  • some rely on kernel support for unprivileged ICMP echo sockets with net.ipv4.ping_group_range

So if you are auditing a real host, inspect the local system rather than assuming what /usr/bin/ping looks like.

Useful checks:

getcap "$(command -v ping)" 2>/dev/null || true
stat -c '%A %U:%G %n' "$(command -v ping)"
sysctl net.ipv4.ping_group_range 2>/dev/null || true

Enter fullscreen mode Exit fullscreen mode

That small habit avoids a lot of copy-paste folklore.

Capability names matter, and some are far riskier than they sound

A few practical rules:

  • prefer the narrowest capability that solves the problem
  • be suspicious of CAP_SYS_ADMIN
  • treat capability changes like a security change, not a convenience tweak
  • document why the capability exists
  • test as the unprivileged service user, not only as root

This is a bad pattern:

sudo setcap 'cap_sys_admin=+ep' /usr/local/bin/myapp

Enter fullscreen mode Exit fullscreen mode

This is the kind of pattern you should look for first:

sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myapp

Enter fullscreen mode Exit fullscreen mode

A practical audit workflow

When you want to replace broad privilege with something tighter, this sequence works well:

  1. identify what the program actually needs to do
  2. map that to the smallest capability that matches
  3. prefer service-level controls if the app is systemd-managed
  4. verify the file or service configuration after the change
  5. run a real functional test as the target non-root user
  6. document the reason so the next admin does not "fix" it back to root

Example verification checklist:

# file metadata
getcap /usr/local/bin/myapp

# service policy
systemctl show myapp.service -p AmbientCapabilities -p CapabilityBoundingSet -p NoNewPrivileges

# listener really came up on a privileged port
ss -ltnp '( sport = :80 )'

# service identity
ps -o user,group,comm,args -C myapp

Enter fullscreen mode Exit fullscreen mode

When capabilities are the wrong tool

Capabilities are not a magic replacement for every privileged workflow.

They are often the wrong choice when:

  • the application still needs broad filesystem access that effectively requires root
  • you are tempted to use CAP_SYS_ADMIN
  • the program is launched through a shared interpreter
  • a reverse proxy, socket activation, or a small privileged helper would be cleaner

Least privilege is not just "fewer root shells". It is choosing the least dangerous mechanism that still keeps operations simple.

Final thought

If a service only needs one narrow privilege, give it one narrow privilege.

That is the real value of Linux capabilities. Not novelty, not cleverness, just a smaller blast radius and a setup you can actually explain during an audit.

References