<?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: Bishal Chapagain</title>
    <description>The latest articles on DEV Community by Bishal Chapagain (@bishal_cpgn).</description>
    <link>https://dev.to/bishal_cpgn</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1830409%2F2676cffb-7f9e-4f90-82dc-165984748578.jpg</url>
      <title>DEV Community: Bishal Chapagain</title>
      <link>https://dev.to/bishal_cpgn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bishal_cpgn"/>
    <language>en</language>
    <item>
      <title>Four supply chain attacks, and none of them was a bug in our code</title>
      <dc:creator>Bishal Chapagain</dc:creator>
      <pubDate>Fri, 31 Jul 2026 07:30:17 +0000</pubDate>
      <link>https://dev.to/aws-builders/four-supply-chain-attacks-and-none-of-them-was-a-bug-in-our-code-1d1h</link>
      <guid>https://dev.to/aws-builders/four-supply-chain-attacks-and-none-of-them-was-a-bug-in-our-code-1d1h</guid>
      <description>&lt;p&gt;We started the project last spring. New service, six weeks to ship, so we did what everyone does and reached for the ecosystem. By the time the first build went green the lockfile had 1,247 entries in it. We had chosen about thirty. The rest arrived as dependencies of dependencies, and I could not have named one of their maintainers if you had paid me.&lt;/p&gt;

&lt;p&gt;One of those maintainers got an email on a Friday evening.&lt;/p&gt;

&lt;p&gt;It offered free API credits for an AI coding tool with a countdown to hurry things along. The login page looked right. He typed in his registry password and a one time code, and within a few minutes a stranger held his publishing rights and had pushed a fresh patch release of every package he maintained. He went to bed, and nobody had noticed anything yet.&lt;/p&gt;

&lt;p&gt;Our CI did not know it was the weekend. We had that package floating on a version range instead of a pinned version, the nightly build resolved the range, and an install script executed inside the runner while it was holding every secret we had ever handed the pipeline. That meant cloud keys, the GitHub token, and our own publishing token, which the script used to push poisoned versions of our internal packages onward. By Monday three other teams had installed our compromise as a dependency of theirs.&lt;/p&gt;

&lt;p&gt;We spent that week rotating credentials and reading logs. Then we did the responsible thing and added a scanner to the pipeline. Well known tool, thousands of projects use it, referenced by version tag like every other workflow file in the company. It sat in front of every install and checked packages against known malicious releases. For four months it was the most reassuring line in our config.&lt;/p&gt;

&lt;p&gt;Then somebody rewrote history on that scanner's tags. The tag we referenced still existed, still looked identical in the commit list, and pointed somewhere new. A scanner needs elevated permissions to do its job, so ours read every secret in the runner and posted them somewhere useful, and it did that while returning a clean report. The control we installed to catch the last attack delivered the next one.&lt;/p&gt;

&lt;p&gt;I updated my CV.&lt;/p&gt;

&lt;p&gt;A recruiter reached out about a senior role. Good money, fully remote, two friendly calls. Before the technical round, the recruiter asked me to clone their repository and come back with recommendations on their API response times. I cloned it, ran npm install, spent an evening in the code and sent back something I was proud of. The stack was interesting and the problem was real, which is why it never occurred to me to be suspicious.&lt;/p&gt;

&lt;p&gt;Then I waited on the offer, and the AWS bill arrived instead.&lt;/p&gt;

&lt;p&gt;The repository was gone from GitHub by the time I went looking for it. There had been an install script in the package manifest, and it had taken my credentials while I was still reading the README, before I had formed a single opinion about their API. I never did hear back about the role.&lt;/p&gt;

&lt;h2&gt;
  
  
  What software supply chain security actually means
&lt;/h2&gt;

&lt;p&gt;Four separate attacks in that story, and none of them exploited a bug in code we wrote or required anybody on my team to make an obviously stupid decision.&lt;/p&gt;

&lt;p&gt;Your software supply chain is everything that has to happen between a person typing code and that code running in your production environment. NIST treats this under cybersecurity supply chain risk management in SP 800-161 Rev. 1, where the risk spans a full lifecycle from development through delivery, integration and operation rather than stopping at the edge of your own repository [1]. SLSA, the framework most teams reach for when they want something they can actually implement, splits the same ground into source threats, build threats and dependency threats, with its strongest guarantees covering the build [2].&lt;/p&gt;

&lt;p&gt;You add one package to &lt;code&gt;package.json&lt;/code&gt; and run &lt;code&gt;npm install&lt;/code&gt;. Three things had already happened in infrastructure you cannot see: a maintainer wrote the code and pushed a commit, a CI job on a platform you have never logged into built it, and that job used a token to publish a tarball to a registry. The rest happens on your side. Your package manager fetches the tarball, your lockfile records a version and a hash, your build copies it into a container image, and your deploy pushes that image into production. You reviewed none of that sequence, you inherited all of it, and each handoff is a place where what arrives can stop matching what was written.&lt;/p&gt;

&lt;p&gt;So the list of things you are trusting is always longer than your dependency list. It runs from the maintainer's inbox all the way through to the base image under your container and the laptop you cloned that repository onto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftjpjogdk2unjs7madtke.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftjpjogdk2unjs7madtke.png" alt="Software Supply Chain Attack" width="799" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every link in that chain runs code you have not read using permissions you granted earlier and stopped thinking about. Both paths end in the same place, because a laptop and a build runner are the same kind of target: a machine holding live credentials, doing what it was told. Neither NIST nor SLSA has much to say about the laptop, which was never part of anybody's build.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parts that actually happened
&lt;/h2&gt;

&lt;p&gt;The narrative above is a composite. Each beat in it is a real, documented incident.&lt;/p&gt;

