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

推荐订阅源

T
Tor Project blog
B
Blog RSS Feed
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
H
Hackread – Cybersecurity News, Data Breaches, AI and More
罗磊的独立博客
GbyAI
GbyAI
N
Netflix TechBlog - Medium
博客园 - 司徒正美
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
W
WeLiveSecurity
Stack Overflow Blog
Stack Overflow Blog
Y
Y Combinator Blog
SecWiki News
SecWiki News
V
Vulnerabilities – Threatpost
Google DeepMind News
Google DeepMind News
C
CERT Recently Published Vulnerability Notes
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Register - Security
The Register - Security
Cisco Talos Blog
Cisco Talos Blog
Martin Fowler
Martin Fowler
A
About on SuperTechFans
S
Security @ Cisco Blogs
T
Tenable Blog
C
Check Point Blog
N
News and Events Feed by Topic
S
SegmentFault 最新的问题
The GitHub Blog
The GitHub Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Attack and Defense Labs
Attack and Defense Labs
美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
Cisco Blogs
P
Palo Alto Networks Blog
V
V2EX
博客园 - 聂微东
Project Zero
Project Zero
酷 壳 – CoolShell
酷 壳 – CoolShell
D
Docker
N
News | PayPal Newsroom
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
小众软件
小众软件
Application and Cybersecurity Blog
Application and Cybersecurity Blog
人人都是产品经理
人人都是产品经理
V2EX - 技术
V2EX - 技术
I
Intezer
L
LINUX DO - 最新话题

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
How we self-pentested ciguard — Cycle 1: four findings, four advisories, two days
Jo Moore · 2026-04-28 · via DEV Community

4 findings. 4 GHSAs. 4 CVEs requested. Same-day disclosure. v0.8.2 ships with the fixes. v0.8.3 wires the four PoCs in as permanent CI regression gates so the bugs cannot silently return. Total elapsed: ~48 hours. Total cost: $0.30 in cloud spend.

ciguard, briefly

ciguard is a static security auditor for CI/CD pipelines — GitLab CI, GitHub Actions, and Jenkins, plus cross-platform SCA. It ships as pip install ciguard, a multi-arch Docker image, and an MCP server you can plug into Claude Desktop, Claude Code, or Cursor. 44 deterministic rules across three platforms, 17 built-in policies, four output formats including SARIF 2.1.0 with native baseline diffing.

It went public on PyPI on 2026-04-25. The next day, it pentested itself.

This is the writeup of that engagement.

Why self-pentest a security tool?

Two reasons, neither of them tactical:

One — the credibility cost of finding a bug in a security tool is multiplicative. Users assume a security tool is itself secure. The moment a CVE lands against ciguard, the question every potential adopter asks is "if they couldn't keep their own code clean, why would I trust their findings about mine?" The way you avoid that is by surfacing the bugs yourself, in public, with a methodology that holds up to scrutiny.

Two — pre-adoption-traction is exactly when self-pentest is cheapest. ciguard had ~zero installs at v0.8.1 ship. No users are exposed by a Critical finding I'd have surfaced too late. Cost = my time + ~$0.30 in cloud spend (ephemeral droplet, destroyed at cycle close). Compare that to the cost once we have real users in real CI pipelines.

So: a recurring 6-monthly cadence, starting now, scoped to the surfaces ciguard actually exposes. CREST-aligned methodology because if I ever bring in an external reviewer, the report shouldn't get dismissed as "ad-hoc."

The methodology

PTES structure (Phases 0–7) for the engagement timeline. OWASP Testing Guide v4.2 for the execution checklist. CREST framing for the report so the format reads as a professional engagement, not a self-cert.

