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

推荐订阅源

Security Latest
Security Latest
Recorded Future
Recorded Future
人人都是产品经理
人人都是产品经理
S
SegmentFault 最新的问题
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
P
Privacy & Cybersecurity Law Blog
WordPress大学
WordPress大学
Know Your Adversary
Know Your Adversary
Spread Privacy
Spread Privacy
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
量子位
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tor Project blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
T
Threatpost
T
Tenable Blog
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
C
Cisco Blogs
H
Heimdal Security Blog
Attack and Defense Labs
Attack and Defense Labs
A
About on SuperTechFans
Last Week in AI
Last Week in AI
N
News and Events Feed by Topic
T
Threat Research - Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
I
Intezer
V
V2EX
Cyberwarzone
Cyberwarzone
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
B
Blog RSS Feed
V
Vulnerabilities – Threatpost
N
Netflix TechBlog - Medium
T
The Blog of Author Tim Ferriss
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
U
Unit 42
PCI Perspectives
PCI Perspectives
P
Privacy International News Feed
D
Docker

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
Your security tool should tell users what to change, not just what's wrong
Bala Paranj · 2026-04-23 · via DEV Community

Our findings said 'this bucket is public.' Users asked 'what do I change to fix it?' We derived the answer mechanically from the predicate AST — no per-rule authoring needed. Here's how counterfactual reasoning turns detection output into actionable fixes.

The finding that doesn't help

Finding: CTL.S3.PUBLIC.001
  Asset:     arn:aws:s3:::prod-assets
  Severity:  high

  DEFECT:
    The bucket's ACL grants read access to the
    AllUsers principal.

  REMEDIATION:
    Remove public access from the bucket ACL,
    or enable Block Public Access.

Enter fullscreen mode Exit fullscreen mode

An engineer reading this knows what's wrong. But does not know:

  • Which specific property in their configuration to change
  • The current value of the property
  • What value would eliminate the finding
  • Whether there are multiple independent fixes (change any one)

DEFECT says "the ACL grants AllUsers read access." REMEDIATION says "remove public access." Neither tells the engineer which line to edit and what to put there.

The engineer opens the console, finds the bucket, reads the ACL, identifies the grant, figures out the fix. Per finding. Fifty times a week.

We added a DELTA section that answers the question directly:

  DELTA:
    Change: bucket ACL grantee
    Current: AllUsers
    Fix: change to any value other than AllUsers,
         or remove the grant

Enter fullscreen mode Exit fullscreen mode

The engineer reads the delta, edits the configuration, re-runs. No console. No manual investigation. The finding told them what to change.

1. The delta comes from the predicate

The delta isn't authored. Nobody wrote "change bucket ACL grantee" for this control. It's derived mechanically from the same predicate that produced the finding.

Every control has a predicate — the condition it checks against observation data. For CTL.S3.PUBLIC.001, the predicate is:

storage.access.acl.grants[].grantee == "AllUsers"

Enter fullscreen mode Exit fullscreen mode

This predicate has three components:

  • Property path: storage.access.acl.grants[].grantee
  • Operator: ==
  • Value: "AllUsers"

The finding fires because the property has a value matching the predicate. The delta inverts this: what change to the property would make the predicate stop matching?

== "AllUsers"  →  "change to any value other than AllUsers"
== true        →  "set to false (disable)"
== false       →  "set to true (enable)"
contains "X"   →  "remove X from the list"
> 90           →  "reduce to 90 or below"

Enter fullscreen mode Exit fullscreen mode

Each operator has a natural inverse. The inverse, applied to the observed value, is the counterfactual fix.

2. Why it's a counterfactual, not advice

The REMEDIATION field is advice. It's authored by a human who understands the vulnerability: "Remove public access from the bucket ACL." Good advice. Generic. The same text for every bucket that triggers this control, regardless of the specific configuration.

The DELTA field is a counterfactual. It's derived from the specific observation data the engine evaluated:

DELTA:
  Change: bucket ACL grantee
  Current: AllUsers          ← YOUR bucket has this now
  Fix: change to any value   ← this makes YOUR finding
       other than AllUsers      disappear

Enter fullscreen mode Exit fullscreen mode

Advice says "you should probably do X." A counterfactual says "if you do X, this specific finding provably disappears." We verified this: modify the observation data per the delta's suggestion, re-run Stave, finding eliminated. The delta isn't a recommendation. It's a mechanical fact about the predicate.

This is Andreas Zeller's counterfactual causality applied to configuration: "if this value were different, the failure would not occur." The delta computes the minimal difference.

3. Walking the predicate AST

Our predicates aren't strings. They're structured trees — parsed and typed before evaluation. The derivation walks the tree, not a regex.

func DeriveDelta(pred *UnsafePredicate, observed []ObservedProperty) []DeltaPath {
    var paths []DeltaPath
    for _, clause := range pred.Misconfigurations {
        if isKindGate(clause) {
            continue // scope condition, not actionable
        }

        label := registry.Label(clause.PropertyPath)
        if label == "" {
            continue // unlabeled path, skip rather than show schema names
        }

        current := findObserved(observed, clause.PropertyPath)
        fix := invertOperator(clause.Operator, clause.Value)

        paths = append(paths, DeltaPath{
            PropertyLabel: label,
            CurrentValue:  current,
            FixAction:     fix,
        })
    }
    return paths
}

Enter fullscreen mode Exit fullscreen mode

Three moving parts:

The property registry. Maps schema paths to human-readable labels. storage.access.acl.grants[].grantee becomes "bucket ACL grantee." Authored once for the observation schema (~150 hand-tuned labels), with an algorithmic fallback that handles the rest by stripping namespaces and expanding abbreviations. Covers 99.6% of controls.

