<?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: Yaa Kesewaa Yeboah </title>
    <description>The latest articles on DEV Community by Yaa Kesewaa Yeboah  (@yaak).</description>
    <link>https://dev.to/yaak</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%2F3783204%2Fc0b90de3-08db-4f06-90fc-92a90c362f2c.png</url>
      <title>DEV Community: Yaa Kesewaa Yeboah </title>
      <link>https://dev.to/yaak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yaak"/>
    <language>en</language>
    <item>
      <title>10 Linux Security Incidents, Reproduced and Fixed</title>
      <dc:creator>Yaa Kesewaa Yeboah </dc:creator>
      <pubDate>Sun, 01 Mar 2026 21:31:44 +0000</pubDate>
      <link>https://dev.to/yaak/10-linux-security-incidents-reproduced-and-fixed-b9h</link>
      <guid>https://dev.to/yaak/10-linux-security-incidents-reproduced-and-fixed-b9h</guid>
      <description>&lt;p&gt;There's a difference between reading about Linux security and actually breaking things on purpose. This assignment made me do the latter; 10 real-world incidents, reproduced and fixed one by one.&lt;/p&gt;

&lt;p&gt;I'll keep this post high-level. If you want the full commands, screenshots, and detailed documentation, it's all on my GitHub: &lt;a href="https://github.com/Yaa-K/devsecops-linux-assignment-2.git" rel="noopener noreferrer"&gt;github.com/Yaa-K/devsecops-linux-assignment&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 1 — Shared Document Deletion Incident
&lt;/h2&gt;

&lt;p&gt;An intern deleted a shared design document. I reproduced it by creating three users, a shared group, and a group-writable directory. As expected, any group member could delete any file inside — regardless of who created it.&lt;/p&gt;

&lt;p&gt;The fix was &lt;code&gt;chattr +i&lt;/code&gt;, which makes a file immutable at the filesystem level. Even root cannot delete it without explicitly removing the attribute first. This is the key difference between &lt;code&gt;chmod&lt;/code&gt; and &lt;code&gt;chattr&lt;/code&gt; — one enforces permissions, the other enforces filesystem-level constraints that sit below permissions entirely.&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.amazonaws.com%2Fuploads%2Farticles%2F26swju18al0lrszne1ch.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%2F26swju18al0lrszne1ch.png" alt="Deletion blocked by chattr +i" width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 2 — Log Overwrite Incident
&lt;/h2&gt;

&lt;p&gt;One accidental &lt;code&gt;&amp;gt;&lt;/code&gt; instead of &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; destroyed over 100 lines of application logs instantly.&lt;/p&gt;

&lt;p&gt;I restored the logs, backed them up using &lt;code&gt;cp -p&lt;/code&gt; to preserve timestamps, and applied &lt;code&gt;chattr +a&lt;/code&gt; (append-only) so no user — regardless of permissions — could overwrite the file again.&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.amazonaws.com%2Fuploads%2Farticles%2Fgdntm78t977t7a1t10mi.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%2Fgdntm78t977t7a1t10mi.png" alt="Append OK, overwrite blocked" width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cp -p&lt;/code&gt; matters here because timestamps are forensic evidence. Without them, a backup file loses its evidentiary value — you can no longer tell when events actually occurred.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 3 — Permission &amp;amp; Ownership Drift
&lt;/h2&gt;

&lt;p&gt;Copying files without the &lt;code&gt;-p&lt;/code&gt; flag silently resets ownership and timestamps. A file that was &lt;code&gt;dev_user:project_team 600&lt;/code&gt; becomes your user's file after a plain &lt;code&gt;cp&lt;/code&gt;. In production that kind of drift can expose secrets without anyone noticing.&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.amazonaws.com%2Fuploads%2Farticles%2Fbdbpx4ew9icec6gt4op2.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%2Fbdbpx4ew9icec6gt4op2.png" alt="Ownership drift vs preserved" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fix: always use &lt;code&gt;cp -p&lt;/code&gt; for anything going to production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 4 — Relative Path Deployment Failure
&lt;/h2&gt;