&lt;h3&gt;
  
  
  The phishing email
&lt;/h3&gt;

&lt;p&gt;On September 8, 2025, the maintainer of &lt;code&gt;chalk&lt;/code&gt; and &lt;code&gt;debug&lt;/code&gt; received a fake two factor reset notice from &lt;code&gt;support@npmjs.help&lt;/code&gt;, a domain registered three days earlier [3]. The attacker captured a password and a live one time code, then published malicious versions of 18 packages carrying a browser based crypto stealer [4]. Those packages draw more than two billion downloads a week. The bad versions were live for roughly two hours, and Wiz still measured the malicious code reaching one in ten cloud environments inside that window [5].&lt;/p&gt;

&lt;p&gt;The lure in my version is free AI credits rather than a security notice, a detail that changes every few months while the mechanism stays the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  The worm in the pipeline
&lt;/h3&gt;

&lt;p&gt;Shai-Hulud, first seen in September 2025, does what the fictional install script did. It steals a publish token, enumerates every package that token can reach, injects itself and republishes [6]. The November 2025 wave compromised over 700 packages and exposed roughly 14,000 secrets across 487 organisations [7]. New waves continued through 2026 [8], and by May 2026 one of them needed no stolen credential at all: the attackers poisoned a CI cache through a pull request workflow misconfiguration and waited [9].&lt;/p&gt;

&lt;h3&gt;
  
  
  The scanner that carried the payload
&lt;/h3&gt;

&lt;p&gt;On March 19, 2026, a group calling itself TeamPCP force pushed 75 existing tags in &lt;code&gt;aquasecurity/trivy-action&lt;/code&gt; to malicious commits, preserving the original author names, messages and timestamps so the history looked untouched. One forensic tell was a commit claiming a 2021 date with a parent commit dated March 2026 [10]. More than 10,000 workflow files referenced that action [11]. The payload took everything the runner could see [12]. Aqua Security confirmed the attacker got in using credentials that were never fully rotated after an earlier incident [13], and within 96 hours those stolen CI credentials were used to compromise the Checkmarx AST action as well [14].&lt;/p&gt;

&lt;h3&gt;
  
  
  The interview that was not an interview
&lt;/h3&gt;

&lt;p&gt;Microsoft tracks this as Contagious Interview and dates it to at least December 2022 [15]. Each campaign uses a fake recruiter from a crypto or AI company, a plausible assessment repository, and a payload in the lifecycle scripts rather than in the code you were asked to review. Some variants now fire when you open the folder in VS Code, through the workspace task file [15]. In July 2026 Elastic documented a version that split its payload across SVG flag images, and no antivirus engine flagged the repositories [16]. Stolen cloud keys get monetised quickly: AWS has seen miners deployed within ten minutes of a credential compromise [17].&lt;/p&gt;

&lt;h3&gt;
  
  
  The people holding it all up
&lt;/h3&gt;

