<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Developer-Tools on </title>
    <link>https://augmentedresilience.com/tags/developer-tools/</link>
    <description>Recent content in Developer-Tools on </description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Sun, 19 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://augmentedresilience.com/tags/developer-tools/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>AI Writes Code Fast. Here&#39;s Why Security-First Thinking Matters More Than Ever.</title>
      <link>https://augmentedresilience.com/posts/augmented-resilience-posts/ai-writes-code-fast.-here-is-why-security-first-thinking-matters-more-than-ever/</link>
      <pubDate>Sun, 19 Apr 2026 00:00:00 +0000</pubDate>
      
      <guid>https://augmentedresilience.com/posts/augmented-resilience-posts/ai-writes-code-fast.-here-is-why-security-first-thinking-matters-more-than-ever/</guid>
      <description>&lt;h2 id=&#34;speed-is-the-feature-unexamined-speed-is-the-liability&#34;&gt;Speed Is the Feature. Unexamined Speed Is the Liability.&lt;/h2&gt;
&lt;p&gt;One of the most impressive things about using AI to write code is how fast it moves. You describe an endpoint, a data model, a feature — and within seconds you have working code. Not a sketch. Not pseudocode. Actual, runnable implementation.&lt;/p&gt;
&lt;p&gt;That speed is real, and it is genuinely useful. I use it every day.&lt;/p&gt;
&lt;p&gt;But here is something I noticed the longer I worked with AI-generated code: it writes to the happy path. AI is extraordinarily good at making code that works when everything goes as expected. It is considerably less reliable at writing code that stays safe when things go wrong — when someone sends unexpected input, when a dependency is compromised, when a secret accidentally surfaces in a log, when a logged-in user tries to access someone else&amp;rsquo;s data.&lt;/p&gt;</description>
      <content>&lt;h2 id=&#34;speed-is-the-feature-unexamined-speed-is-the-liability&#34;&gt;Speed Is the Feature. Unexamined Speed Is the Liability.&lt;/h2&gt;