&lt;p&gt;A deployment script used a relative path. It worked perfectly from the project directory and broke immediately when called from anywhere else — which is exactly what CI/CD systems do.&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.amazonaws.com%2Fuploads%2Farticles%2Ff4nrjyokih7mvvqx3h2t.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%2Ff4nrjyokih7mvvqx3h2t.png" alt="Deployment failure" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Switching to an absolute path fixed it completely. Relative paths are environment-dependent. Absolute paths are not.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 5 — Monitoring Failure After Log Cleanup
&lt;/h2&gt;

&lt;p&gt;Removing a log file broke a symlink-based monitoring agent. A hard link to the same file survived without any issues.&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.amazonaws.com%2Fuploads%2Farticles%2Fmbuk5ct3t5qngdf7i9jj.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%2Fmbuk5ct3t5qngdf7i9jj.png" alt="Hard link works, symlink broken" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A symlink is just a pointer to a path — remove the original and the symlink has nothing to point to. A hard link shares the same inode, so the data lives on as long as the link exists. For monitoring tools that need to survive log rotation, hard links are the safer choice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 6 — Sensitive Data Exposure Hunt
&lt;/h2&gt;

&lt;p&gt;Scanned an entire directory tree for exposed credentials using &lt;code&gt;grep -r&lt;/code&gt;, multiple expressions with &lt;code&gt;-e&lt;/code&gt;, and a pattern file with &lt;code&gt;-f&lt;/code&gt;. Found passwords, API keys, and tokens sitting in plaintext in both config and log files.&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.amazonaws.com%2Fuploads%2Farticles%2F4xe8es6jvz0sm3xt13wb.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%2F4xe8es6jvz0sm3xt13wb.png" alt="Findings from grep scan" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finding credentials in plaintext means immediate rotation. No exceptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 7 — Shared Directory Stability Controls
&lt;/h2&gt;

&lt;p&gt;Developers were losing files because teammates were accidentally deleting each other's work. The fix was a single command — applying the sticky bit with &lt;code&gt;chmod +t&lt;/code&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2Fv3s6bkkt1578el9d96jc.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%2Fv3s6bkkt1578el9d96jc.png" alt="Cross-user deletion blocked" width="800" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sticky bit means only the file owner or root can delete a file, even if everyone in the group has write access. It's the same mechanism that keeps &lt;code&gt;/tmp&lt;/code&gt; working safely on every Linux system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 8 — Special Permission Risk Review
&lt;/h2&gt;

&lt;p&gt;This one covered three special bits — sticky, setgid, and setuid — across a nested production-like directory path.&lt;/p&gt;

&lt;p&gt;SetGID ensures new files inherit the directory's group automatically, so the whole team always has access without needing manual &lt;code&gt;chgrp&lt;/code&gt; after every file creation.&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.amazonaws.com%2Fuploads%2Farticles%2Fdoofvkdfnebxdw72je5v.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%2Fdoofvkdfnebxdw72je5v.png" alt="SetGID group inheritance" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For setuid, the difference between lowercase &lt;code&gt;s&lt;/code&gt; and uppercase &lt;code&gt;S&lt;/code&gt; is worth knowing. Lowercase means it's active. Uppercase means setuid was set without an execute bit — completely meaningless and always a misconfiguration.&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.amazonaws.com%2Fuploads%2Farticles%2Fk6cjz5kd2872fl1ietuc.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%2Fk6cjz5kd2872fl1ietuc.png" alt="SetUID s vs S" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 9 — Process Anomaly Investigation
&lt;/h2&gt;

