<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Riotaro OKADA</title>
    <description>The latest articles on DEV Community by Riotaro OKADA (@riotaro).</description>
    <link>https://dev.to/riotaro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F655466%2F23332fb2-0e47-470b-bdb3-5b7e1feb6696.jpeg</url>
      <title>DEV Community: Riotaro OKADA</title>
      <link>https://dev.to/riotaro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/riotaro"/>
    <language>en</language>
    <item>
      <title>Hardening Cheatsheet for Codex CLI — and the Design Philosophy Was Fascinating</title>
      <dc:creator>Riotaro OKADA</dc:creator>
      <pubDate>Fri, 27 Mar 2026 13:39:14 +0000</pubDate>
      <link>https://dev.to/riotaro/hardening-cheatsheet-for-codex-cli-and-the-design-philosophy-was-fascinating-1jch</link>
      <guid>https://dev.to/riotaro/hardening-cheatsheet-for-codex-cli-and-the-design-philosophy-was-fascinating-1jch</guid>
      <description>&lt;p&gt;Today, I published a hardening cheatsheet for Codex CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/okdt/codex-cli-hardening-cheatsheet" rel="noopener noreferrer"&gt;okdt/codex-cli-hardening-cheatsheet&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Hardening Matters
&lt;/h2&gt;

&lt;p&gt;Codex CLI is powerful. It reads and writes files, runs shell commands, and can reach out to external services — all autonomously, on your behalf.&lt;/p&gt;

&lt;p&gt;But give it &lt;code&gt;danger-full-access&lt;/code&gt; with broad permissions, and that autonomy becomes the blast radius. "Let me tidy up" — and it touches files outside your workspace. "Fixed that for you" — and it rewrites your &lt;code&gt;.gitconfig&lt;/code&gt;. Technically correct, maybe. But beyond what you intended.&lt;/p&gt;

&lt;p&gt;Then there's indirect prompt injection. A malicious instruction buried in a fetched README, an issue body, or a dependency's postinstall script can lead Codex CLI to "add this package for you" or "run this script first" — actions you never asked for.&lt;/p&gt;

&lt;p&gt;And here's the thing about AI confidence: humans and AI both get things wrong with full conviction, but AI doesn't show you a hesitant face. Applying a plausible-sounding suggestion without verification is risky.&lt;/p&gt;

&lt;p&gt;"Can't I just write 'don't do that' in AGENTS.md?" — I hear this a lot. The answer is no. Instruction files are prompts, not policies. They have no enforcement power. When you want to prevent something from happening, you enforce it as policy, not request it as a favor. That's what &lt;code&gt;config.toml&lt;/code&gt; hardening is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Cat and a Sheepdog
&lt;/h2&gt;

&lt;p&gt;Working with Claude Code feels like having a sharp, slightly unpredictable cat as a thinking partner. It surprises you. It pushes back. Sometimes it goes somewhere you didn't expect, and that detour turns out to be exactly right.&lt;/p&gt;

&lt;p&gt;Codex CLI is nothing like that.&lt;/p&gt;

&lt;p&gt;It's a sheepdog. Smart, loyal, hardworking — but it stays inside the fence. It doesn't go outside. It &lt;em&gt;can't&lt;/em&gt; go outside. Not because of temperament, but because that's how the fence is built.&lt;/p&gt;

&lt;p&gt;I wrote this cheatsheet to help people configure those fences well. But in the process of reading through &lt;code&gt;config.toml&lt;/code&gt; line by line, I found the fence design itself genuinely fascinating. That's what this post is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fence
&lt;/h2&gt;

&lt;p&gt;Codex CLI's security configuration is structured around four axes: sandbox, approval, network, and history. Each one functions as an independent defense layer.&lt;/p&gt;

&lt;p&gt;If the sandbox config is too loose, approval catches it. If you accidentally approve something you shouldn't have, the network being closed keeps data from leaving. You can see the layers of defense just by looking at how the config file is organized. "Defense in depth" is a phrase that gets thrown around a lot — Codex CLI actually implements it in the structure of &lt;code&gt;config.toml&lt;/code&gt;. That's elegant.&lt;/p&gt;

&lt;p&gt;Network access is closed by default. You open it only when needed, through a profile. The worldview is: &lt;em&gt;open is the exception&lt;/em&gt;. Even if prompt injection hits, data doesn't leave the fence. This "closed by default" decision, baked into the design, is quiet but significant.&lt;/p&gt;

&lt;p&gt;And the name of the widest sandbox mode? Not &lt;code&gt;full-access&lt;/code&gt;. It's &lt;strong&gt;&lt;code&gt;danger&lt;/code&gt;-full-access&lt;/strong&gt;. The name tells you that opening up is dangerous. A small thing, but this is where a designer's values show through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declaring Your Posture
&lt;/h2&gt;

&lt;p&gt;The feature that fascinated me most was profiles. Codex CLI lets you define multiple profiles in &lt;code&gt;config.toml&lt;/code&gt; and switch between them with &lt;code&gt;--profile&lt;/code&gt;. You declare your working posture as a permission before you start.&lt;/p&gt;