&lt;p&gt;Tidelift surveyed 437 maintainers in 2024. Sixty percent called themselves unpaid hobbyists, and 61% of that group maintain their projects alone [18]. Census II, from the Linux Foundation and Harvard, found that 136 developers wrote more than 80% of the lines added to 50 of the most used open source libraries [19]. The solo maintainer answering email on a Friday night is what the ecosystem actually looks like, not a device I invented for the story.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to break the attack chain
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Commit a lockfile and install with &lt;code&gt;npm ci&lt;/code&gt; in CI, so no build ever resolves a version range on its own.&lt;/li&gt;
&lt;li&gt;Add an install cooldown, so a version published an hour ago cannot reach your build. npm supports this through &lt;code&gt;minimumReleaseAge&lt;/code&gt;, pnpm 11 enables it by default, and Dependabot ships a default cooldown [20].&lt;/li&gt;
&lt;li&gt;Disable lifecycle scripts by default and keep a short allowlist for the packages that genuinely need them. Both the worm and the interview repository needed an install hook to run at all.&lt;/li&gt;
&lt;li&gt;Pin GitHub Actions to full commit SHAs instead of version tags. A tag can be force pushed to point at new code, which is not possible with a SHA [14].&lt;/li&gt;
&lt;li&gt;Scope secrets per job and retire standing cloud keys in favour of short lived OIDC credentials. That is the same reasoning behind npm revoking every classic token in December 2025 and capping write tokens at 90 days [21].&lt;/li&gt;
&lt;li&gt;Rotate everything after an incident, not the parts you can reach easily. The Trivy compromise ran on credentials left behind by a previous cleanup [13].&lt;/li&gt;
&lt;li&gt;Open anything a stranger sends you inside a throwaway VM that has nothing worth stealing on it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of that is advanced. Every attack in this story worked because code nobody had read ran with credentials nobody had scoped.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;NIST, &lt;a href="https://csrc.nist.gov/pubs/sp/800/161/r1/upd1/final" rel="noopener noreferrer"&gt;SP 800-161 Rev. 1, Cybersecurity Supply Chain Risk Management Practices for Systems and Organizations&lt;/a&gt;, updated November 2024.&lt;/li&gt;
&lt;li&gt;SLSA, &lt;a href="https://slsa.dev/spec/v1.0/threats" rel="noopener noreferrer"&gt;Supply chain threats&lt;/a&gt;, OpenSSF.&lt;/li&gt;
&lt;li&gt;Aikido Security, &lt;a href="https://www.aikido.dev/blog/npm-debug-and-chalk-packages-compromised" rel="noopener noreferrer"&gt;npm debug and chalk packages compromised&lt;/a&gt;, September 2025.&lt;/li&gt;
&lt;li&gt;Checkmarx, &lt;a href="https://checkmarx.com/zero-post/chalk-and-17-other-npm-packages-compromised-in-supply-chain-attack/" rel="noopener noreferrer"&gt;Chalk and 17 other npm packages compromised in supply chain attack&lt;/a&gt;, September 2025.&lt;/li&gt;
&lt;li&gt;Wiz, &lt;a href="https://www.wiz.io/blog/widespread-npm-supply-chain-attack-breaking-down-impact-scope-across-debug-chalk" rel="noopener noreferrer"&gt;Widespread npm supply chain attack: breaking down impact and scope&lt;/a&gt;, September 2025.&lt;/li&gt;
&lt;li&gt;ReversingLabs, &lt;a href="https://www.reversinglabs.com/blog/new-shai-hulud-worm-spreads-what-to-know" rel="noopener noreferrer"&gt;New Shai-Hulud worm spreads: what to know&lt;/a&gt;, November 2025.&lt;/li&gt;
&lt;li&gt;Zscaler ThreatLabz, &lt;a href="https://www.zscaler.com/blogs/security-research/shai-hulud-v2-poses-risk-npm-supply-chain" rel="noopener noreferrer"&gt;Shai-Hulud V2 poses risk to the npm supply chain&lt;/a&gt;, November 2025.&lt;/li&gt;
&lt;li&gt;Unit 42, &lt;a href="https://unit42.paloaltonetworks.com/monitoring-npm-supply-chain-attacks/" rel="noopener noreferrer"&gt;The npm threat landscape: attack surface and mitigations&lt;/a&gt;, updated July 2026.&lt;/li&gt;
&lt;li&gt;Akamai, &lt;a href="https://www.akamai.com/blog/security-research/mini-shai-hulud-worm-returns-goes-public" rel="noopener noreferrer"&gt;Mini Shai-Hulud: the worm returns and goes public&lt;/a&gt;, May 2026.&lt;/li&gt;
&lt;li&gt;Upwind, &lt;a href="https://www.upwind.io/feed/trivy-supply-chain-incident-github-actions-compromise-breakdown" rel="noopener noreferrer"&gt;Trivy supply chain incident: GitHub Actions compromise breakdown&lt;/a&gt;, March 2026.&lt;/li&gt;
&lt;li&gt;Cloud Security Alliance Labs, &lt;a href="https://labs.cloudsecurityalliance.org/research/csa-research-note-teampcp-supply-chain-ci-cd-20260324-csa-st/" rel="noopener noreferrer"&gt;TeamPCP supply chain CI/CD research note&lt;/a&gt;, March 2026.&lt;/li&gt;
&lt;li&gt;Wiz, &lt;a href="https://www.wiz.io/blog/trivy-compromised-teampcp-supply-chain-attack" rel="noopener noreferrer"&gt;Trivy compromised by TeamPCP&lt;/a&gt;, March 2026.&lt;/li&gt;
&lt;li&gt;Legit Security, &lt;a href="https://www.legitsecurity.com/blog/the-trivy-supply-chain-compromise-what-happened-and-playbooks-to-respond" rel="noopener noreferrer"&gt;The Trivy supply chain compromise: what happened and playbooks to respond&lt;/a&gt;, March 2026.&lt;/li&gt;
&lt;li&gt;Sysdig, &lt;a href="https://www.sysdig.com/blog/teampcp-expands-supply-chain-compromise-spreads-from-trivy-to-checkmarx-github-actions" rel="noopener noreferrer"&gt;TeamPCP expands: supply chain compromise spreads from Trivy to Checkmarx GitHub Actions&lt;/a&gt;, March 2026.&lt;/li&gt;
&lt;li&gt;Microsoft Security, &lt;a href="https://www.microsoft.com/en-us/security/blog/2026/03/11/contagious-interview-malware-delivered-through-fake-developer-job-interviews/" rel="noopener noreferrer"&gt;Contagious Interview: malware delivered through fake developer job interviews&lt;/a&gt;, March 2026.&lt;/li&gt;
&lt;li&gt;Elastic Security Labs, &lt;a href="https://www.elastic.co/security-labs/contagious-interview-malware-svg-steganography" rel="noopener noreferrer"&gt;Contagious Interview malware in SVG images&lt;/a&gt;, July 2026.&lt;/li&gt;
&lt;li&gt;Dark Reading, &lt;a href="https://www.darkreading.com/cloud-security/attackers-use-stolen-aws-credentials-cryptomining" rel="noopener noreferrer"&gt;Attackers use stolen AWS credentials in cryptomining campaign&lt;/a&gt;, December 2025.&lt;/li&gt;
&lt;li&gt;Socket, &lt;a href="https://socket.dev/blog/the-unpaid-backbone-of-open-source" rel="noopener noreferrer"&gt;The unpaid backbone of open source&lt;/a&gt;, on the 2024 Tidelift maintainer survey.&lt;/li&gt;
&lt;li&gt;Linux Foundation, &lt;a href="https://www.linuxfoundation.org/blog/open-source-maintainers-what-they-need-and-how-to-support-them" rel="noopener noreferrer"&gt;Open source maintainers: what they need and how to support them&lt;/a&gt;, on Census II.&lt;/li&gt;
&lt;li&gt;Socket, &lt;a href="https://socket.dev/blog/npm-introduces-minimumreleaseage-and-bulk-oidc-configuration" rel="noopener noreferrer"&gt;npm introduces minimumReleaseAge and bulk OIDC configuration&lt;/a&gt;, February 2026.&lt;/li&gt;
&lt;li&gt;GitHub Changelog, &lt;a href="https://github.blog/changelog/2025-12-09-npm-classic-tokens-revoked-session-based-auth-and-cli-token-management-now-available/" rel="noopener noreferrer"&gt;npm classic tokens revoked, session based auth and CLI token management&lt;/a&gt;, December 2025.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>security</category>
      <category>softwaresupplychain</category>
      <category>software</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>A Practical Guide to Claude Code's Security-Guidance Plugin</title>
      <dc:creator>Bishal Chapagain</dc:creator>
      <pubDate>Wed, 29 Jul 2026 17:27:30 +0000</pubDate>
      <link>https://dev.to/bishal_cpgn/a-practical-guide-to-claude-codes-security-guidance-plugin-33d8</link>
      <guid>https://dev.to/bishal_cpgn/a-practical-guide-to-claude-codes-security-guidance-plugin-33d8</guid>
      <description>&lt;p&gt;Development velocity has moved faster than the machinery built to review it. An engineer working with a coding agent can touch a dozen files, refactor across them, and commit inside an afternoon. The gates around that work mostly stayed where they were: static analysis in CI, dependency scanners on a schedule, and a human reading the diff once it reaches a pull request. Those gates assume that writing code is the slow step.&lt;/p&gt;