The operator inverter. Maps each operator to its counterfactual phrase. == becomes "change to any value other than." contains becomes "remove from the list." > N becomes "reduce to N or below." Boolean-aware: == true becomes "set to false (disable)" not "change to any value other than true."

The observed-value lookup. Pairs each predicate clause with the actual value the engine read during evaluation. The delta shows what YOUR configuration has, not what the predicate checks in the abstract.

4. Compound predicates: independent fix paths

Simple predicates produce one delta. Compound predicates (AND) produce multiple independent fix paths:

Finding: CTL.IAM.ESCALATION.001
  Asset: arn:aws:iam::123456:role/DeployerRole

  DEFECT:
    The role grants iam:PassRole and
    lambda:InvokeFunction without resource
    constraints.

  DELTA:
    Any ONE of these changes eliminates this finding:

    1. role permissions
       Current: [iam:PassRole, lambda:InvokeFunction, ...]
       Fix: remove iam:PassRole from the list

    2. role permissions
       Current: [iam:PassRole, lambda:InvokeFunction, ...]
       Fix: remove lambda:InvokeFunction from the list

Enter fullscreen mode Exit fullscreen mode

The predicate is permissions contains "iam:PassRole" AND permissions contains "lambda:InvokeFunction". Both clauses must be true for the finding to fire. Negating either one eliminates the finding. The delta shows both options; the engineer picks whichever is cheaper.

This is the practical value of walking the AST. A string-based approach would have to parse "A AND B" with regex. The AST already has the conjunction structure — each child of an AND node is an independent fix path.

5. What the derivation skips

Not every predicate clause produces a useful delta:

Kind-gates. Many predicates start with a scope condition: asset.kind == "bucket". This isn't an actionable defect — you can't "change the asset kind" to fix a security issue. The derivation filters these out. Any clause matching *.kind == value or *.type == value is a scope condition, not a delta candidate.

Parameter references. Some predicates compare against configurable thresholds: password_length < $min_length. The threshold is a parameter, not a fixed value. The delta for these would be "increase to at least $min_length" — useful but requires resolving the parameter. Skipped in the current implementation; the REMEDIATION field covers these cases with authored guidance.

Complex OR branches. AND predicates produce independent fix paths (fix any one). OR predicates require fixing all branches (any one independently triggers the finding). The rendering for "ALL of these changes are needed" is less intuitive than "any ONE." Currently skipped — OR predicates show no DELTA section and fall back to REMEDIATION.

Unlabeled property paths. If the property registry doesn't have a human-readable label for a path, the derivation skips it rather than showing raw schema names like identity.credentials.access_key.last_rotated. Schema paths in user-facing output look like implementation leaking through. Better to show nothing than to show noise.

6. Coverage without authoring

The derivation covers 672 of 675 controls. No per-control authoring. The same three inputs — property registry, operator inverter, observed values — produce deltas for every control whose predicate the AST walker can handle.

Compare with the defect description, which uses the same infrastructure:

Output section Source Coverage Authoring needed
DEFECT Predicate-derived or per-control override 672/675 (99.6%) ~150 registry labels (one-time)
INFECTION Family template or per-control override 675/675 47 family templates
FAILURE Family template or per-control override 675/675 47 family templates
OBSERVED Engine property-access trace 675/675 Zero
DELTA Predicate-derived counterfactual 672/675 (99.6%) Zero (uses defect registry)

The DELTA section reuses the property registry from defect derivation. Authoring the registry once serves both purposes. The operator inverter is ~30 lines of Go. The AST walker is shared with defect derivation.

Total new code for the delta: the inverter function and the rendering. The infrastructure was already built.

7. Verifying the counterfactual

A delta that says "change X to Y" but doesn't eliminate the finding is worse than no delta at all. The user follows the suggestion, re-runs, and the finding persists. Trust is destroyed.

We verified the counterfactual by testing it:

  1. Run Stave against a fixture → finding fires, delta says "change public_read to false"
  2. Modify the observation: set public_read to false
  3. Re-run Stave → finding eliminated

The delta's suggestion genuinely eliminates the finding. This isn't a proof for every possible observation (the predicate logic guarantees it — negating any clause in an AND predicate makes the conjunction false), but running it confirms the derivation doesn't have bugs the logic guarantees shouldn't exist.

When to add counterfactual output

The pattern applies to any tool that evaluates conditions against data:

  1. Linters that flag rule violations can show "change this token/value to eliminate the warning." The lint rule's AST encodes what it checks; the inverse is the fix.

  2. Policy engines that evaluate policies against configurations can show "this policy clause fails because of this value; changing it to X makes the policy pass."

  3. Compliance scanners that check controls against evidence can show "this control fails because this property is X; the control passes when the property is Y."

  4. Validators that check schemas against data can show "this field fails validation because its value is X; valid values are Y."

The common prerequisite: the tool's rules must be structured (AST, typed predicates, parsed expressions) rather than opaque (arbitrary code, black-box functions). If you can walk the rule's structure, you can invert it. If the rule is a function pointer, you can't.

Reducing the Triage Time

Most security tools stop at detection. They tell you what's wrong. Some add remediation — authored advice about what to do. Very few tell you the specific, mechanically-verified change that eliminates the specific finding on your specific configuration.

The gap between "this bucket is public" and "change grants[0].grantee from AllUsers to a restricted principal" is where triage time lives. The first is a finding. The second is an action. Engineers act on actions, not findings.

The delta closes that gap without per-rule authoring. The predicate already knows what it checks. The observation already records what exists. The counterfactual is the mechanical inverse of the match. The only work is building the inversion — once — and letting it scale to every rule in the catalog.

Your security tool already knows why the finding fired. It should tell the user what to change.


The code discussed in this article is from Stave, an open-source security CLI that evaluates cloud configurations against a catalog of controls.