The lab: ephemeral DigitalOcean droplet provisioned by Terraform, Ubuntu 24.04, full toolchain (atheris, ZAP, semgrep, Trivy, ffuf, gobuster, nmap) installed via cloud-init in 3-5 minutes. make up CYCLE=1 to bring it up; make destroy && make nuke at close-out. Total cycle cost: $0.30 of a $50 cap. The droplet is destroyed at cycle close; Cycle 2 reprovisions from scratch with whatever the latest tool versions are then.

Why cloud-ephemeral instead of Kali-in-UTM (the original plan)? Three reasons: my Mac doesn't have 60 GB free for a VM; "attacker tools never run on the target machine" is honoured by cloud separation; and reprovisioning Cycle 2 in October from the same Terraform doesn't depend on a snapshot that's drifted six months.

Scope: six of ciguard's eight surfaces — CLI, parsers, FastAPI Web UI, reporters, baseline+delta, MCP server. Out of scope: the GitHub App and hosted SaaS, neither of which has shipped yet — they get assessed when they do. Supply chain is out of scope because it's already covered by Trivy + OIDC publishing; social engineering and physical access are out of scope by definition for a one-person open-source project.

What we found

Four findings — one Medium, three Low. No Critical or High.

Finding Severity CVSS v4.0 GHSA
CYCLE-1-001discover_pipeline_files follows symlinks out of scan root Medium 5.7 GHSA-8cxw-cc62-q28v
CYCLE-1-002 — Container image runs as root Low 3.4 GHSA-jrm4-4pcf-4763
CYCLE-1-003 — SCA HTTP client reads response body unbounded Low 3.1 GHSA-xw8c-rrvx-f7xq
CYCLE-1-004 — Web UI missing HTTP defence-in-depth headers Low (Medium hosted) 4.3 GHSA-7ww3-xvf5-cxwm

The interesting one is CYCLE-1-001. ciguard ships an MCP server. One of the tools it exposes is scan_repo, which walks a directory and audits any pipeline files it finds. The threat scenario writes itself: an AI agent gets fed an adversarial prompt — "Scan /tmp/cloned-suspicious-repo for pipeline issues" — and the cloned-untrusted-source repo contains symlinks pointing at ~/.aws/, ~/.ssh/, or /etc/some-secret-pipeline/. Discovery walks the symlinks, returns the symlink-target paths and their contents to the AI, which faithfully reports the "findings" back. Pipeline files often contain hardcoded secrets, internal hostnames, deploy keys.

Confused-deputy via MCP. Realistic in 2026 in a way it wasn't a year ago. Mitigated in v0.8.2 with follow_symlinks=False as the new default for the discovery walker, plus a belt-and-braces filter that drops any result whose .resolve() lies outside the scan root.

The other three — container as root, unbounded HTTP read, and missing defence-in-depth headers — are bread-and-butter findings that any CREST-style engagement would surface. Useful catches that strengthen the posture; nothing exotic.

What didn't find anything (also worth saying)

ciguard had passed Bandit + pip-audit + Trivy gates on every commit since v0.1.4 (2026-04-25). That accumulated discipline showed up in what the cycle didn't find:

  • Atheris coverage-guided fuzzing — 220k iterations across all three parsers (GitLabCIParser, GitHubActionsParser, hand-rolled JenkinsfileParser). Zero crashes, zero hangs, memory ceiling 65 MB. The Jenkinsfile parser was the highest-risk surface per threat model (no upstream parser to inherit hardening from); it survived clean.
  • Stored XSS via Jinja template injection — the HTML reporter renders findings into a template. Carefully crafted pipeline content with <script>alert(1)</script> payloads. Auto-escape is on; the payload renders as &lt;script&gt;alert(1)&lt;/script&gt; inside a <pre> block. Defence-in-depth working.
  • YAML deserialisation — every loader is yaml.SafeLoader, no exceptions. pickle and eval and exec of user input — zero occurrences in src/.
  • MCP gate (CIGUARD_MCP_DISABLED) truthy parsing — 25-case battery covering canonical truthy, mixed case, whitespace, falsy, empty, substring confusion (yesno, true_thing), numeric coincidence (01, 00, 2), literal escapes. All correctly classified.