&lt;p&gt;That assumption no longer holds, and the cost shows up as delay. A vulnerable query gets written, committed, and pushed before anything examines it, and the tool that eventually flags it is describing work the author finished hours earlier and has stopped thinking about. The gates are not wrong. There are simply more diffs arriving than they were built to absorb, and the later a finding lands, the more expensive it is to act on.&lt;/p&gt;

&lt;p&gt;Anthropic’s &lt;code&gt;security-guidance&lt;/code&gt; plugin moves the first check into the session itself. Claude writes code, the plugin reviews the change, and findings come back to Claude in the same conversation. There is nothing to invoke and no command to remember.&lt;/p&gt;

&lt;p&gt;I spent an evening setting it up in a small repository and then trying to get each of its three layers to fire on code written to trip them. This is what that took, and how to tell that each layer is actually running rather than merely installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the plugin&amp;nbsp;does
&lt;/h3&gt;

&lt;p&gt;The plugin is built from Claude Code lifecycle hooks. It registers &lt;code&gt;SessionStart&lt;/code&gt; to bootstrap a Python environment, &lt;code&gt;UserPromptSubmit&lt;/code&gt; to capture a git baseline for the turn, &lt;code&gt;PostToolUse&lt;/code&gt; on the edit tools for the pattern check, &lt;code&gt;Stop&lt;/code&gt; for the end-of-turn review, and &lt;code&gt;PostToolUse&lt;/code&gt; on Bash filtered to &lt;code&gt;git commit&lt;/code&gt; and &lt;code&gt;git push&lt;/code&gt; for the deep review. If those event names are new to you, the hooks reference describes what each one fires on.&lt;/p&gt;

&lt;p&gt;Those registrations give you three layers at increasing depth and cost.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3rt7gh60hyj4l076tkkx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3rt7gh60hyj4l076tkkx.png" alt="Cheap checks run constantly. Expensive checks run&amp;nbsp;rarely." width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Layer 1 is a string and regex match with no model call, so it is free and instant. It covers dynamic execution such as &lt;code&gt;eval(&lt;/code&gt; and &lt;code&gt;os.system&lt;/code&gt;, unsafe deserialization such as &lt;code&gt;pickle&lt;/code&gt;, DOM injection such as&amp;nbsp;&lt;code&gt;.innerHTML =&lt;/code&gt; and &lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt;, and edits under&amp;nbsp;&lt;code&gt;.github/workflows/&lt;/code&gt;, which can quietly grant repository permissions. Those are the built-ins you get before writing anything. Your own rules from &lt;code&gt;security-patterns.json&lt;/code&gt; run in this same pass, covered further down.&lt;/p&gt;

&lt;p&gt;Layer 2 diffs the working tree at the end of a turn and sends the result to a separate Claude call with a security-only prompt. It covers what a string match cannot: injection, server-side request forgery, weak cryptography, authorization bypass. It runs in the background, so Claude’s reply is not delayed, and it covers up to 30 changed files per turn.&lt;/p&gt;

&lt;p&gt;Layer 3 fires when Claude runs &lt;code&gt;git commit&lt;/code&gt; or &lt;code&gt;git push&lt;/code&gt; through its Bash tool. This reviewer reads surrounding code, including callers and sanitizers, before deciding whether a finding is real. It is capped at 20 reviews per rolling hour.&lt;/p&gt;

&lt;p&gt;One point is worth saying to your team early, because it is the first thing they will assume wrongly. None of these layers stops anything. They find problems and hand them to Claude, which fixes them in the conversation. Nothing gets blocked. If you want a hard stop, you build it yourself with a &lt;code&gt;PreToolUse&lt;/code&gt; hook or a check in CI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code 2.1.144 or later (Scroll to the end if you’re on OpenRouter)&lt;/li&gt;
&lt;li&gt;Python 3.10 or later, and a git repository&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A repository worth attacking
&lt;/h3&gt;

&lt;p&gt;None of the checks below mean anything against an empty directory, so the first thing I built was a small Python service with a few files: a data layer&amp;nbsp;, a couple of route stubs, and a front-end file so the JavaScript patterns had somewhere to land. The baseline is deliberately clean, which makes the contrast visible when Claude adds something unsafe on request.&lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;git init&lt;/code&gt; and a first commit. Layer 2 diffs the working tree and Layer 3 only fires on &lt;code&gt;git commit&lt;/code&gt; or &lt;code&gt;git push&lt;/code&gt;, so without a repository two of the three checks quietly do nothing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing security-guidance plugin
&lt;/h3&gt;