&lt;p&gt;Obvious in hindsight, but having it as a first-class mechanism in the config file matters.&lt;/p&gt;

&lt;p&gt;The thing is, Codex CLI gives you the mechanism but not the names. And naming matters more than you'd think — call something &lt;code&gt;full_auto&lt;/code&gt; and people will use it like it's full auto, regardless of what the actual permissions are.&lt;/p&gt;

&lt;p&gt;In the cheatsheet, I named them &lt;code&gt;readonly_quiet&lt;/code&gt;, &lt;code&gt;local_write&lt;/code&gt;, and &lt;code&gt;remote_enabled&lt;/code&gt;. Names that say exactly what they do. When names are honest, operations stay honest too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audit Was There from the Start
&lt;/h2&gt;

&lt;p&gt;I was genuinely surprised to find OpenTelemetry integration sitting right there in &lt;code&gt;config.toml&lt;/code&gt;. Tool approvals and rejections, execution results, API calls — all of it can be exported to your organization's existing observability stack.&lt;/p&gt;

&lt;p&gt;It's not prominently featured in the docs, but this is the design of a tool built for organizations, not just individuals. That's sheepdog thinking, too — if you work on a ranch, the rancher needs to know what you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  If You Open the Fence Yourself
&lt;/h2&gt;

&lt;p&gt;Here's the thing, though. No matter how well the fence is designed, &lt;code&gt;danger-full-access&lt;/code&gt; + &lt;code&gt;approval_policy = "never"&lt;/code&gt; bypasses everything. If you open the fence yourself, even the sheepdog can't stop you.&lt;/p&gt;

&lt;p&gt;This cheatsheet exists to prevent that kind of waste. Copy the Quick Start template to &lt;code&gt;~/.codex/config.toml&lt;/code&gt; and you start from a secure baseline. The detailed reasoning and OWASP LLM Top 10 mapping are in the cheatsheet itself — give it a read.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Took Away
&lt;/h2&gt;

&lt;p&gt;AI coding tool security is still uncharted territory. Every tool is figuring it out as they go.&lt;/p&gt;

&lt;p&gt;Reading through Codex CLI's &lt;code&gt;config.toml&lt;/code&gt; one line at a time, watching the designer's thinking emerge from what looks like mundane configuration — that was genuinely enjoyable. Solid, honest, unglamorous, but trustworthy. A good sheepdog.&lt;/p&gt;

&lt;p&gt;Licensed under CC BY-SA 4.0. Feedback and contributions are welcome.&lt;/p&gt;

&lt;p&gt;Now, if you'll excuse me — I'm grabbing a beer. Happy weekend.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/okdt/codex-cli-hardening-cheatsheet" rel="noopener noreferrer"&gt;okdt/codex-cli-hardening-cheatsheet&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hardening Cheatsheet for Claude Code's settings.json</title>
      <dc:creator>Riotaro OKADA</dc:creator>
      <pubDate>Mon, 23 Mar 2026 06:30:16 +0000</pubDate>
      <link>https://dev.to/riotaro/hardening-cheatsheet-for-claude-codes-settingsjson-20lk</link>
      <guid>https://dev.to/riotaro/hardening-cheatsheet-for-claude-codes-settingsjson-20lk</guid>
      <description>&lt;p&gt;Claude Code is remarkable. It runs shell commands, reads and writes files, connects to external services, and works autonomously toward your goals. Honestly, I can't go back to working without it.&lt;/p&gt;

&lt;p&gt;But then I caught myself. I was reflexively moving to "yes" and slamming ENTER on every permission prompt. When you're in the zone, you don't want to stop and read what it's asking. But what if that "yes" was for &lt;code&gt;rm -rf&lt;/code&gt;? Or &lt;code&gt;git push --force&lt;/code&gt;? Or worse — some abstract task that internally triggers a cascade of deletions or publications, and "undo" isn't an option?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Risks Are Real
&lt;/h2&gt;

&lt;p&gt;Claude Code doesn't have malicious intent. But it can hallucinate. It can take well-intentioned actions that go far beyond what you asked for — deleting files to "clean up," force-pushing to "fix" a branch, installing packages you never requested. Good intentions, excessive action.&lt;/p&gt;

&lt;p&gt;Then there's indirect prompt injection. The source code, documents, and web pages that Claude Code processes during normal work could contain hidden instructions. An attacker embeds a malicious prompt in a dependency or a document, and Claude follows it without question.&lt;/p&gt;

&lt;p&gt;And here's one that keeps me up at night: we've always had risk scenarios for local exploits — what happens when an attacker gains user-level access to your machine. Now imagine Claude Code is sitting there too, with the ability to run any command your user account can run. The blast radius just got a lot bigger.&lt;/p&gt;

&lt;p&gt;These map directly to the &lt;a href="https://genai.owasp.org/llm-top-10/" rel="noopener noreferrer"&gt;OWASP Top 10 for LLM Applications&lt;/a&gt;: Overreliance (LLM09), Excessive Agency (LLM06), and Prompt Injection (LLM01).&lt;/p&gt;

