<?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: Charles P</title>
    <description>The latest articles on DEV Community by Charles P (@charles_p_2803da53bc5d54c).</description>
    <link>https://dev.to/charles_p_2803da53bc5d54c</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%2F3896876%2F3dced60e-2f66-499b-8a41-b6be8f08fac4.png</url>
      <title>DEV Community: Charles P</title>
      <link>https://dev.to/charles_p_2803da53bc5d54c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/charles_p_2803da53bc5d54c"/>
    <language>en</language>
    <item>
      <title>11 Months Undetected: Inside a Silent Data Exfiltration Through a Trusted Vendor's Remote-Access Tool</title>
      <dc:creator>Charles P</dc:creator>
      <pubDate>Mon, 27 Apr 2026 19:44:18 +0000</pubDate>
      <link>https://dev.to/charles_p_2803da53bc5d54c/11-months-undetected-inside-a-silent-data-exfiltration-through-a-trusted-vendors-remote-access-47n7</link>
      <guid>https://dev.to/charles_p_2803da53bc5d54c/11-months-undetected-inside-a-silent-data-exfiltration-through-a-trusted-vendors-remote-access-47n7</guid>
      <description>&lt;h2&gt;
  
  
  The Call That Changed Everything
&lt;/h2&gt;

&lt;p&gt;It started with an anomaly that almost nobody noticed.&lt;/p&gt;

&lt;p&gt;A regional accounting firm — mid-sized, 60+ employees, handling tax filings and financial audits for hundreds of business clients — reached out after their cyber insurance provider flagged unusual outbound traffic during a routine policy renewal review. The firm's internal IT contact assumed it was a misconfigured backup job. It wasn't.&lt;/p&gt;

&lt;p&gt;What we uncovered over the next several weeks was eleven months of silent, systematic data exfiltration. Client financial records, PII, tax identification numbers, business banking details. All of it leaving the network through a vector nobody had thought to question: a remote-access tool installed by a third-party payroll software vendor.&lt;/p&gt;

&lt;p&gt;This is the story of how it happened, how we found it, and what it took to contain the damage without destroying the trust that firm had spent decades building.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Attack Vector Nobody Audited
&lt;/h2&gt;

&lt;p&gt;The vendor in question was a legitimate payroll software company the firm had used for years. During a routine product update roughly eleven months prior, the vendor's support team had remotely installed a lightweight remote desktop agent — standard practice for troubleshooting. The installation was authorized. The agent itself was legitimate.&lt;/p&gt;

&lt;p&gt;The problem: the vendor had been compromised. Attackers had obtained credentials to the vendor's internal support infrastructure and were using it as a launchpad into every client environment where their remote-access agent was deployed.&lt;/p&gt;

&lt;p&gt;This is a classic &lt;strong&gt;supply chain intrusion&lt;/strong&gt;, and it's devastatingly effective because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The remote-access tool is already trusted by endpoint security&lt;/li&gt;
&lt;li&gt;Traffic originates from a known, whitelisted IP range&lt;/li&gt;
&lt;li&gt;The activity looks like normal vendor support behavior&lt;/li&gt;
&lt;li&gt;There's no malware on the victim's systems to detect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The attackers weren't noisy. They exfiltrated data in small, irregular bursts — typically during business hours, mimicking legitimate support sessions. Over eleven months, they systematically harvested the firm's file shares.&lt;/p&gt;




&lt;h2&gt;
  
  
  How We Uncovered It
&lt;/h2&gt;

&lt;p&gt;The insurance provider's anomaly flag gave us a starting point, but it was vague: elevated outbound data volume to a third-party IP. Our investigation began with log analysis.&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="c"&gt;# Reconstructing outbound session data from firewall logs&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"PERMIT"&lt;/span&gt; firewall.log | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $6, $7, $8, $12}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-k4&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sorting by data volume revealed dozens of sessions to a single IP range — all attributed in the logs to the payroll vendor's support domain. At first glance, nothing alarming. But cross-referencing timestamps with the vendor's actual support ticket history showed a critical gap: &lt;strong&gt;most of these sessions had no corresponding support ticket&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We then pulled endpoint telemetry from the remote-access agent's own activity logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2023-03-14 10:42:17] Session initiated — user: vendor_support_01
[2023-03-14 10:42:19] File browse: \\FILESERVER01\ClientRecords\2022\
[2023-03-14 10:43:04] File copy: 47 files transferred
[2023-03-14 10:43:31] Session closed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No support ticket. No email from the client requesting help. A session opened, files copied, session closed. Repeated hundreds of times across eleven months.&lt;/p&gt;

&lt;p&gt;The attacker was methodical. They never triggered volume thresholds that would have alerted on a single session. They rotated through directories slowly, never grabbing everything at once.&lt;/p&gt;




&lt;h2&gt;
  
  
  Containment: What You Do and Don't Do
&lt;/h2&gt;

&lt;p&gt;Here's where firms make their worst mistakes. The instinct is to immediately kill everything — terminate vendor access, wipe affected systems, rotate all credentials simultaneously. That instinct can destroy forensic evidence and tip off attackers to cover their tracks before you've mapped the full scope.&lt;/p&gt;