&lt;p&gt;1.Run this inside a Claude Code session to install the official plugin from the Anthropic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin &lt;span class="nb"&gt;install &lt;/span&gt;security-guidance@claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.The installer asks for a scope. Choose “Install for all collaborators on this repository”, which writes&amp;nbsp;&lt;code&gt;.claude/settings.json&lt;/code&gt; for you with the plugin enabled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxdp1uaq51b07mfgians0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxdp1uaq51b07mfgians0.png" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.Then apply it to the open session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/reload-plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg15yo4tkj5h0e1hoieep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg15yo4tkj5h0e1hoieep.png" width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Confirm the file &lt;code&gt;settings.json&lt;/code&gt; landed under the&amp;nbsp;&lt;code&gt;.claude&lt;/code&gt; folder in your project root.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: If the marketplace is not registered on the machine, add it first with &lt;code&gt;/plugin marketplace add anthropics/claude-plugins-official&lt;/code&gt; and retry.&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  What ends up in the repository
&lt;/h3&gt;

&lt;p&gt;The installer writes one of the three files. You write the other two, because the plugin has no opinion about your codebase and never generates them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu75xucyjllm656ccz1hr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu75xucyjllm656ccz1hr.png" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full working example, including the demo repository these snippets come from, is on &lt;code&gt;[&lt;/code&gt;&lt;a href="https://github.com/bishalcpgn/claude-security-guidance-plugin" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;code&gt;]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;They are configuration, they belong next to the code they protect, and versioning them means a rule change shows up in review like any other change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm2irime04sklu2fok17j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm2irime04sklu2fok17j.png" width="800" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Your threat model, in plain&amp;nbsp;English
&lt;/h3&gt;

&lt;p&gt;The two model-backed reviews load&amp;nbsp;&lt;code&gt;.claude/claude-security-guidance.md&lt;/code&gt; as extra context alongside the built-in vulnerability checklist. There is no DSL. Write the rules the way you would explain them to a new hire.&lt;/p&gt;

&lt;p&gt;This is the file that carries knowledge a generic scanner cannot have. Nothing about &lt;code&gt;org_id&lt;/code&gt; is universal. It is your schema, and the reviewer only knows about it because you wrote it down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom patterns for the free&amp;nbsp;layer
&lt;/h3&gt;

&lt;p&gt;Anthropic’s security plugin includes built-in detection patterns in &lt;code&gt;patterns.py&lt;/code&gt;. You can locate the file with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find ~/.claude/plugins &lt;span class="nt"&gt;-path&lt;/span&gt; &lt;span class="s1"&gt;'*security-guidance/hooks/patterns.py'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can add your own custom patterns in&amp;nbsp;&lt;code&gt;.claude/security-patterns.json&lt;/code&gt;. These feed the free Layer 1 checks, so they run instantly with no additional model cost.&lt;/p&gt;

&lt;p&gt;The plugin also supports&amp;nbsp;&lt;code&gt;.yaml&lt;/code&gt;,&amp;nbsp;&lt;code&gt;.yml&lt;/code&gt; and&amp;nbsp;&lt;code&gt;.json&lt;/code&gt; using the same schema. YAML requires &lt;code&gt;PyYAML&lt;/code&gt; to be installed separately, while JSON works on any standard Python installation.&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  What each layer can&amp;nbsp;see
&lt;/h3&gt;

&lt;p&gt;The layering is worth understanding before you decide how much of it to pay for.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Sees&lt;/th&gt;
&lt;th&gt;Strength&lt;/th&gt;
&lt;th&gt;Limitation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Layer 1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single edit only&lt;/td&gt;
&lt;td&gt;Free, instant pattern matching&lt;/td&gt;
&lt;td&gt;No project context or data flow awareness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Layer 2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;All changes in the current turn&lt;/td&gt;
&lt;td&gt;Tracks data flow across the diff&lt;/td&gt;
&lt;td&gt;Limited to current-turn changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Layer 3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Diff plus related files&lt;/td&gt;
&lt;td&gt;Uses project context to reduce false positives&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Proving each layer&amp;nbsp;fires
&lt;/h3&gt;

&lt;p&gt;Installing the plugin and reading the docs tells you what should happen. It does not tell you what is happening on your machine.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Start a fresh session from the repo root and run &lt;code&gt;/hooks&lt;/code&gt;, which should show registrations against &lt;code&gt;SessionStart&lt;/code&gt;, &lt;code&gt;UserPromptSubmit&lt;/code&gt;, &lt;code&gt;PostToolUse&lt;/code&gt;, and &lt;code&gt;Stop&lt;/code&gt;. That screen makes a good opening slide for a team walkthrough, because it shows there is nothing hidden in the design.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm62201sfw6cofuostxrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm62201sfw6cofuostxrk.png" width="799" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then make each layer fire on purpose. The plugin keeps its own log at &lt;code&gt;~/.claude/security/log.txt&lt;/code&gt;, and that is the thing to read rather than the session transcript. Claude sometimes adds its own security comments to code unprompted, which is easy to mistake for the plugin having spoken.&lt;/p&gt;

&lt;p&gt;Keep a second terminal open on the log before prompting claude-code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.claude/security/log.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Check 1: the built-in pattern&amp;nbsp;layer
&lt;/h2&gt;

&lt;p&gt;Ask for something the built-in list covers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In app/routes.py, add a function run_report(expr) that evaluates the expr string the caller passes in and returns the result. Keep it to three lines.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fix7e8dg7ys67tipkpyfu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fix7e8dg7ys67tipkpyfu.png" width="799" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude writes &lt;code&gt;eval(expr)&lt;/code&gt;. The warning appears in the transcript with no perceptible delay. Next, screen shows the hook event and pattern matched. &amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkbf7uaf2vke6ppj65l8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkbf7uaf2vke6ppj65l8r.png" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Check 2: your own pattern&amp;nbsp;rule
&lt;/h3&gt;