Documenting what passed matters because it forms the regression watchlist for future cycles. These are the things to re-check first when a refactor lands.

The disclosure decision

Standard responsible-disclosure convention: 14-day window between fix-ship and public advisory. v0.8.2 shipped 2026-04-27. Standard would publish the GHSAs on 2026-05-11.

I published all four same-day instead.

The 14-day window protects affected users — it gives them time to upgrade between the patch landing and the vulnerability becoming public. The standard policy assumes there is a user base whose safety would be compromised by faster disclosure.

ciguard had ~zero downloads at v0.8.1 ship. No affected users → no safety upside to waiting → standard policy adapts to publish promptly. v0.8.2 has been the default pip install ciguard since 2026-04-27; anyone landing on the project from this point forward gets the fixed version.

The credibility upside of immediate disclosure was the deciding factor: a public set of GHSAs (with CVEs requested, propagating to NVD over the following days) is the strongest possible artefact of "we self-pentested and shipped the fixes the same day." Withholding them for two weeks would have delayed exactly the thing that makes a self-pentest valuable as a credibility signal.

The decision is documented in the Cycle 1 final report's Definition of Done section. By Cycle 2 (October 2026), ciguard may have actual users, and the standard 14-day window applies again. This is a judgement call per cycle, not a permanent policy.

Closing the loop — making sure these don't come back

Cycle 1's final-report recommendations included two CI hooks that just shipped in v0.8.3:

Recommendation #2 — wire the four PoC scripts in as CI regression gates. Each of the four PoCs has a binary outcome encoded in its exit code: 0 = EXPLOIT_CONFIRMED, 1 = EXPLOIT_FAILED. v0.8.3 adds tests/regression/cycle1/ holding the four scripts as live regression copies, plus a new regression-cycle1 job in the reusable _checks.yml workflow that runs all four on every push, every PR, and every release tag. Inverts each script's exit code so the build fails only when a regression appears. The container PoC builds the image locally first so the gate fires before publish, not after.

The unit tests added in v0.8.2 cover the fixes as code paths. The PoC regression gates cover the exploit chains end-to-end. A future refactor that breaks the security guarantee in a different layer can pass the unit tests and fail the PoC — that's the property we want.

Recommendation #3 — schedule a weekly atheris fuzz cron. v0.8.3 adds .github/workflows/atheris-fuzz.yml running 1M iterations of coverage-guided fuzz across all three parsers every Sunday 06:00 UTC. Per-input timeout 10s, total budget 30 minutes. Crash uploads the input as a 30-day artifact and opens a security/fuzz-finding issue. Manual workflow_dispatch accepts a custom iteration count for spot runs.

Cycle 1 ran 220k iterations in ~2 minutes and surfaced no crashes; weekly 1M is cheap insurance against regressions when new rules or parser refactors land.

What's next

Cycle 2 is scheduled for 2026-10-28 → 2026-11-11 (six-monthly cadence). The Terraform lab gets reprovisioned from scratch with then-current tool versions; the report template clones from Cycle 1's. Same Definition of Done, applied to whatever surfaces have shipped by then (likely the v0.9.0 GitHub App + ciguard scan-repo CLI).

The four GHSAs are public as of today. CVE numbers from MITRE are working their way through GitHub's CNA pipeline and should attach to the advisories over the next few days; once they propagate, the GHSAs auto-decorate with CVE-2026-NNNN IDs.

If you're maintaining a security tool — or any open-source tool with a non-trivial attack surface — and you've been waiting for the "right moment" to do a self-pentest: do it before you have users. The cost is your time and a few dollars. The upside is a defensible posture that doesn't depend on nobody bothering to look.

Links

If you spot something in ciguard that should have been on this list, open a security advisory. Cycle 2 will gladly cite you.