&lt;p&gt;Our containment sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Isolate, don't disconnect.&lt;/strong&gt; We moved the compromised file server to a quarantine VLAN before terminating vendor access. This preserved live artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshot before remediation.&lt;/strong&gt; Full disk images before any credential rotation or system changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notify vendor security team in parallel.&lt;/strong&gt; They confirmed their support infrastructure had been compromised. Eleven other clients were affected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Map the blast radius.&lt;/strong&gt; Using the session logs, we reconstructed exactly which directories, which files, which client records were accessed. This took four days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staged credential rotation.&lt;/strong&gt; Rotating everything at once in an active environment causes outages. We sequenced rotations across 72 hours.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Client Relationship Problem Is Harder Than the Technical Problem
&lt;/h2&gt;

&lt;p&gt;This is what the incident response playbooks don't tell you: &lt;strong&gt;notifying clients of a breach involving their financial data, when you're a firm whose entire value proposition is trust, is existentially dangerous.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The firm had approximately 340 business clients whose data may have been accessed. Legal counsel advised notification within the breach window required by their state. We advised being specific about what was and wasn't accessed, rather than issuing a vague blanket notification.&lt;/p&gt;

&lt;p&gt;The session logs saved them. Because we could reconstruct precisely which client folders were accessed in which sessions, the firm was able to notify clients with specific detail:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Your 2021 and 2022 tax filing records were accessed in three sessions between April and June 2023. The following file types were involved..."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Specificity is uncomfortable. It's also the only thing that preserves credibility. Clients who received vague "we may have had an incident" letters were more likely to churn. Clients who received detailed, honest disclosures with a clear remediation timeline largely stayed.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Should Have Prevented This
&lt;/h2&gt;

&lt;p&gt;The hard truth: this breach was preventable with controls the firm hadn't prioritized.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vendor access reviews.&lt;/strong&gt; A quarterly audit of all active third-party remote-access agents would have caught an agent with no recent legitimate sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session logging with anomaly baselining.&lt;/strong&gt; If you authorize vendor remote access, log every session and baseline what "normal" looks like.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Just-in-time access.&lt;/strong&gt; Rather than a persistent always-on agent, require vendors to request access for a defined window. The agent activates, the session occurs, the access closes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outbound DLP rules.&lt;/strong&gt; Even basic data-volume thresholds per destination IP would have flagged this within weeks, not months.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're evaluating your own third-party access posture and aren't sure where to start, the advisory team at &lt;a href="http://www.asktechgurus.com" rel="noopener noreferrer"&gt;www.asktechgurus.com&lt;/a&gt; has published vendor risk frameworks specifically designed for professional services firms managing sensitive client data.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Lesson That Doesn't Age
&lt;/h2&gt;

&lt;p&gt;Supply chain attacks succeed not because defenders are incompetent, but because they extend trust to familiar names and stop asking questions. The remote-access agent was legitimate. The vendor was legitimate. The traffic looked legitimate.&lt;/p&gt;

&lt;p&gt;The attackers exploited a gap between &lt;em&gt;authorized&lt;/em&gt; and &lt;em&gt;audited&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Every tool you've permitted into your environment is a door. The question isn't whether you trust whoever gave you the key — it's whether you're watching who walks through.&lt;/p&gt;

&lt;p&gt;Eleven months is a long time for a door to be open.&lt;/p&gt;




</description>
      <category>cybersecurity</category>
      <category>incidentresponse</category>
      <category>supplychainattack</category>
      <category>databreach</category>
    </item>
    <item>
      <title>I Applied to 47 Internships Across 6 Spreadsheets and Still Blew It: A Postmortem</title>
      <dc:creator>Charles P</dc:creator>
      <pubDate>Mon, 27 Apr 2026 19:11:36 +0000</pubDate>
      <link>https://dev.to/charles_p_2803da53bc5d54c/i-applied-to-47-internships-across-6-spreadsheets-and-still-blew-it-a-postmortem-304c</link>
      <guid>https://dev.to/charles_p_2803da53bc5d54c/i-applied-to-47-internships-across-6-spreadsheets-and-still-blew-it-a-postmortem-304c</guid>
      <description>&lt;p&gt;Let me tell you about the most embarrassing professional mistake I made as a CS student. I missed a follow-up deadline for an internship offer — not because I didn't care, but because I had buried it under six layers of organizational chaos I genuinely believed was "a system."&lt;/p&gt;

&lt;p&gt;This is that story. It's cringeworthy. It's specific. And if you're managing your internship hunt with a patchwork of spreadsheets, sticky notes, and gut feelings, you need to read it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup: Six Spreadsheets and a False Sense of Control
&lt;/h2&gt;