&lt;p&gt;Same free layer, your vocabulary. This one exercises the &lt;code&gt;paths&lt;/code&gt; glob, which is the part most likely to be silently wrong.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In app/db.py add a function list_invoices() that returns Invoice.objects.all().&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The warning text should be the &lt;code&gt;reminder&lt;/code&gt; string you wrote, not a generic one.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8boaqciv7q0yg7fv1nno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8boaqciv7q0yg7fv1nno.png" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: A rule that never appears here, with no error anywhere, is almost always a &lt;code&gt;paths&lt;/code&gt; glob missing its &lt;code&gt;**/&lt;/code&gt; prefix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check 3: the end-of-turn model&amp;nbsp;review
&lt;/h3&gt;

&lt;p&gt;Now ask for something no string match will catch cleanly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Add a function search_users(term) to app/db.py that runs a LIKE query against the users table. Build the SQL as an f-string so it is easy to read.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude replies without delay. A few seconds later the review returns in the background. Claude is re-prompted with the finding. If it acknowledges the finding but leaves the code as it is, prompt “apply the security review’s recommendation” and it will rewrite the query with parameter binding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhdly3k1dmm1yr7mzs5fq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhdly3k1dmm1yr7mzs5fq.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Check 4: the commit&amp;nbsp;review
&lt;/h3&gt;

&lt;p&gt;Let Claude make the commit itself, since this layer only sees commits that go through its Bash tool.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Commit everything we just changed with a sensible message.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The commit completes, then the deeper review runs in the background and reports separately after a few minutes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpjk0av6fmka7s1xi1dh6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpjk0av6fmka7s1xi1dh6.png" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This reviewer reads related files before deciding, so it takes longer than Layer 2 and may run several model turns. If its findings duplicate what the end-of-turn review already reported, Claude is not re-prompted, so a clean commit can produce no visible output at all. That silence is documented behaviour rather than a failure.&lt;/p&gt;

&lt;p&gt;Worth noticing while this is on screen: the commit already exists by the time the finding arrives. Any fix becomes a second commit. “Review on commit” sounds like a gate and is not one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limits worth stating up&amp;nbsp;front
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Manual commits, shell escapes, or commits made outside Claude are not reviewed. A CI security check is still recommended.&lt;/li&gt;
&lt;li&gt;Findings are suggestions, not guarantees. The model can miss vulnerabilities, generate false positives and its results may vary across codebases, languages and model versions.&lt;/li&gt;
&lt;li&gt;This plugin complements, but does not replace, static analysis, dependency scanning, pull request reviews, or human review.&lt;/li&gt;
&lt;li&gt;The plugin is an early security gate. Anthropic also provides deeper repository scanning with its multi-agent scanner and pull request reviews through Code Review for Team and Enterprise plans. Each stage helps catch issues missed by the previous one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it does well is cheap: it puts your team’s actual rules in front of the model at the moment code is written, in a file any engineer can edit in five minutes, versioned in the repository like everything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workaround for OpenRouter
&lt;/h3&gt;

&lt;p&gt;Skip this if you are not on OpenRouter.&lt;/p&gt;

&lt;p&gt;I was running Claude Code through OpenRouter instead of a first-party&lt;br&gt;&lt;br&gt;
Anthropic account. Sessions worked fine but the plugin did not, because both model-backed reviews default to Claude Opus 4.7 and my OpenRouter key had roughly the spending power of a library card. It asked for Opus. It got a polite note about credits.&lt;/p&gt;

&lt;p&gt;The fix is environment variables that redirect the reviews to a model the key actually serves. Here is the relevant part of my&amp;nbsp;&lt;code&gt;.bashrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-key"&lt;/span&gt;  
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://openrouter.ai/api"&lt;/span&gt;  
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;  

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_DEFAULT_SONNET_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"openrouter/free"&lt;/span&gt;  
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_DEFAULT_HAIKU_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"openrouter/free"&lt;/span&gt;  
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_DEFAULT_OPUS_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"openrouter/free"&lt;/span&gt;  
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CODE_SUBAGENT_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"openrouter/free"&lt;/span&gt;   

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SECURITY_REVIEW_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"openrouter/free"&lt;/span&gt;  
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SG_AGENTIC_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"openrouter/free"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;SECURITY_REVIEW_MODEL&lt;/code&gt; covers the end-of-turn review and &lt;code&gt;SG_AGENTIC_MODEL&lt;/code&gt; covers the commit review. The plugin reads them independently of the session model, which is the point: you can run a cheap model for coding and a stronger one for review, or the reverse if you are watching spend.&lt;/p&gt;