&lt;h2&gt;
  
  
  Sandbox First
&lt;/h2&gt;

&lt;p&gt;Everyone should enable sandboxing. It's the strongest protection layer available — OS-level isolation of file and network access. Just run &lt;code&gt;/sandbox&lt;/code&gt; in Claude Code's interactive mode. The cheatsheet covers the setup and configuration.&lt;/p&gt;

&lt;p&gt;Here's why it matters: deny rules alone have gaps. If you deny &lt;code&gt;Read(**/.env)&lt;/code&gt;, Claude's built-in Read tool is blocked. But &lt;code&gt;cat .env&lt;/code&gt; through Bash? That goes right through. Read deny and Bash deny are separate layers that don't cover each other. The sandbox catches what deny rules miss.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude Code's settings.json Can Do
&lt;/h2&gt;

&lt;p&gt;Claude Code has a &lt;code&gt;~/.claude/settings.json&lt;/code&gt; file that controls permissions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;deny&lt;/strong&gt; — commands that are always blocked, no prompt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ask&lt;/strong&gt; — commands that always prompt, even if you previously said "don't ask again"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;allow&lt;/strong&gt; — commands that are always permitted without prompting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Put &lt;code&gt;rm -rf&lt;/code&gt;, &lt;code&gt;sudo&lt;/code&gt;, and &lt;code&gt;git push --force&lt;/code&gt; in your deny list, and Claude Code simply can't execute them, no matter how much it "wants" to.&lt;/p&gt;

&lt;p&gt;But database commands like &lt;code&gt;psql&lt;/code&gt;? If you deny those, you block &lt;code&gt;SELECT&lt;/code&gt; and &lt;code&gt;DROP TABLE&lt;/code&gt; alike. For these, &lt;code&gt;ask&lt;/code&gt; is the practical choice — you get prompted every time and can check what's actually being run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Your Brain" Problem
&lt;/h2&gt;

&lt;p&gt;My favorite line in the whole cheatsheet is in the permission levels table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Permission&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;th&gt;Where to set&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;(default)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Prompted on first use; "don't ask again" makes it permanent&lt;/td&gt;
&lt;td&gt;Your brain — which may say yes too quickly when busy, or can't tell safe from unsafe when tired&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The default behavior is "ask the user." But the judgment happens in &lt;strong&gt;your brain&lt;/strong&gt;. The one that's rushing to meet a deadline. The one that's not sure what &lt;code&gt;chmod -R&lt;/code&gt; actually does in this context. The one that already said "don't ask again" three prompts ago.&lt;/p&gt;

&lt;p&gt;That's why &lt;code&gt;deny&lt;/code&gt; exists. It doesn't get tired. It doesn't rush. It doesn't second-guess itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cheatsheet
&lt;/h2&gt;

&lt;p&gt;I organized all of this into a cheatsheet and published it on GitHub. I plan to keep updating it, so issues and pull requests are welcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/okdt/claude-code-hardening-cheatsheet" rel="noopener noreferrer"&gt;okdt/claude-code-hardening-cheatsheet&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Read the README and full cheatsheet &lt;a href="https://github.com/okdt/claude-code-hardening-cheatsheet" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why Claude Code needs hardening (risk scenarios with references to OWASP LLM Top 10)&lt;/li&gt;
&lt;li&gt;Sandbox setup — everyone should do this&lt;/li&gt;
&lt;li&gt;The permission system: deny, ask, allow, and how they interact

&lt;ul&gt;
&lt;li&gt;Deny lists by threat category (git ops, file deletion, privilege escalation, remote access, macOS-specific commands, and more)&lt;/li&gt;
&lt;li&gt;Human-in-the-Loop (HITL) with &lt;code&gt;ask&lt;/code&gt; rules&lt;/li&gt;
&lt;li&gt;Limitations of deny rules and defense in depth with Hooks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Available in both English and Japanese. Loosely styled after the OWASP Cheat Sheet Series — whether it ends up there is another question, but the structure is ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use It
&lt;/h2&gt;

&lt;p&gt;Clone the repo and review &lt;code&gt;settings_example.jsonc&lt;/code&gt;. Don't copy it blindly — read the cheatsheet to understand &lt;em&gt;why&lt;/em&gt; each rule exists, then pick what applies to your environment.&lt;/p&gt;

&lt;p&gt;The deny list is a sample of what I wanted to block first. It's not exhaustive. Your environment is different from mine.&lt;/p&gt;

&lt;p&gt;Licensed under CC BY-SA 4.0. Use it freely for documentation, training materials, or anything else — just let me know if you do, I'd love to hear about it. If you modify it, share under the same license. Feedback and additional rules for other platforms are welcome.&lt;/p&gt;

&lt;p&gt;Now, if you'll excuse me, I'm going to go make some coffee.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/okdt/claude-code-hardening-cheatsheet" rel="noopener noreferrer"&gt;okdt/claude-code-hardening-cheatsheet&lt;/a&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>security</category>
      <category>agentaichallenge</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