&lt;p&gt;A rogue infinite loop process was consuming 100% CPU. I identified it with &lt;code&gt;ps&lt;/code&gt; and &lt;code&gt;top&lt;/code&gt;, suspended it with &lt;code&gt;kill -STOP&lt;/code&gt;, resumed it with &lt;code&gt;kill -CONT&lt;/code&gt;, and terminated it gracefully with &lt;code&gt;kill -15&lt;/code&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2Fz8quzdzp2t5z3ludtx5t.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%2Fz8quzdzp2t5z3ludtx5t.png" alt="Rogue process identified" width="800" height="420"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2F27x5oer9t10z882cfmqo.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%2F27x5oer9t10z882cfmqo.png" alt="Process terminated" width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Always try &lt;code&gt;kill -15&lt;/code&gt; (SIGTERM) first. It lets the process clean up properly. &lt;code&gt;kill -9&lt;/code&gt; forces it dead with no cleanup — in production that can mean corrupted data or stuck locks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 10 — Incident Documentation via Heredoc
&lt;/h2&gt;

&lt;p&gt;Generated a structured incident report for all 10 scenarios using a heredoc directly in the terminal — no text editor needed.&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.amazonaws.com%2Fuploads%2Farticles%2F06hl5ucin3zsy8koqfb5.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%2F06hl5ucin3zsy8koqfb5.png" alt="Incident report generated" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;A few things that genuinely stuck with me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;chattr&lt;/code&gt; is underused.&lt;/strong&gt; For files that should never be touched, it's a stronger guarantee than &lt;code&gt;chmod&lt;/code&gt; — it sits below the permission layer entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;gt;&lt;/code&gt; vs &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; matters more than people realise.&lt;/strong&gt; In log management this is the difference between preserving forensic history and destroying it. Default to &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uppercase &lt;code&gt;S&lt;/code&gt; on a file is always a misconfiguration.&lt;/strong&gt; Don't ignore it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Absolute paths in scripts are not optional in production.&lt;/strong&gt; They work from anywhere. Relative paths don't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hard links and symlinks are not interchangeable.&lt;/strong&gt; Symlinks are convenient but fragile. Know when to use each.&lt;/p&gt;

&lt;p&gt;This assignment was genuinely useful. These are not contrived scenarios — they reflect real incidents. If you want to dig into the full commands and evidence for each one, everything is documented on my GitHub: &lt;a href="https://github.com/Yaa-K/parocyber-linux-assignment" rel="noopener noreferrer"&gt;github.com/Yaa-K/parocyber-linux-assignment&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Completed as part of the ParoCyber Linux Assignment, facilitated by Samuel Nartey Otuafo at ParoCyber LLC.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>security</category>
      <category>devsecops</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>I Thought I Knew Linux. This Lab Proved Me Wrong.</title>
      <dc:creator>Yaa Kesewaa Yeboah </dc:creator>
      <pubDate>Fri, 20 Feb 2026 21:57:19 +0000</pubDate>
      <link>https://dev.to/yaak/i-thought-i-knew-linux-this-lab-proved-me-wrong-2ljp</link>
      <guid>https://dev.to/yaak/i-thought-i-knew-linux-this-lab-proved-me-wrong-2ljp</guid>
      <description>&lt;p&gt;I've been using Linux for a while. Commands like &lt;code&gt;useradd&lt;/code&gt;, &lt;code&gt;chmod&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt; — I knew them. I could navigate the terminal without panicking. So when I started my first assignment in the ParoCyber DevSecOps Bootcamp, I figured it would be straightforward.&lt;/p&gt;

&lt;p&gt;It wasn't. And I mean that in the best way possible.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Assignment Was About
&lt;/h2&gt;

&lt;p&gt;The lab had two scenarios. The first was a password state investigation — find users on a system with no passwords set, understand &lt;em&gt;where&lt;/em&gt; Linux stores that information, and remediate it. The second was a full onboarding simulation: create users, assign them to department groups, configure a CI/CD service account, manage sudo access, and safely offboard a user.&lt;/p&gt;

&lt;p&gt;On paper, it sounds like basic sysadmin work. In practice, it forced me to think like a security engineer — and that changed everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Moment That Reframed Everything
&lt;/h2&gt;