&lt;p&gt;Hooks run as subprocesses of Claude Code, so they inherit the environment of the shell that started &lt;code&gt;claude&lt;/code&gt;. Putting these in&amp;nbsp;&lt;code&gt;.bashrc&lt;/code&gt; rather than typing them in a second terminal is the reliable way to make sure the reviews see them.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;Anthropic. “Catch security issues as Claude writes code.” Claude Code documentation. &lt;a href="https://code.claude.com/docs/en/security-guidance" rel="noopener noreferrer"&gt;https://code.claude.com/docs/en/security-guidance&lt;/a&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Anthropic. “Hooks reference.” Claude Code documentation. &lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;https://code.claude.com/docs/en/hooks&lt;/a&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Anthropic. “Automate actions with hooks.” Claude Code documentation. &lt;a href="https://code.claude.com/docs/en/hooks-guide" rel="noopener noreferrer"&gt;https://code.claude.com/docs/en/hooks-guide&lt;/a&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Anthropic. “Settings.” Claude Code documentation. &lt;a href="https://code.claude.com/docs/en/settings" rel="noopener noreferrer"&gt;https://code.claude.com/docs/en/settings&lt;/a&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Anthropic. “security-guidance plugin.” claude-plugins-official repository, GitHub. &lt;a href="https://github.com/anthropics/claude-plugins-official/tree/main/plugins/security-guidance" rel="noopener noreferrer"&gt;https://github.com/anthropics/claude-plugins-official/tree/main/plugins/security-guidance&lt;/a&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Anthropic. “Code Review.” Claude Code documentation. &lt;a href="https://code.claude.com/docs/en/code-review" rel="noopener noreferrer"&gt;https://code.claude.com/docs/en/code-review&lt;/a&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Anthropic. “Claude Security plugin.” Claude Code documentation. &lt;a href="https://code.claude.com/docs/en/claude-security" rel="noopener noreferrer"&gt;https://code.claude.com/docs/en/claude-security&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>claude</category>
      <category>security</category>
    </item>
    <item>
      <title>ENABLE EBS ENCRYPTION BY DEFAULT IN 30 SECONDS</title>
      <dc:creator>Bishal Chapagain</dc:creator>
      <pubDate>Fri, 21 Nov 2025 08:09:01 +0000</pubDate>
      <link>https://dev.to/aws-builders/enable-ebs-encryption-by-default-in-30-seconds-2125</link>
      <guid>https://dev.to/aws-builders/enable-ebs-encryption-by-default-in-30-seconds-2125</guid>
      <description>&lt;h3&gt;
  
  
  The One Security Setting Every AWS Account Needs
&lt;/h3&gt;

&lt;p&gt;We have all been there. You are in a rush to launch an EC2 instance. You click through the configuration screens, hit "Launch," and then realize... you forgot to tick the "Encrypt" box for the storage volume.&lt;/p&gt;

&lt;p&gt;In the world of cloud security, human error is the biggest risk. But what if you could "future-proof" your account so that you never have to remember to click that button again?&lt;/p&gt;

&lt;p&gt;There is a setting in AWS that takes literally 30 seconds to turn on, costs nothing extra to enable, and ensures that every single new hard drive (EBS volume) you create is encrypted automatically. Here is how to turn it on, why it matters, and the few things you need to know.&lt;br&gt;
Why should you care?&lt;/p&gt;

&lt;p&gt;Think of EBS Encryption by Default as automatically locking your front door every time you close it.&lt;/p&gt;

&lt;p&gt;Peace of Mind: You don’t need to rely on your team remembering to encrypt data. AWS enforces it for you.&lt;/p&gt;

&lt;p&gt;Compliance: If you are handling sensitive data (GDPR, HIPAA, etc.), encryption at rest is usually mandatory.&lt;/p&gt;
&lt;h3&gt;
  
  
  How to Enable it (The 30-Second Guide)
&lt;/h3&gt;

&lt;p&gt;If you are familiar with AWS CLI, use the following command and it's done.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws ec2 get-ebs-encryption-by-default --region &amp;lt;region&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Else, you don’t need to be a coding wizard to do this. Just follow these steps in the AWS Console.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Pick your Region&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Log into your AWS Console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select your region from the top right corner.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Crucial: This setting is Region-Specific. If you work in both us-east-1 (N. Virginia) and ap-south-1 (Mumbai), you need to do this in both places.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Navigate to the EC2 service.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Find the Settings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Look at the navigation pane on the left side. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll all the way down to the bottom and click on Settings &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8kwx91zkpzb0wxrhw73o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8kwx91zkpzb0wxrhw73o.png" alt="AWS EC2 Settings" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the Data Protection and Security tab.&lt;/li&gt;
&lt;li&gt;You will see a section called EBS Encryption.&lt;/li&gt;
&lt;li&gt;Click Manage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qfk1ocw2nweu8hg7vr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qfk1ocw2nweu8hg7vr7.png" alt="EBS Encryption By Default" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the Enable box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnei21h2ozbiqezpcr8sq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnei21h2ozbiqezpcr8sq.png" alt="EBS Encryption By Default" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Key Selection: You can leave it as the default (aws/ebs)  or pick a Customer Managed Key (CMK) if you plan to share snapshots later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Note: While the default key is free, AWS charges approx. $1/month to maintain a Customer Managed Key.&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click Update EBS encryption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Done. That’s it. You are now secure by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Things to Consider Before You Switch It On
&lt;/h3&gt;

&lt;p&gt;While this setting is fantastic for security, there are a few details you should know so you aren't surprised later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. It doesn’t fix the past&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Turning this on acts like a fresh start. It encrypts every new volume you create from this moment forward. However, for your old volumes, you can’t simply turn on encryption for drives that already exist. You have to create a snapshot and copy it to a new drive to secure them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. It is Region-Specific&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AWS settings often apply to just one specific location (Region). If you enable this in N. Virginia, it does not automatically turn on in Mumbai or Sydney. You need to repeat this process for every Region where you have servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Be careful with "Key Selection"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Default Key: It is totally free and auto rotated every year but you cannot share snapshots encrypted with this key to other AWS accounts.&lt;/p&gt;

&lt;p&gt;Customer Managed Key (CMK): If you plan to share disk images with a client or a different production account later, you must create and use your own Customer Managed Key. AWS charges for using CMK and you are responsible for rotating it.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. It is "All or Nothing"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you enable this for a Region, it applies to everything you create in that Region. You cannot disable encryption for just one specific volume later. This is actually a good thing; it prevents accidental loopholes in your security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. A note on storage costs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you decide to clean up your old data by copying unencrypted snapshots to make them encrypted, be aware that AWS creates a full copy, not a partial one. This means you will be storing more data, which might result in a small increase in your storage bill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Security doesn't always have to be hard. By enabling EBS Encryption by Default, you are removing the chance of human error and ensuring that your data remains locked tight, no matter who launches the instance.&lt;/p&gt;

&lt;p&gt;Go do it now,it will take less time than finishing your coffee!&lt;/p&gt;