&lt;p&gt;One of the most impressive things about using AI to write code is how fast it moves. You describe an endpoint, a data model, a feature — and within seconds you have working code. Not a sketch. Not pseudocode. Actual, runnable implementation.&lt;/p&gt;
&lt;p&gt;That speed is real, and it is genuinely useful. I use it every day.&lt;/p&gt;
&lt;p&gt;But here is something I noticed the longer I worked with AI-generated code: it writes to the happy path. AI is extraordinarily good at making code that works when everything goes as expected. It is considerably less reliable at writing code that stays safe when things go wrong — when someone sends unexpected input, when a dependency is compromised, when a secret accidentally surfaces in a log, when a logged-in user tries to access someone else&amp;rsquo;s data.&lt;/p&gt;
&lt;p&gt;This is not a criticism of AI models. It is a structural observation about how code generation works. AI learns from what code looks like, not from what happens to systems that run it. The attack surface is invisible at generation time.&lt;/p&gt;
&lt;p&gt;Security-first thinking is the discipline that fills that gap. And building it into how you work with AI is one of the highest-leverage things you can do as a developer.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;what-ai-gets-wrong-by-default&#34;&gt;What AI Gets Wrong By Default&lt;/h2&gt;
&lt;p&gt;Before we get to principles, it helps to see the failure modes concretely. These are patterns I started noticing after reviewing AI-generated code more carefully.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hardcoded secrets.&lt;/strong&gt; Ask AI to write a function that connects to a database or calls an external API, and it will often produce something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;db &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; connect(host&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;prod-db.company.com&amp;#34;&lt;/span&gt;, user&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;, password&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Sup3rS3cr3t!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;client &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; OpenAI(api_key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sk-proj-abc123...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code works. It will also put your credentials in git history forever. A secret committed to a repository — even briefly, even to a private repo — must be treated as compromised. Git history is permanent. The only remediation is rotation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Missing input validation.&lt;/strong&gt; AI tends to write code that trusts request data. An endpoint that receives &lt;code&gt;req.body.quantity&lt;/code&gt; will often use it directly, skipping the check for whether it is a positive integer, whether it is within expected bounds, whether it contains what the code assumes it contains.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fetch-then-check authorization.&lt;/strong&gt; This one is subtle. AI commonly writes authorization logic like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;order&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;db&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;orders&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;findById&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;req&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;params&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;id&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;order&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;userId&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!==&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;req&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;id&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;res&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;403&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;send&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;res&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;json&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;order&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That looks right. But it fetches the record first and checks ownership second. A slightly better pattern is to include the user ID in the query itself, so that non-owned records simply return null — and you return a 404, not a 403. Returning 403 confirms to an attacker that the resource exists. It is a small thing that compounds at scale.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Weak cryptography by familiarity.&lt;/strong&gt; Ask AI to hash a password and it might reach for SHA-256. SHA-256 is a solid hash function — for data integrity. It is the wrong tool for passwords because it is fast. Fast means a GPU can test billions of candidate passwords per second against a leaked hash. bcrypt and Argon2 are deliberately slow. That slowness is the security property.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No rate limiting on authentication.&lt;/strong&gt; AI generates login endpoints without the defensive scaffolding that should always accompany them: rate limiting per IP, account lockout after repeated failures, uniform response times to prevent user enumeration.&lt;/p&gt;
&lt;p&gt;None of these are exotic edge cases. They are the everyday failure modes that show up in security audits and breach post-mortems, again and again.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;the-mindset-shift-from-checklist-to-first-principles&#34;&gt;The Mindset Shift: From Checklist to First Principles&lt;/h2&gt;
&lt;p&gt;Here is where I want to push back against the usual framing. Security is often presented as a checklist — OWASP Top 10, compliance requirements, &amp;ldquo;use HTTPS.&amp;rdquo; Checklists have their place, but they do not produce secure code. They produce code that passes the checklist.&lt;/p&gt;
&lt;p&gt;Security-first thinking is different. It is a way of looking at code that asks one question at every boundary: &lt;em&gt;who or what is being trusted here, and has that trust been earned?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Every class of vulnerability — SQL injection, XSS, CSRF, IDOR, broken authentication, insecure deserialization — reduces to a single failure: &lt;strong&gt;untrusted data crossing a trust boundary with the authority of trusted data.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SQL injection happens when user input is trusted to be SQL-safe before it reaches the database. XSS happens when user-generated content is trusted to be display-safe before it enters the DOM. IDOR happens when a request parameter is trusted to represent a resource the current user is allowed to access.&lt;/p&gt;
&lt;p&gt;Once you see security through this lens — trust boundaries and their enforcement — you stop asking &amp;ldquo;did I remember the checklist item?&amp;rdquo; and start asking &amp;ldquo;where are the trust boundaries in this code, and what enforces them?&amp;rdquo; That question applies to every system, every language, every framework. It does not go stale.&lt;/p&gt;
&lt;p&gt;This is what I mean by security-first thinking as a mindset rather than a procedure. It is not about knowing rules. It is about developing the habit of seeing trust assumptions in code.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;the-eight-principles&#34;&gt;The Eight Principles&lt;/h2&gt;
&lt;p&gt;When I worked through this with Luna recently — building a security knowledge base from 50 cybersecurity books — we distilled the trust boundary framework down to eight irreducible properties that AI-generated code must satisfy.&lt;/p&gt;
&lt;p&gt;I want to walk through each one because they are not independent rules. They are facets of the same underlying principle.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Input is untrusted by default.&lt;/strong&gt; Every value arriving from outside your process — HTTP body, query parameters, headers, cookies, file uploads — is hostile until validated. Client-side validation is UX. Server-side validation is security. They cannot substitute for each other.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Output is encoded for its context.&lt;/strong&gt; A string displayed in HTML needs HTML encoding. A value interpolated into SQL needs parameterization. A value passed to a shell command needs to go through an argument array, not string concatenation. The encoding is not about the string itself — it is about the context it will be interpreted in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Secrets never live in code.&lt;/strong&gt; Passwords, API keys, tokens, certificates — these belong in environment variables or a secrets manager, never in source files. This is absolute. Git history is permanent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Authentication is verified, not assumed.&lt;/strong&gt; Every protected route, every protected function, checks identity on that request. Being logged in at some prior point does not carry forward.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Authorization is checked at the data layer.&lt;/strong&gt; Being authenticated is not the same as being authorized to access a specific resource. Ownership checks belong in the query itself, not as a post-fetch condition.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Least privilege is the default.&lt;/strong&gt; Database connections, service accounts, IAM roles, file operations — each gets only the access its specific function requires. Nothing more. A compromised least-privilege component fails safely. A compromised over-privileged one does not.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. Cryptography is never homegrown.&lt;/strong&gt; Cipher and hash choices go to battle-tested libraries: bcrypt or Argon2 for passwords, AES-GCM for encryption, HMAC-SHA256 for message authentication. The failure modes of hand-rolled crypto are subtle and catastrophic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;8. Dependencies are trust extensions.&lt;/strong&gt; Every package you add is code you are trusting. Its transitive dependencies are code you are trusting. Supply chain attacks are real. Lock files, audits, and version pinning are not paranoia — they are basic hygiene.&lt;/p&gt;
&lt;p&gt;These eight properties are not a checklist to run through at the end. They are filters to apply while generating code. The question during every code-writing session is: which of these are relevant to what I am building right now?&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;baking-it-into-your-ai-workflow&#34;&gt;Baking It Into Your AI Workflow&lt;/h2&gt;
&lt;p&gt;Knowing principles is not the same as applying them consistently. The reason I started building infrastructure around this is that consistency requires more than intention — it requires systems.&lt;/p&gt;
&lt;p&gt;Here is what I built, and it came directly from the work of turning 50 cybersecurity books into a searchable knowledge base.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tier 1 topic files.&lt;/strong&gt; Each of the eight principles above now lives in a concise reference file — 8 to 12KB each — distilled from the source material. &lt;code&gt;input-validation.md&lt;/code&gt;, &lt;code&gt;secrets-management.md&lt;/code&gt;, &lt;code&gt;authentication.md&lt;/code&gt;, &lt;code&gt;authorization.md&lt;/code&gt;, &lt;code&gt;cryptography.md&lt;/code&gt;, and the others. Each file is dense but scannable: concrete patterns, code examples, anti-patterns, quick checklists.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Engineer PREFERENCES.&lt;/strong&gt; I wired those topic files into the Engineer agent through a PREFERENCES file. The trigger table maps code categories to topic files: anything involving SQL gets &lt;code&gt;xss-injection-prevention.md&lt;/code&gt; loaded. Anything involving authentication loads &lt;code&gt;authentication.md&lt;/code&gt;. Anything involving secrets loads &lt;code&gt;secrets-management.md&lt;/code&gt;. The agent loads the relevant files silently before writing code and runs the associated checklist before declaring work done.&lt;/p&gt;
&lt;p&gt;The result is that security context is present in every relevant code-generation session without me having to ask for it. The principles are not something I have to remember to invoke. They are part of the workflow infrastructure.&lt;/p&gt;
&lt;p&gt;This is what I keep coming back to with PAI: the value is not in any single AI interaction. It is in building infrastructure that makes the right thing the default thing. Security-first code used to require conscious effort and specialized knowledge in the moment. Now it is loaded context — always present, reliably applied.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;security-and-ai-are-not-in-tension&#34;&gt;Security and AI Are Not in Tension&lt;/h2&gt;
&lt;p&gt;I want to end on this because it is easy to come away from a security conversation feeling like the message is &amp;ldquo;AI is dangerous, slow down, be careful.&amp;rdquo; That is not the message.&lt;/p&gt;
&lt;p&gt;AI writing code fast is a genuine capability improvement. Being able to go from specification to working implementation in minutes changes what is possible for a small team or a solo developer. That is real.&lt;/p&gt;
&lt;p&gt;Security-first thinking is not a constraint on that capability. It is the thing that makes the output of that capability trustworthy. Code that moves fast and ships vulnerable systems is not actually faster in any meaningful sense — it is accumulating debt that will be paid with interest.&lt;/p&gt;
&lt;p&gt;The combination is the point. AI that knows how to think about trust boundaries, that loads security context automatically, that applies principles rather than just patterns — that is a force multiplier, not a liability. You get the speed and you get the rigor.&lt;/p&gt;
&lt;p&gt;Building toward that combination is one of the more interesting engineering problems I have worked on. The knowledge base, the topic files, the wiring into the workflow — it is all aimed at the same thing: making security-first thinking something that happens automatically, not something that requires a specialist in the room.&lt;/p&gt;
&lt;p&gt;The specialist knowledge exists. We built it into 77KB of reference material drawn from 50 books. Now it is always in the room.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Part of the PAI series on building infrastructure that makes AI more useful, more reliable, and more trustworthy. The security knowledge base and topic files referenced in this post were built using Claude Code, PostgreSQL, pgvector, and source material from O&amp;rsquo;Reilly&amp;rsquo;s security catalog.&lt;/em&gt;&lt;/p&gt;
</content>
    </item>
    
  </channel>
</rss>
