<?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: Aharon Hyman</title>
    <description>The latest articles on DEV Community by Aharon Hyman (@hymanaharon).</description>
    <link>https://dev.to/hymanaharon</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%2F510436%2Fb62f9c04-3184-4894-9194-ef79ab6c9a17.jpg</url>
      <title>DEV Community: Aharon Hyman</title>
      <link>https://dev.to/hymanaharon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hymanaharon"/>
    <language>en</language>
    <item>
      <title>Beyond the Vibe: Why “Secure by Default” is the Only Way to Build in 2026</title>
      <dc:creator>Aharon Hyman</dc:creator>
      <pubDate>Mon, 11 May 2026 07:39:11 +0000</pubDate>
      <link>https://dev.to/hymanaharon/beyond-the-vibe-why-secure-by-default-is-the-only-way-to-build-in-2026-2oh6</link>
      <guid>https://dev.to/hymanaharon/beyond-the-vibe-why-secure-by-default-is-the-only-way-to-build-in-2026-2oh6</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Beyond the Vibe: Why "Secure by Default" is the Only Way to Build in 2026&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;We’ve all been there. You’re trying to complete a simple task—in my case, registering my son for a Judo seminar—and the page hangs. As a developer, your instinct isn't to refresh; it's to open the &lt;strong&gt;Network Tab&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
What I found wasn't just a bug. It was a window into a growing problem in the era of "vibe coding" and rapid-fire deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Discovery: A Judo Chop to Data Privacy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The landing page for this event was built using a popular third-party "vibe coding" platform. These tools are incredible for speed, allowing users to describe a functional app and see it come to life in seconds. However, speed without a safety net is a liability.&lt;br&gt;&lt;br&gt;
By inspecting the network traffic to see why the registration was failing, I realized the API wasn't just sending my son's data—it was capable of sending &lt;strong&gt;everyone's&lt;/strong&gt;. Using Postman, I confirmed the worst: I had full &lt;strong&gt;CRUD (Create, Read, Update, Delete)&lt;/strong&gt; access. I could have wiped the entire event roster or modified participant details with a few clicks.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Root Cause: The Danger of Permissive Defaults&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The platform offered a simple toggle: &lt;strong&gt;[Allow All Users]&lt;/strong&gt; vs. &lt;strong&gt;[Admins Only]&lt;/strong&gt;. By default, it was set to &lt;strong&gt;"Allow All Users."&lt;/strong&gt; This is the "Default-Allow" trap. It assumes the developer will remember to lock the doors later. But if a door starts unlocked, it usually stays unlocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Sticklight Handles This&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Short answer: Sticklight defaults to "Deny All" by design.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Seeing this failure in the wild made me reflect on our own architecture. Here is the breakdown of how we prevent this exact scenario:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Row Level Security (RLS) is Mandatory&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When Cloud Backend is enabled in Sticklight, every table has RLS enabled by default. With RLS enabled and &lt;strong&gt;no policies defined&lt;/strong&gt;, the default behavior is a total lockdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SELECT/INSERT/UPDATE/DELETE&lt;/strong&gt;: All Denied.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the polar opposite of the "Allow All Users" default. In Sticklight, if a developer forgets to add policies, users get a 403 error—not access to the entire database.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Policies Must Be Explicitly Created&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The AI agent is built with a security-first mindset. It is instructed to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Never disable RLS.
&lt;/li&gt;
&lt;li&gt;Never create USING (true) policies unless data is genuinely public.
&lt;/li&gt;
&lt;li&gt;Always scope user data with user_id filters.
&lt;/li&gt;
&lt;li&gt;Create the minimum necessary permissions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example: The Judo Registration Table&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If this seminar page had been built in Sticklight, the generated SQL would look like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-- RLS is enabled by default. &lt;br&gt;
-- Policy: Users can only see their OWN registration.&lt;br&gt;
CREATE POLICY "Users can view own registration"&lt;br&gt;
ON registrations FOR SELECT&lt;br&gt;
USING (user_id = auth.uid());&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In this scenario, an attacker inspecting the network tab would only see their own data. The "vibe" remains the same for the user, but the data remains private.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Failure Mode Comparison&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Other "Vibe" Platforms&lt;/th&gt;
&lt;th&gt;Sticklight&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default setting&lt;/td&gt;
&lt;td&gt;"All Users" (permissive)&lt;/td&gt;
&lt;td&gt;No access (deny all)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgot to configure&lt;/td&gt;
&lt;td&gt;Full CRUD for everyone&lt;/td&gt;
&lt;td&gt;403 Forbidden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode&lt;/td&gt;
&lt;td&gt;Silent data breach&lt;/td&gt;
&lt;td&gt;Broken feature (visible)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Pro-Tip: How to "Vibe Code" Without Leaking Data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you’re building your own apps from scratch using AI agents (like Claude Code, Replit Agent, or Cursor), you are the primary architect. Here’s how to ensure your vibe stays secure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Security-First Prompting:&lt;/strong&gt; Specifically instruct the AI to use Secure-by-Default patterns and assume the frontend is untrusted.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Establish a Security Rubric:&lt;/strong&gt; Maintain a persistent CLAUDE.md or instructions file that mandates RLS and 403-by-default behavior.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "Postman Audit":&lt;/strong&gt; Never trust the UI. Manually test your API endpoints with tools like Postman to ensure they don't leak data when unauthenticated.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review Every Diff:&lt;/strong&gt; Look specifically for cases where the agent might have simplified a policy or left a "TODO" on an authentication check.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As we move toward AI-generated boilerplate and "vibe-driven" development, the responsibility shifts to the platform architect. At Sticklight, we believe a "broken" feature is a ticket, but a "broken" security setting is a catastrophic liability. By choosing a "Deny All" default, we ensure that the path of least resistance for a developer is also the safest one for the end user.&lt;/p&gt;