&lt;p&gt;For more technical details or CLI commands, you can check the official &lt;a href="https://docs.aws.amazon.com/ebs/latest/userguide/encryption-by-default.html" rel="noopener noreferrer"&gt;AWS Documentation&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>AWS Support: "We're here to help"</title>
      <dc:creator>Bishal Chapagain</dc:creator>
      <pubDate>Sat, 19 Jul 2025 04:46:47 +0000</pubDate>
      <link>https://dev.to/bishal_cpgn/aws-support-were-here-to-help-2dhp</link>
      <guid>https://dev.to/bishal_cpgn/aws-support-were-here-to-help-2dhp</guid>
      <description>&lt;p&gt;They said they’re “here to help.”&lt;/p&gt;

&lt;p&gt;They meant help me cry more. &lt;/p&gt;

</description>
      <category>aws</category>
      <category>humor</category>
      <category>awssupport</category>
      <category>troubleshoot</category>
    </item>
    <item>
      <title>From Container to Root</title>
      <dc:creator>Bishal Chapagain</dc:creator>
      <pubDate>Fri, 25 Apr 2025 17:18:04 +0000</pubDate>
      <link>https://dev.to/bishal_cpgn/privilege-escalation-using-docker-container-4h7</link>
      <guid>https://dev.to/bishal_cpgn/privilege-escalation-using-docker-container-4h7</guid>
      <description>&lt;h4&gt;
  
  
  Background&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;In many companies, employees are often provided with limited user privileges. These accounts often lack &lt;code&gt;sudo&lt;/code&gt; or &lt;code&gt;root&lt;/code&gt; privileges, preventing direct access to install packages or make system-wide changes. But what if you could break through these restrictions with a Docker container?&amp;nbsp;&lt;/p&gt;

&lt;p&gt;In this article, I’ll show you how I got root access onto the host all from within a container.&lt;/p&gt;

&lt;h4&gt;
  
  
  About Docker
&lt;/h4&gt;

&lt;p&gt;Docker makes extensive use of &lt;em&gt;cgroups&lt;/em&gt; and &lt;em&gt;namespaces&lt;/em&gt; to provide containerization. These are core Linux kernel features that enable Docker to isolate and manage resources for containers effectively. Even with &lt;code&gt;root&lt;/code&gt; inside a container, you can't affect the host system unless you explicitly allow it. Docker containers are isolated environments that share the host kernel but are otherwise sandboxed.&lt;/p&gt;

&lt;p&gt;By running containers in &lt;code&gt;--privileged&lt;/code&gt; mode and mounting the host filesystem, we effectively give the container god-mode access to the host. This is what we exploit in this method.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;This method is tested on &lt;em&gt;Ubuntu 24.04.2 LTS&lt;/em&gt; with &lt;em&gt;Docker&lt;/em&gt; installed on it.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  Disclaimer:&amp;nbsp;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This method is dangerous as it breaks the isolation model of Docker.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One wrong move and you can corrupt your host system.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Steps
&lt;/h3&gt;

&lt;p&gt;1. Run a Docker Container&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, run a privileged Ubuntu container with the host root directory mounted on it.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fea628a14ocea2cnq85df.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fea628a14ocea2cnq85df.png" alt="docker-container-with-host-root-volume" width="800" height="108"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -it --rm --privileged -v /:/mnt/host ubuntu:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Once inside the container, you can check the contents of the host root directory.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwadvdirmklwq88d90npe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwadvdirmklwq88d90npe.png" alt="check-contents-of-directory-ls" width="800" height="157"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls /mnt/host
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;nbsp;2. &lt;code&gt;chroot&lt;/code&gt; into the host system&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The chroot command changes the apparent root directory for the current process and its children.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The directory &lt;code&gt;/mnt/host&lt;/code&gt; becomes the new root for the processes. Thus, host files and directories can be accessed with an isolated bash shell.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chroot /mnt/host /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3t7hqtnia4w1zy296wmo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3t7hqtnia4w1zy296wmo.png" alt="chroot" width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we’re in the host environment and can install packages or make other modifications as if we were logged in directly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it fails, check for missing binaries or libraries using strace.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;strace -f chroot /mnt/host /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. Install packages&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For this demo, let’s install python3.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3mjf2wxuy7yuzgjllue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3mjf2wxuy7yuzgjllue.png" alt="install-pyhton3-in-ubuntu" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4. Test it from your end&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We can see a running Ubuntu container using &lt;code&gt;docker ps&lt;/code&gt; command in the new terminal.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On testing, python3 has been successfully installed on our system.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitiqv1vp4wfs95k8ck2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitiqv1vp4wfs95k8ck2n.png" alt="check-python-version" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5. Fixing DNS Issues&lt;/p&gt;

&lt;p&gt;If you face any DNS issues inside the container, you can resolve this by manually setting the DNS.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "nameserver 8.8.8.8" &amp;gt; /etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to prevent&amp;nbsp;it?&amp;nbsp;
&lt;/h3&gt;

&lt;p&gt;When an employee gains unauthorized root access to a company's end device, the impacts can be severe, affecting security, operations and compliance.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;The following ways can be considered for prevention&amp;nbsp;:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use Rootless mode&lt;br&gt;&lt;br&gt;
This is the safest way to run containers without risking the host system’s security as both Docker daemon and containers runs in rootless mode.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leverage SELinux/AppArmor&lt;br&gt;&lt;br&gt;
Mandatory Access Control via SELinux or AppArmor prevents containers from accessing host paths, even if privileged.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;This method granted me the freedom to act as root on a machine where I didn’t have direct access. However, never test this on critical systems.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>cybersecurity</category>
      <category>linux</category>
      <category>containers</category>
    </item>
  </channel>
</rss>