&lt;p&gt;In Scenario 1, the task said: &lt;em&gt;"You are not told where Linux stores password state. Finding it is part of the task."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I knew about &lt;code&gt;/etc/passwd&lt;/code&gt;. Everyone who has touched Linux knows &lt;code&gt;/etc/passwd&lt;/code&gt;. But when I ran &lt;code&gt;cat /etc/passwd&lt;/code&gt;, the password field just showed &lt;code&gt;x&lt;/code&gt;. A placeholder. I had seen that a hundred times and never thought twice about it.&lt;/p&gt;

&lt;p&gt;That &lt;code&gt;x&lt;/code&gt; means the actual password data lives somewhere else — &lt;code&gt;/etc/shadow&lt;/code&gt;. And when I inspected it, I saw something that stopped me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;audit_test:!:...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;!&lt;/code&gt; in the second field. One character. That single character is the difference between a secured account and a vulnerability sitting open on your system. I had been using Linux without ever knowing that file existed, let alone what it meant.&lt;/p&gt;

&lt;p&gt;Then I tested whether a normal user could read &lt;code&gt;/etc/shadow&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;cat&lt;/span&gt; /etc/shadow
&lt;span class="c"&gt;# Permission denied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's when it clicked. The fact that &lt;code&gt;/etc/passwd&lt;/code&gt; is world-readable but &lt;code&gt;/etc/shadow&lt;/code&gt; is root-only isn't an accident — it's a deliberate security design. Two files, one visible to everyone, one locked down. I had been looking at half the picture this whole time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 2: Access Control Is a People Problem Too
&lt;/h2&gt;

&lt;p&gt;The second scenario was about onboarding eight new staff members across four departments — dev, security, QA, and ops. Each team gets its own group. Each group gets access to what it needs and nothing more.&lt;/p&gt;

&lt;p&gt;What struck me here wasn't the commands. It was the &lt;em&gt;reasoning&lt;/em&gt; behind them.&lt;/p&gt;

&lt;p&gt;When I created the &lt;code&gt;ci_runner&lt;/code&gt; service account with a non-login shell:&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;sudo &lt;/span&gt;useradd &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /usr/sbin/nologin ci_runner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trainer's question wasn't "did you run the command" — it was "do you know &lt;em&gt;why&lt;/em&gt; this matters?" A service account with an interactive shell is an open door. Automated pipelines don't need to log in. Humans shouldn't be logging in as them either. That shell setting is a security decision, not a configuration detail.&lt;/p&gt;

&lt;p&gt;Same with removing a user at the end. I used:&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;sudo &lt;/span&gt;userdel yaa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not &lt;code&gt;userdel -r&lt;/code&gt;. The &lt;code&gt;-r&lt;/code&gt; flag would have deleted the home directory too. But in a real environment, that directory might contain evidence — scripts, logs, files that matter in an investigation. Deleting it immediately could mean destroying forensic data. That's not a Linux lesson. That's a security operations lesson.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'm Taking Away
&lt;/h2&gt;

&lt;p&gt;I came into this thinking DevSecOps was Linux plus some security tools on top. What I'm leaving with is a different understanding — security isn't a layer you add. It's a lens you apply to every decision, including the ones that look purely technical.&lt;/p&gt;

&lt;p&gt;The commands I ran in this lab weren't new. The &lt;em&gt;questions&lt;/em&gt; behind them were.&lt;/p&gt;

&lt;p&gt;Why does this file have these permissions? Why does this account need this shell? What happens to this data when this user is gone? Those questions are what separate someone who &lt;em&gt;uses&lt;/em&gt; Linux from someone who &lt;em&gt;secures&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;This is assignment one. I'm already thinking differently. Looking forward to what's next.&lt;/p&gt;

</description>
      <category>devsecops</category>
      <category>linux</category>
      <category>cybersecurity</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