</description>
      <category>security</category>
      <category>vibecoding</category>
      <category>guardrails</category>
      <category>brokenaccesscontrol</category>
    </item>
    <item>
      <title>CodeSandbox init shortcuts</title>
      <dc:creator>Aharon Hyman</dc:creator>
      <pubDate>Wed, 06 Jan 2021 12:52:44 +0000</pubDate>
      <link>https://dev.to/hymanaharon/codesandbox-init-shortcuts-3g3n</link>
      <guid>https://dev.to/hymanaharon/codesandbox-init-shortcuts-3g3n</guid>
      <description>&lt;p&gt;Fun new find of the day&lt;br&gt;
Type into browser URL: “&lt;a href="http://js.new%E2%80%9D"&gt;http://js.new”&lt;/a&gt;, “&lt;a href="http://vue.new%E2%80%9D"&gt;http://vue.new”&lt;/a&gt;, “&lt;a href="http://react.new%E2%80%9D"&gt;http://react.new”&lt;/a&gt;, “&lt;a href="http://ng.new%E2%80%9D"&gt;http://ng.new”&lt;/a&gt;, “&lt;a href="http://ts.new%E2%80%9D"&gt;http://ts.new”&lt;/a&gt;&lt;br&gt;
You will get full environment to play around in.&lt;/p&gt;

</description>
      <category>devtips</category>
      <category>webdev</category>
      <category>browsertricks</category>
    </item>
    <item>
      <title>Imposter syndrome &amp; at what point did you realise you where a developer</title>
      <dc:creator>Aharon Hyman</dc:creator>
      <pubDate>Sun, 29 Nov 2020 19:59:38 +0000</pubDate>
      <link>https://dev.to/hymanaharon/imposter-syndrome-at-what-point-did-you-realise-you-where-a-developer-3hog</link>
      <guid>https://dev.to/hymanaharon/imposter-syndrome-at-what-point-did-you-realise-you-where-a-developer-3hog</guid>
      <description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Impostor_syndrome"&gt;Imposter syndrome&lt;/a&gt; is something I have often felt in my journey to becoming a developer. &lt;br&gt;
I am self taught (mostly), and was lucky to be given a chance at a growing start up (&lt;a href="https://www.strattic.com/careers/"&gt;Strattic&lt;/a&gt;). &lt;br&gt;
My first few weeks where filled with fake it until you make it, with many late nights and LOOOOTS of caffeine. But I after a couple of weeks I sat down with the team to show what I had achieved and I amazed myself.&lt;br&gt;
I look back on that code now and laugh, and am amazed that not only does it still work but some of that code still on production (with a lot of refactors and help from much more experienced devs).&lt;br&gt;
Did you have an AH HA! moment when you suddenly realised you where keeping up with the big boys?&lt;/p&gt;

</description>
      <category>conversation</category>
      <category>forn00bs</category>
    </item>
    <item>
      <title>Maintaining a company culture while working from home?</title>
      <dc:creator>Aharon Hyman</dc:creator>
      <pubDate>Sun, 15 Nov 2020 11:54:29 +0000</pubDate>
      <link>https://dev.to/hymanaharon/how-to-keep-a-company-culture-while-working-from-home-14d9</link>
      <guid>https://dev.to/hymanaharon/how-to-keep-a-company-culture-while-working-from-home-14d9</guid>
      <description>&lt;h1&gt;
  
  
  Company culture at home.
&lt;/h1&gt;