&lt;p&gt;By February of my junior year, I had applied to 47 internships. Here's what my "tracking system" actually looked like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sheet 1&lt;/strong&gt; — "Applications Master List" (last updated January 3rd)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sheet 2&lt;/strong&gt; — "FAANG + Big Tech" (a separate tab because these felt special)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sheet 3&lt;/strong&gt; — "Startups 2024" (copied from a Reddit post, half the companies were dead)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sheet 4&lt;/strong&gt; — "Applied But No Portal Confirmation" (a graveyard)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sheet 5&lt;/strong&gt; — a friend's shared doc I had been given edit access to "for inspiration"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sheet 6&lt;/strong&gt; — an export from LinkedIn's saved jobs feature that I reformatted exactly once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then there were the sticky notes. Three of them. On my monitor. One said "FOLLOW UP - APEX???" with two question marks. Another said "Resume v7 or v8??" The third was a phone number with no name attached. I never figured out whose it was.&lt;/p&gt;

&lt;p&gt;Each spreadsheet had slightly different columns. Some tracked "date applied." Some tracked "last contact." Some had a status column with values like "applied," "waiting," "maybe?", and — I'm not kidding — "vibes."&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Happened
&lt;/h2&gt;

&lt;p&gt;In early March, a mid-size fintech company sent me an offer letter via email. It was a real offer. Competitive pay, good location, solid team. They gave me a 10-day window to respond.&lt;/p&gt;

&lt;p&gt;I saw the email. I remember feeling genuinely excited. I opened one of my spreadsheets, looked for the company name, didn't find it immediately, told myself I'd log it "later," and then got distracted by a problem set.&lt;/p&gt;

&lt;p&gt;I logged it four days later — in the wrong spreadsheet. Under the company's &lt;em&gt;parent company name&lt;/em&gt;, which I only half-remembered. The deadline column said "March 19th" but I had typed it wrong. It was actually March 17th.&lt;/p&gt;

&lt;p&gt;On March 18th, I was catching up on emails and saw the offer. I also saw a follow-up from their recruiter sent March 16th asking if I had questions. I had never replied to that either.&lt;/p&gt;

&lt;p&gt;I emailed them the morning of March 19th, apologized, said I was still interested. They had already extended the offer to another candidate. Offer rescinded. Done.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Failure Analysis
&lt;/h2&gt;

&lt;p&gt;If you treat your job search like an engineering problem (you should), here's what went wrong at a systems level:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single point of failure: human memory.&lt;/strong&gt; My spreadsheets were write-only. I wrote data in but had no mechanism for surfacing critical deadlines proactively. A calendar reminder, a cron job, literally anything automated would have caught this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No canonical source of truth.&lt;/strong&gt; Six spreadsheets means six chances for data to be stale, duplicated, or wrong. Every lookup required reconciling multiple sources mentally. That's O(n) cognitive overhead per decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status fields were undefined.&lt;/strong&gt; "Vibes" is not a status. "Maybe?" is not actionable. I had no consistent finite state machine for applications: Applied → Screen Scheduled → Interview → Offer → Decision Due → Accepted/Rejected. Without clear states, I couldn't see what actually needed attention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No deadline-first view.&lt;/strong&gt; Every spreadsheet was sorted by company name or date applied — not by urgency. The most important row was buried alphabetically under "F."&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Should Have Done Differently
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Centralize immediately.&lt;/strong&gt; One place. Non-negotiable. Every application gets logged the moment you submit, not later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deadline tracking is primary, not a column.&lt;/strong&gt; Deadlines should drive your dashboard. You should open your tracker and see "3 things need action in the next 48 hours" before you see anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status as a finite state machine.&lt;/strong&gt; Define your stages and stick to them. Knowing an application is in "Offer Received — Decision Due March 17" is operationally different from "offer!!!" in a cell somewhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automate reminders.&lt;/strong&gt; Even a simple Google Apps Script that emails you when a deadline column is within 72 hours would have saved me. Spreadsheets can do this. Set it up once.&lt;/p&gt;

&lt;p&gt;After that disaster I eventually rebuilt my workflow from scratch — I ended up building &lt;a href="https://www.myinternshiptracker.com/?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=devto-mohknts1" rel="noopener noreferrer"&gt;InternshipTracker&lt;/a&gt; partly because I wanted something that treated deadlines as first-class objects rather than afterthoughts buried in a column.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Lesson
&lt;/h2&gt;

&lt;p&gt;The painful irony is that I had &lt;em&gt;more&lt;/em&gt; data than most of my peers. 47 applications. Six tracking documents. I was thorough in the wrong direction — optimizing for logging breadth instead of decision support.&lt;/p&gt;

&lt;p&gt;Your tracking system isn't a historical record. It's a control panel. It should answer one question at any given moment: &lt;strong&gt;what do I need to do right now?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your spreadsheet can't answer that without you mentally joining tables across six tabs, it's not a system. It's archaeology.&lt;/p&gt;

&lt;p&gt;Don't let a recruiter's 10-day window expire because your deadline was in the wrong spreadsheet under the wrong name. That mistake is avoidable. I learned it the hard way so you don't have to.&lt;/p&gt;

</description>
      <category>career</category>
      <category>internships</category>
      <category>productivity</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