&lt;p&gt;Has your company switched to remote work?&lt;br&gt;
Have you made any changes to your company culture to fit in with a remote environment?&lt;br&gt;
Do you find your life-work balance has shifted as a result of remote work?&lt;/p&gt;

&lt;p&gt;I will start :D.&lt;br&gt;
Our company values our work culture and has spent time supporting us whether with assistance to set up a home office or with increased social interactions 'online'.&lt;br&gt;
We moved out weekly happy hour online and try to spend some time catching up with each other outside of our regular meetings.&lt;br&gt;
A big one for me was encouraging everyone to have their videos on during meetings, it helps you feel like you are talking with colleagues and humans, not just talking to a computer. Even if it means you have to get more formal looking PJ's!&lt;br&gt;
Being at home especially during lockdown has meant that putting in a full work day can sometimes not be so easy, especially with little kids around. Work being flexible and allowing for make up hours in the evenings is a big help.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>workfromhome</category>
      <category>officeculture</category>
    </item>
    <item>
      <title>Why I will no longer be using console.log() to check React state updates</title>
      <dc:creator>Aharon Hyman</dc:creator>
      <pubDate>Wed, 11 Nov 2020 09:05:15 +0000</pubDate>
      <link>https://dev.to/hymanaharon/why-i-will-no-longer-be-using-console-log-to-check-react-state-updates-29el</link>
      <guid>https://dev.to/hymanaharon/why-i-will-no-longer-be-using-console-log-to-check-react-state-updates-29el</guid>
      <description>&lt;p&gt;As a front end developer one of the key tools in my debugging arsenal is the console log. The ability to log data and check that it renders as expected in the browser allows you to quickly debug specific parts of your code in a quick and neat fashion.&lt;/p&gt;

&lt;p&gt;I work in React and being able to console log your state and check that the components are rendering as expected is a key development pattern.&lt;/p&gt;

&lt;p&gt;When your state is simple and you have one or two values to monitor, &lt;strong&gt;console.log()&lt;/strong&gt; is great but when you start adding more to your component state especially in a Class component this can start getting very ugly as your state object being output is minified.&lt;/p&gt;

&lt;h1&gt;
  
  
  Console.table()
&lt;/h1&gt;

&lt;p&gt;Console.table is a great way of logging to the console that will parse your data and log in the console as a table.&lt;/p&gt;

&lt;p&gt;Using the console in Chrome dev tools we can see console.table() at work&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3m5h9sld37bqm66i5skq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3m5h9sld37bqm66i5skq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The function console.table() takes either an array or an object and can also take an optional parameter ‘columns’&lt;/p&gt;

&lt;p&gt;The first column will be labelled index and in the case of an array it will display the indices, while an object will display the Key or property names. &lt;/p&gt;

&lt;p&gt;The table also works as you would expect allowing you to sort the column by clicking on the title. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that in Firefox console.table() is currently limited to 1000 rows&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Columns&lt;/strong&gt;&lt;br&gt;
Where this really comes in useful is the columns parameter. &lt;br&gt;
As a default the columns.table() will list all the elements in an object. The columns parameter takes an array of column names or values and allows you to select the values you would like displayed. By using this you are able to parse an array of large objects and select only the columns relevant to you.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logging your state!&lt;/strong&gt;&lt;br&gt;
Going back to React, a common pattern is to store a server response in your state, often there is data involved that will not be used in the component you are working on. &lt;br&gt;
Using the columns parameter you can display in the console only the columns of data that you are actually watching&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lets see what that looks like&lt;/strong&gt;&lt;br&gt;
In the below example our api call returns a json of users and they are stored in the state. &lt;br&gt;
Using console.table(users) in the render we will be able to produce the below table and check the data is as expected, without having to build out our table component in the ui.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdd9auary9nrevo6gjkkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdd9auary9nrevo6gjkkw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now if we wanted to build a quick filter button to check which of our clients paid in Yuan Renminbi we could do the following &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const onlyYuanUsers = users.filter( user =&amp;gt; user.currency === "Yuan Renminbi")
console.table(onlyYuanUsers)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;this will produce a filtered table to check it returns the values you need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fav3lgofcfhqyoy26hv6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fav3lgofcfhqyoy26hv6x.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But this is more data than you need to display to check your filter is working. &lt;/p&gt;

&lt;p&gt;By passing in the columns parameter, you are able to select which columns you want to select by defining an array of the column names. &lt;/p&gt;

&lt;p&gt;The output will be a more compact table allowing for an ‘at a glance’ comparison.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

console.table(onlyYuanUsers, ['id', 'currency'])


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi45dob16iwiajfftjcxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi45dob16iwiajfftjcxs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is worthy of note that as of publishing console.table() is supported by all modern browsers with the exception of IE (I did say modern)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>firstpost</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
