<?xml version="1.0" encoding="UTF-8"?><feed
	xmlns="http://www.w3.org/2005/Atom"
	xmlns:thr="http://purl.org/syndication/thread/1.0"
	xml:lang="en-US"
	>
	<title type="text">Philipp Salvisberg&#039;s Blog</title>
	<subtitle type="text">Database-centric development</subtitle>

	<updated>2026-10-12T18:47:38Z</updated>

	<link rel="alternate" type="text/html" href="https://www.salvis.com/blog/" />
	<id>https://www.salvis.com/blog/feed/atom/</id>
	<link rel="self" type="application/atom+xml" href="https://www.salvis.com/blog/feed/atom/" />

	<generator uri="https://wordpress.org/" version="7.1.3">WordPress</generator>
<icon>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</icon>
<link rel="hub" href="https://pubsubhubbub.appspot.com" />
<link rel="hub" href="https://pubsubhubbub.superfeedr.com" />
<link rel="hub" href="https://websubhub.com/hub" />
<link rel="self" href="https://www.salvis.com/blog/feed/atom/" />
	<entry>
		<author>
			<name>Philipp Salvisberg</name>
							<uri>http://www.salvis.com/</uri>
						</author>

		<title type="html"><![CDATA[Some Thoughts About Joel and AI #JoelKallmanDay]]></title>
		<link rel="alternate" type="text/html" href="https://www.salvis.com/blog/2026/10/14/some-thoughts-about-joel-and-ai-joelkallmanday/" />

		<id>https://www.salvis.com/blog/?p=25305</id>
		<updated>2026-10-12T18:47:38Z</updated>
		<published>2026-10-13T22:01:00Z</published>
		<category scheme="https://www.salvis.com/blog/" term="Oracle" /><category scheme="https://www.salvis.com/blog/" term="JoelKallmanDay" />
		<summary type="html"><![CDATA[<p>Where I Saw Joel for the First Time I remember Joel Kallman’s talk on the boat at APEX World 2019 in Rotterdam very well. I was sitting in the front row on the right, about two metres away from Joel, enjoying his talk. Because I was that close, I could see the<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/10/14/some-thoughts-about-joel-and-ai-joelkallmanday/">Some Thoughts About Joel and AI #JoelKallmanDay</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></summary>

					<content type="html" xml:base="https://www.salvis.com/blog/2026/10/14/some-thoughts-about-joel-and-ai-joelkallmanday/"><![CDATA[
<h2 id="where-i-saw-joel-for-the-first-time" class="wp-block-heading">Where I Saw Joel for the First Time</h2>



<p class="wp-block-paragraph"></p><p>I remember Joel Kallman’s talk on the boat at APEX World 2019 in Rotterdam very well. I was sitting in the front row on the right, about two metres away from Joel, enjoying his talk. Because I was that close, I could see the screen of his laptop. He made use of the available technology: presenter view, which allows you to read your prepared text word for word or just ensure that you do not forget to mention an important point. Some people like using presenter view, and others think you should know your slides and therefore just see what the attendees see. I’m in the latter group, also because I was always afraid of mixing up the presenter and audience views and not being able to fix it in time, especially when switching between slides and live demos. So mirroring was and still is easier for me.</p>



<p class="wp-block-paragraph"></p><p>The talk was excellent. The content was good. It was well presented. It was his talk. The fact that he used technology to support his presentation does not change that. So at what point does using technology change who we consider the author?</p>



<p class="wp-block-paragraph"></p><p>I wonder what Joel would think about AI as we know it today.</p>



<h2 id="how-i-looked-things-up-in-my-early-days" class="wp-block-heading">How I Looked Things Up in My Early Days</h2>



<p class="wp-block-paragraph"></p><p>When I was in school, I liked Duden’s <a href="https://books.google.ch/books?id=F80TAQAAMAAJ" target="_blank" rel="noopener">Sinn- und sachverwandte Wörter</a> the most. You could look up a word and find synonyms and words with similar meanings. I spent a lot of time looking up words and was constantly irritated by my inability to easily put letters in alphabetical order in my head to decide whether I had to go forwards or backwards. Is &#8220;m&#8221; before &#8220;o&#8221;? So I silently say &#8220;a, b, c, d, e, f, g, h, i, j, k, l, m, n, o&#8221; to the melody of the alphabet song we learned in my first school year (similar to <a href="https://open.spotify.com/track/0HMtOkTYNPUMIqrxs9iJWT?si=8b7ba4c5d6ee499f" target="_blank" rel="noopener">this</a>). And ah, yes, &#8220;m&#8221; is before &#8220;o&#8221;. So backwards… Sounds silly, but &#8220;a, b, c, d, e, f, g&#8221; is probably the phrase I use most in my life.</p>



<p class="wp-block-paragraph"></p><p>Back then, I thought it was fancy not to repeat words in the next sentence in my essays, and basically in general, because we were taught that it was a good thing. In the meantime, I have come to believe that you should use the same word to refer to the same thing, regardless of how often it appears in a text. It is less ambiguous. In other words, it is clearer and easier to understand. I believe this is true in IT and in business in general. For poetry, this might be different, but that’s for sure not my domain.</p>



<p class="wp-block-paragraph"></p><p>I also used Duden’s <a href="https://en.wikipedia.org/wiki/Duden" target="_blank" rel="noopener">Die deutsche Rechtschreibung</a> and the <a href="https://en.wikipedia.org/wiki/Brockhaus_Enzyklop%C3%A4die" target="_blank" rel="noopener">Brockhaus Enzyklopädie</a> to look things up and sometimes stumbled across something interesting while scanning the pages for the original term. Driven by curiosity, I learnt a few things along the way.</p>



<p class="wp-block-paragraph"></p><p>In any case, even back then, what I wrote was influenced by things I had read. Sometimes intentionally and, over time, for sure also unintentionally. Learning words and ways of expressing things from others is different from presenting their text or ideas as my own without acknowledgement. That would be <a href="https://www.ox.ac.uk/students/academic/guidance/skills/plagiarism" target="_blank" rel="noopener">plagiarism</a>. But if I could measure how much of my writing was influenced by others, the percentage might well be substantial.</p>



<p class="wp-block-paragraph"></p><p>What I want to say is that I started asking for help very early. Often I asked my father, because he basically knew everything and had a perfect memory. It was easier for me to ask him than to look it up myself (remember, I always had to repeat &#8220;a, b, c, d&#8221; in my head). But more often than not, he just gave me the right book so I could look it up myself and was available to discuss things.</p>



<p class="wp-block-paragraph"></p><p>Since then, many technological inventions have improved our ability to look things up ourselves.</p>



<h2 id="my-first-contact-with-ai" class="wp-block-heading">My First Contact With AI</h2>



<p class="wp-block-paragraph"></p><p>I guess my first use of AI tools was DeepL. I didn’t know that at the time, but DeepL has been using neural networks to translate text since its launch in 2017. See <a href="https://www.deepl.com/en/blog/how-does-deepl-work" target="_blank" rel="noopener">How does DeepL work?</a> for an explanation of the technology.</p>



<p class="wp-block-paragraph"></p><p>Before DeepL offered DeepL Write, I often translated a text from German to English, then the English result back to German, and that result again to English. I made some adjustments in between and repeated the process until I was satisfied. It usually produced a good result, something I felt I could have written myself if given enough time. I provided the initial input as German text, after all, right?</p>



<h2 id="autocomplition-and-refactoring" class="wp-block-heading">Autocomplition &amp; Refactoring</h2>



<p class="wp-block-paragraph"></p><p>Long before today’s AI assistants, IDEs already provided autocompletion and refactoring based on rules. Autocompletion used information about the programming language and the code, and refactoring applied hand-written transformation rules. I used the <a href="https://www.jetbrains.com/help/inspectopedia/Convert2streamapi.html" target="_blank" rel="noopener">Loop can be collapsed with Stream API</a> transformation and similar transformations just to better understand newer language alternatives. Some of them I kept, with or without adaptations, and some of them I completely reverted. Once I had reviewed and committed the changes to version control, I considered it my code. I was driving the development, after all, right?</p>



<p class="wp-block-paragraph"></p><p>Nowadays, IntelliJ IDEA’s <a href="https://www.jetbrains.com/help/idea/full-line-code-completion.html" target="_blank" rel="noopener">Full Line Code Completion</a> plugin, available as part of the Ultimate subscription, uses a local deep learning model to complete code. So, even if I don’t use an AI assistant to create code, I use local AI to complete code, which I then claim as my own. I was driving the development, after all, right?</p>



<h2 id="does-it-matter" class="wp-block-heading">Does It Matter?</h2>



<p class="wp-block-paragraph"></p><p>I guess it depends. On the size of the result, the overall change, the potential impact and so on. When I’m in the driver’s seat, I decide what to accept and take responsibility for the result. However, with large results, I am easily overwhelmed and unable to decide quickly. Being in the driver’s seat is only useful if I can still understand and assess what I’m accepting.</p>



<p class="wp-block-paragraph"></p><p>A presenter view, a dictionary and an AI assistant do different things. AI can produce a whole text or a large amount of code. If the AI writes the code, what makes it &#8220;my code&#8221;? With spec-driven development, I might think of myself as the owner of the guardrails I give the AI: the specifications, including the input for test cases. But that is a topic for another post.</p>



<p class="wp-block-paragraph"></p><p>When you ask the CEO of a startup company whether they developed the company’s product alone, they will most probably say no and explain who else was involved in making it happen. It is usually a team effort. Even products from single-person companies often involve help from somebody or something behind the scenes.</p>



<p class="wp-block-paragraph"></p><p>AI tools are becoming part of that process. Just tools, but tools that can improve our efficiency. Ignoring them where they are useful may put us at a disadvantage in a functioning market economy. But using them does not automatically make us more efficient. The time needed to check and correct the result also counts.</p>



<p class="wp-block-paragraph"></p><p>So for me, the question is how we can use AI tools in a beneficial way and in which contexts that makes sense.</p>



<h2 id="yes-i-use-ai-on-this-blog" class="wp-block-heading"><p><span style="font-size: 30px;">Yes, I Use AI on This Blog</span></p></h2>



<p class="wp-block-paragraph"></p><p>So yes, I use AI on this blog too. You can see this very clearly in the featured images: most of those published since 29 July 2024 were generated by AI. I also use tools such as Grammarly, DeepL and AI assistants to help with the text. For this post, I started with my own draft and used AI to review the language and logic and help write this ending.</p>



<p class="wp-block-paragraph"></p><p>The memories, opinions and the reason for writing this post are mine. I decide what to keep, what to change and what to publish. And I remain responsible for the result. For me, that is an important part of being the author, even when I have help.</p>



<p class="wp-block-paragraph"></p><p>Looking something up in a book, translating a text and asking AI for a suggestion are different kinds of help. I need to understand what each tool contributes and decide whether it is useful for what I want to say. Sometimes it is. Sometimes I have to change it or start again.</p>



<p class="wp-block-paragraph"></p><p>I cannot know what Joel would think about today’s AI. But I remember his talk and what he shared with us. Presenter view was part of how he delivered it, and it was still his talk. That memory is a useful reminder for my own work: I can use the available tools and still put my own thoughts and care into what I share.</p>



<p class="wp-block-paragraph"></p><p>And yes, I still consider this my blog post. Without blushing ;-)</p>
<p>The post <a href="https://www.salvis.com/blog/2026/10/14/some-thoughts-about-joel-and-ai-joelkallmanday/">Some Thoughts About Joel and AI #JoelKallmanDay</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content>
		
					<link rel="replies" type="text/html" href="https://www.salvis.com/blog/2026/10/14/some-thoughts-about-joel-and-ai-joelkallmanday/#comments" thr:count="0" />
			<link rel="replies" type="application/atom+xml" href="https://www.salvis.com/blog/2026/10/14/some-thoughts-about-joel-and-ai-joelkallmanday/feed/atom/" thr:count="0" />
			<thr:total>0</thr:total>
			</entry>
		<entry>
		<author>
			<name>Philipp Salvisberg</name>
							<uri>http://www.salvis.com/</uri>
						</author>

		<title type="html"><![CDATA[Implicit Outer Joins in Join-to-One: Feature or Flaw?]]></title>
		<link rel="alternate" type="text/html" href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/" />

		<id>https://www.salvis.com/blog/?p=23948</id>
		<updated>2026-08-29T07:52:43Z</updated>
		<published>2026-08-29T07:52:40Z</published>
		<category scheme="https://www.salvis.com/blog/" term="Oracle" /><category scheme="https://www.salvis.com/blog/" term="Oracle 26ai" /><category scheme="https://www.salvis.com/blog/" term="SQL" />
		<summary type="html"><![CDATA[<p>Background As you probably know, I&#8217;m maintaining a parser for grammars used in SQL files for Oracle AI Database and PostgreSQL. As a result, I check for new statements and clauses in every version of those DBMSs. PostgreSQL typically adds new features only in major versions; this means yearly. Oracle, on the<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/">Implicit Outer Joins in Join-to-One: Feature or Flaw?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></summary>

					<content type="html" xml:base="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/"><![CDATA[
<h2 id="background" class="wp-block-heading">Background</h2>



<p class="wp-block-paragraph">As you probably know, I&#8217;m maintaining a parser for grammars used in SQL files for Oracle AI Database and PostgreSQL. As a result, I check for new statements and clauses in every version of those DBMSs. PostgreSQL typically adds new features only in major versions; this means yearly. Oracle, on the other hand, documents new features in every new RU; this means quarterly. </p>



<p class="wp-block-paragraph">The RU for 26.2 was a bit delayed. So, on 1 May 2026, I went through the new features in 26.2 and discovered the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/adfns/building-queries-correct-joins-more-easily.html#GUID-FEB8218C-8FD5-47BC-BB14-4E43DDD32F35" target="_blank" rel="noreferrer noopener">join-to-one clause</a> while documenting the changes required for IslandSQL in a <a href="https://github.com/IslandSQL/IslandSQL/issues/315" data-type="link" data-id="https://github.com/IslandSQL/IslandSQL/issues/315" target="_blank" rel="noreferrer noopener">GitHub issue</a>. I tried the feature in an OCI instance and posted about it on Bluesky.</p>



<figure class="wp-block-image size-full"><a href="https://bsky.app/profile/salvis.com/post/3mkt4dj3ofc2c" target="_blank" rel=" noopener"><img fetchpriority="high" decoding="async" width="592" height="511" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky.png" alt="Join to one post on Bluesky" class="wp-image-23950" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky.png 592w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-300x259.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-87x75.png 87w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-480x414.png 480w" sizes="(max-width:767px) 480px, 592px" /></a></figure>



<p class="wp-block-paragraph">This led to some discussions in private channels. </p>



<p class="wp-block-paragraph">Back then, I hadn&#8217;t made up my mind regarding the usefulness of this feature, but the fact that a join uses outer-join semantics by default irritated me from the very first moment.</p>



<p class="wp-block-paragraph">In the meantime, I believe that this feature is useful for various use cases. I&#8217;m not going to talk about that in this blog post. However, the longer I thought about the implicit outer join in join-to-one, the more it irritated me.</p>



<h2 id="join-to-one-will-make-it-into-the-sql-standard" class="wp-block-heading">Join-To-One Will Make It Into the SQL Standard</h2>



<p class="wp-block-paragraph">According to <a href="https://peter.eisentraut.org/blog/2026/06/30/waiting-for-sql-202y-stockholm-meeting-report#join-to-one" target="_blank" rel="noreferrer noopener">Peter Eisentraut&#8217;s blog post</a>, this feature has been accepted into the next SQL standard and is now part of its working draft. I wonder whether they also discussed the default join behaviour of a join-to-one and what the consensus was. </p>



<p class="wp-block-paragraph">Anyway, since version 26.2, this feature is part of Oracle AI Database. Changing the behaviour at that stage is only feasible with a database parameter similar to <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/refrn/GROUP_BY_POSITION_ENABLED.html" data-type="link" data-id="https://docs.oracle.com/en/database/oracle/oracle-database/26/refrn/GROUP_BY_POSITION_ENABLED.html" target="_blank" rel="noreferrer noopener">group_by_position_enabled</a> to keep backward compatibility. I doubt that something like this will happen.</p>



<h2 id="what-is-the-problem" class="wp-block-heading">What Is the Problem?</h2>



<p class="wp-block-paragraph">It is the first time an outer join has become the default. For every other join variant since ANSI SQL-86, an inner join has been the default. We are used to that.</p>



<p class="wp-block-paragraph">Changing such a long-established convention is not necessarily a bad thing. However, there should be a convincing reason for doing so.</p>



<p class="wp-block-paragraph">The <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-9388EBCC-9ADE-4668-AAF4-D6193B8395F2" data-type="link" data-id="https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-9388EBCC-9ADE-4668-AAF4-D6193B8395F2" target="_blank" rel="noreferrer noopener">SQL Language Reference</a> provides this reason:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">&#8220;The database chose this default because <code>INNER JOIN</code>s often filter rows unintentionally.&#8221;</p>
</blockquote>



<p class="wp-block-paragraph">So, the intention is to avoid accidental filtering. That sounds reasonable. But is silently preserving rows really better than silently filtering them?</p>



<p class="wp-block-paragraph">In both cases, the omitted join type affects the result. An implicit inner join may remove rows. An implicit outer join may introduce null values that have to be considered in subsequent expressions and predicates.</p>



<p class="wp-block-paragraph">In any case, the join-to-one clause relies on integrity constraints. These constraints are already used to derive the join condition. So why not consider them fully and choose an inner join for mandatory foreign keys and an outer join for optional foreign keys?</p>



<p class="wp-block-paragraph">Of course, this would make the join type depend on the schema definition. A change to the optionality of a foreign key could then change the semantics of an existing query. That would have been a very good reason not to choose a fixed default join type, right?</p>



<p class="wp-block-paragraph">However, while the optimiser could deal with a dynamically determined join type, the query would be more challenging to read and understand. We would need to check the current optionality of each foreign key involved to determine whether nulls need to be handled.</p>



<p class="wp-block-paragraph">Ouch. This would be cumbersome without implementing an additional concept that forces us to handle null values in SQL expressions and predicates (something similar to <a href="https://jspecify.dev/docs/user-guide/" data-type="link" data-id="https://jspecify.dev/docs/user-guide/" target="_blank" rel="noreferrer noopener">JSpecify</a>). Therefore, it&#8217;s probably better not to derive the join type automatically from a foreign key&#8217;s optionality. Being explicit has its value.</p>



<p class="wp-block-paragraph">Furthermore, an outer join limits the optimiser&#8217;s solution space and can affect performance, as Andrej Pashchenko demonstrated for join-to-one in <a href="https://blog.sqlora.com/en/oracle-26ai-an-even-closer-look-at-join-to-one/" data-type="link" data-id="https://blog.sqlora.com/en/oracle-26ai-an-even-closer-look-at-join-to-one/" target="_blank" rel="noreferrer noopener">this blog post</a>.</p>



<p class="wp-block-paragraph">These performance aspects may be addressed in upcoming versions. But the unfamiliar implicit default join strategy remains.</p>



<h2 id="an-example" class="wp-block-heading">An Example</h2>



<p class="wp-block-paragraph">Let&#8217;s compare the following two queries:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">1) Implicit outer joins</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          departments d,
          jobs j,
          employees mgr on e.manager_id 
                       = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          departments d,</span></span>
<span class="line"><span style="color: #D4D4D4">          jobs j,</span></span>
<span class="line"><span style="color: #D4D4D4">          employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                       = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">2) Explict inner and outer joins</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          outer join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>
</div>



<p class="wp-block-paragraph">The queries are based on the HR example schema and produce the same result.</p>



<p class="wp-block-paragraph">Which one is easier to read and understand?</p>



<p class="wp-block-paragraph">Which one reveals information that might be helpful when crafting or reviewing the WHERE clause?</p>



<p class="wp-block-paragraph">IMO, the second example. For both questions.</p>



<p class="wp-block-paragraph">The second example shows that: </p>



<ul class="wp-block-list">
<li>Employees do not necessarily belong to a department. Yes, the <code>department_id</code> column in the <code>employees</code> table is optional.</li>



<li>Not every employee has a manager.</li>



<li>Every employee has a job.</li>
</ul>



<p class="wp-block-paragraph">This information helps us filter data using the department or manager columns. We have to handle null values there.</p>



<p class="wp-block-paragraph">Based on that, we can see a flaw in the query. We can either use an inner join for managers because we are not interested in counting employees without a manager, or we have to address employees without a manager in the WHERE clause.</p>



<p class="wp-block-paragraph">So, we should change the query to something like the following:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">2a) Excluding emps without mgr</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          inner join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">2b) Including emps without mgr</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          outer join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary
    or mgr.employee_id is null;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> mgr.employee_id </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4">;</span></span></code></pre></div>
</div>
</div>



<p class="wp-block-paragraph">Query 2a produces the same result as queries 1 and 2, but the inner join on employees makes it clear that excluding employees without a manager was intended.</p>



<p class="wp-block-paragraph">Query 2b produces additional results for employees without a manager. The outer join on employees and the null handling in the WHERE clause make it clear that this was intentional.</p>



<h2 id="summary" class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">IMO, the implicit outer joins in the new join-to-one clause are clearly a flaw. You should always specify inner or outer joins explicitly in a join-to-one clause. This communicates the intended semantics and highlights where downstream null handling may be required.</p>



<p class="wp-block-paragraph">If you are using <a href="https://marketplace.visualstudio.com/items?itemName=Grisselbav.dblinter" target="_blank" rel="noreferrer noopener">dbLinter</a> &#8211; which you should &#8211; then you can enable the rule <a href="https://dblinter.app/ords/r/dblinter/dblinter-console/rules#P1000_SHOW_RULE=core%20g-3194" target="_blank" rel="noreferrer noopener">G-3194</a> to improve the maintainability of your join-to-one clauses.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/">Implicit Outer Joins in Join-to-One: Feature or Flaw?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content>
		
					<link rel="replies" type="text/html" href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/#comments" thr:count="0" />
			<link rel="replies" type="application/atom+xml" href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/feed/atom/" thr:count="0" />
			<thr:total>0</thr:total>
			</entry>
		<entry>
		<author>
			<name>Philipp Salvisberg</name>
							<uri>http://www.salvis.com/</uri>
						</author>

		<title type="html"><![CDATA[The Checkbox That Disables TLS]]></title>
		<link rel="alternate" type="text/html" href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/" />

		<id>https://www.salvis.com/blog/?p=23591</id>
		<updated>2026-08-24T05:38:18Z</updated>
		<published>2026-08-23T21:20:28Z</published>
		<category scheme="https://www.salvis.com/blog/" term="Oracle" /><category scheme="https://www.salvis.com/blog/" term="APEXlang" /><category scheme="https://www.salvis.com/blog/" term="Code Analysis" /><category scheme="https://www.salvis.com/blog/" term="dbLinter" /><category scheme="https://www.salvis.com/blog/" term="PL/SQL" /><category scheme="https://www.salvis.com/blog/" term="SQL" />
		<summary type="html"><![CDATA[<p>Introduction The dbLinter clients include a new setting named Allow Insecure TLS. It is disabled by default. As a result, all REST API calls verify the TLS certificate and hostname. The setting allows dbLinter to work in organisations that inspect TLS traffic using tools such as Zscaler. In larger organisations, arranging an<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/">The Checkbox That Disables TLS</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></summary>

					<content type="html" xml:base="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/"><![CDATA[
<h2 id="introduction" class="wp-block-heading">Introduction</h2>



<p class="wp-block-paragraph">The dbLinter clients include a new setting named <code>Allow Insecure TLS</code>. It is disabled by default. As a result, all REST API calls verify the TLS certificate and hostname. </p>



<p class="wp-block-paragraph">The setting allows dbLinter to work in organisations that inspect TLS traffic using tools such as <a href="https://help.zscaler.com/zia/understanding-ssltls-inspection" target="_blank" rel="noreferrer noopener">Zscaler</a>.</p>



<p class="wp-block-paragraph">In larger organisations, arranging an inspection bypass can be cumbersome and is often too much effort for an ad-hoc trial of dbLinter. The checkbox provides a temporary workaround and should be enabled only on a trusted network.</p>



<p class="wp-block-paragraph">However, allowing insecure TLS on untrusted networks, such as open Wi-Fi without client isolation, can let an attacker redirect traffic through their own machine using techniques like <a href="https://en.wikipedia.org/wiki/ARP_spoofing" target="_blank" rel="noreferrer noopener">ARP spoofing</a>. The attacker can also operate the access point themselves, for example, by creating a rogue Wi-Fi hotspot.</p>



<p class="wp-block-paragraph">In this blog post, I demonstrate the effect of this checkbox.</p>



<h2 id="allow-insecure-tls" class="wp-block-heading">Allow Insecure TLS</h2>



<p class="wp-block-paragraph">The latest version of dbLinter for VS Code has a checkbox that disables certificate and hostname verification.</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox.png"><img decoding="async" width="1024" height="833" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1024x833.png" alt="Allow Insecure TLS Checkbox in VS Code" class="wp-image-23595" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1024x833.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-300x244.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-768x624.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1536x1249.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-2048x1665.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-92x75.png 92w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-480x390.png 480w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">dbLinter&#8217;s <code>allowInsecureTls</code> setting is nothing unusual. Many common tools offer a similar option, including curl (<code>--insecure</code>), wget (<code>--no-check-certificate</code>), and git (<code>--config http.sslVerify false</code>).</p>



<h2 id="installing-and-configuring-a-proxy" class="wp-block-heading">Installing and Configuring a Proxy</h2>



<p class="wp-block-paragraph">I run this demo on macOS 26.6.2.</p>



<p class="wp-block-paragraph">A simple proxy is <a href="https://www.mitmproxy.org/" data-type="link" data-id="https://www.mitmproxy.org/" target="_blank" rel="noreferrer noopener">mitmweb</a>. We can install and configure it as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>brew install mitmproxy
networksetup -setsecurewebproxy "Wi-Fi" 127.0.0.1 8090
mitmweb --listen-port 8090 --web-port 8091 --allow-hosts '^api\.dblinter\.app'</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">brew</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">install</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">mitmproxy</span></span>
<span class="line"><span style="color: #DCDCAA">networksetup</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-setsecurewebproxy</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Wi-Fi&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">127.0</span><span style="color: #CE9178">.0.1</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8090</span></span>
<span class="line"><span style="color: #DCDCAA">mitmweb</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--listen-port</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8090</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--web-port</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8091</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--allow-hosts</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;^api\.dblinter\.app&#39;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&#91;20:36:20.907&#93; HTTP(S) proxy listening at *:8090.
&#91;20:36:20.908&#93; Web server listening at http://127.0.0.1:8091/?token=f83b02032aaaccd282ad3925a484fcdb</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&#91;20:36:20.907&#93; HTTP(S) proxy listening at *:8090.</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:36:20.908&#93; Web server listening at http://127.0.0.1:8091/?token=f83b02032aaaccd282ad3925a484fcdb</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>mitmweb</code> command starts the proxy and listens on port 8090 for TLS traffic between localhost and <code>api.dblinter.app</code>. All other traffic is bypassed. </p>



<p class="wp-block-paragraph">The <code>mitmweb</code> proxy also opens the following web page:</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start.png"><img decoding="async" width="1024" height="201" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-1024x201.png" alt="mitmproxy after start up" class="wp-image-23617" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-1024x201.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-300x59.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-768x150.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-150x29.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-480x94.png 480w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start.png 1281w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<h2 id="intercepting-traffic" class="wp-block-heading">Intercepting Traffic</h2>



<p class="wp-block-paragraph">To generate traffic, we launch VS Code and open a SQL file. This produces the following in the output panel for dbLinter:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>2026-08-23 20:37:43.216 &#91;Info &#93; Starting dbLinter Language Server.
2026-08-23 20:37:43.539 &#91;Info &#93; connect.
2026-08-23 20:37:43.611 &#91;Info &#93; initialize VSCode 1.10.0.
2026-08-23 20:37:43.646 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.
2026-08-23 20:37:43.651 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.
2026-08-23 20:37:43.671 &#91;Warn &#93; TLS certificate and hostname verification are disabled for dbLinter repository API calls. Use this temporary workaround only when TLS interception cannot be bypassed.
2026-08-23 20:37:45.533 &#91;Info &#93; Configuration dbLinter of tenant Grisselbav loaded with 294 check methods.
2026-08-23 20:37:45.534 &#91;Info &#93; didChangeConfiguration.
2026-08-23 20:37:45.703 &#91;Info &#93; tests returned 43 tests.
2026-08-23 20:37:45.796 &#91;Info &#93; parseAndCheck file:///.../dbl_client_types.sql.
2026-08-23 20:37:45.910 &#91;Info &#93; hasFeature Config returned true.
2026-08-23 20:37:46.286 &#91;Info &#93; parseAndCheck completed in 0.489 sec including 0.052 sec for checks.
2026-08-23 20:37:46.289 &#91;Info &#93; diagnostics for file:///.../dbl_client_types.sql with 2 issues.</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.216 &#91;Info &#93; Starting dbLinter Language Server.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.539 &#91;Info &#93; connect.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.611 &#91;Info &#93; initialize VSCode 1.10.0.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.646 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.651 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">2026-08-23 20:37:43.671 &#91;Warn &#93; TLS certificate and hostname verification are disabled for dbLinter repository API calls. Use this temporary workaround only when TLS interception cannot be bypassed.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.533 &#91;Info &#93; Configuration dbLinter of tenant Grisselbav loaded with 294 check methods.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.534 &#91;Info &#93; didChangeConfiguration.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.703 &#91;Info &#93; tests returned 43 tests.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.796 &#91;Info &#93; parseAndCheck file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.910 &#91;Info &#93; hasFeature Config returned true.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:46.286 &#91;Info &#93; parseAndCheck completed in 0.489 sec including 0.052 sec for checks.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:46.289 &#91;Info &#93; diagnostics for file:///.../dbl_client_types.sql with 2 issues.</span></span></code></pre></div>



<p class="wp-block-paragraph">The log contains a warning that TLS certificate and hostname verification are disabled.</p>



<p class="wp-block-paragraph">dbLinter analyses SQL and APEXlang files locally. The captured traffic lets us verify what is sent to the dbLinter API. It contains the API key and session data, but not the contents of the analysed files. The source code therefore remains within the local network.</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-scaled.png"><img loading="lazy" decoding="async" width="1024" height="538" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1024x538.png" alt="mitmproxy request message" class="wp-image-23618" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1024x538.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-300x158.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-768x403.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1536x807.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-2048x1076.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-143x75.png 143w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-480x252.png 480w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">It goes without saying that it is not good to expose the API key in plain text.</p>



<p class="wp-block-paragraph">The proxy also shows the decrypted response:</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-scaled.png"><img loading="lazy" decoding="async" width="1024" height="292" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1024x292.png" alt="mitmproxy response message" class="wp-image-23619" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1024x292.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-300x85.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-768x219.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1536x438.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-2048x584.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-150x43.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-480x137.png 480w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">The session object in the response contains a signature. The client can therefore detect changes to the signed content, including the validators. This prevents the proxy from silently modifying the validators or injecting malicious code. However, the signature does not prevent the proxy from reading the request and response.</p>



<h2 id="enforce-tls-verification" class="wp-block-heading">Enforce TLS Verification</h2>



<p class="wp-block-paragraph">Now let&#8217;s uncheck the <code>Allow Insecure TLS</code> checkbox and execute the <code>Reload Window</code> command. </p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2.png"><img loading="lazy" decoding="async" width="1024" height="191" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-1024x191.png" alt="disallow insecure TLS in VS Code" class="wp-image-23613" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-1024x191.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-300x56.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-768x143.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-150x28.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-480x89.png 480w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2.png 1354w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">This produces the following in the output panel for dbLinter:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>2026-08-23 20:52:37.281 &#91;Info &#93; Starting dbLinter Language Server.
2026-08-23 20:52:37.550 &#91;Info &#93; connect.
2026-08-23 20:52:37.606 &#91;Info &#93; initialize VSCode 1.10.0.
2026-08-23 20:52:38.047 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.
2026-08-23 20:52:38.049 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.
2026-08-23 20:52:38.375 &#91;Error&#93; Failed to load configuration.

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://api.dblinter.app/api/client-session/open": (certificate_unknown) PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:37.281 &#91;Info &#93; Starting dbLinter Language Server.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:37.550 &#91;Info &#93; connect.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:37.606 &#91;Info &#93; initialize VSCode 1.10.0.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:38.047 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:38.049 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">2026-08-23 20:52:38.375 &#91;Error&#93; Failed to load configuration.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">org.springframework.web.client.ResourceAccessException: I/O error on POST request for &quot;https://api.dblinter.app/api/client-session/open&quot;: (certificate_unknown) PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</span></span></code></pre></div>



<p class="wp-block-paragraph">The proxy presented a certificate for <code>api.dblinter.app</code> which was not issued by a trusted certification authority.</p>



<p class="wp-block-paragraph">The proxy console therefore shows the following log entry:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&#91;20:52:38.217&#93;&#91;127.0.0.1:60439&#93; server connect api.dblinter.app:443 (91.98.90.2:443)
&#91;20:52:38.360&#93;&#91;127.0.0.1:60441&#93; client connect
&#91;20:52:38.375&#93;&#91;127.0.0.1:60439&#93; Client TLS handshake failed. The client does not trust the proxy's certificate for api.dblinter.app (OpenSSL Error(&#91;('SSL routines', '', 'ssl/tls alert certificate unknown')&#93;))
&#91;20:52:38.377&#93;&#91;127.0.0.1:60439&#93; client disconnect
&#91;20:52:38.380&#93;&#91;127.0.0.1:60439&#93; server disconnect api.dblinter.app:443 (91.98.90.2:443)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&#91;20:52:38.217&#93;&#91;127.0.0.1:60439&#93; server connect api.dblinter.app:443 (91.98.90.2:443)</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.360&#93;&#91;127.0.0.1:60441&#93; client connect</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">&#91;20:52:38.375&#93;&#91;127.0.0.1:60439&#93; Client TLS handshake failed. The client does not trust the proxy&#39;s certificate for api.dblinter.app (OpenSSL Error(&#91;(&#39;SSL routines&#39;, &#39;&#39;, &#39;ssl/tls alert certificate unknown&#39;)&#93;))</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.377&#93;&#91;127.0.0.1:60439&#93; client disconnect</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.380&#93;&#91;127.0.0.1:60439&#93; server disconnect api.dblinter.app:443 (91.98.90.2:443)</span></span></code></pre></div>



<p class="wp-block-paragraph">The REST API call failed before the proxy received the HTTP request. Therefore, the API key and other request data were not exposed.</p>



<h2 id="reset-network-configuration-and-unistall-proxy" class="wp-block-heading">Reset Network Configuration and Uninstall Proxy</h2>



<p class="wp-block-paragraph">Let&#8217;s stop the proxy by pressing Ctrl-C in the terminal window running it. Then run the following:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>networksetup -setsecurewebproxystate "Wi-Fi" off
brew uninstall mitmproxy
rm -rf ~/.mitmproxy</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">networksetup</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-setsecurewebproxystate</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Wi-Fi&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">off</span></span>
<span class="line"><span style="color: #DCDCAA">brew</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">uninstall</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">mitmproxy</span></span>
<span class="line"><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-rf</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">~/.mitmproxy</span></span></code></pre></div>



<h2 id="conclusion" class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">The <code>Allow Insecure TLS</code> option solves a practical problem in environments where TLS inspection cannot easily be bypassed. However, it disables certificate and hostname verification. A proxy or an attacker controlling the network can then read requests, including the API key.</p>



<p class="wp-block-paragraph">The captured traffic also confirms that dbLinter analyses SQL and APEXlang files locally. Signed server responses protect the downloaded configuration from manipulation, but they do not protect confidential request data.</p>



<p class="wp-block-paragraph">Therefore, enable this option only as a temporary workaround on a trusted network. The preferred solution is to configure a TLS inspection bypass. Disable the option again as soon as possible.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/">The Checkbox That Disables TLS</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content>
		
					<link rel="replies" type="text/html" href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/#comments" thr:count="0" />
			<link rel="replies" type="application/atom+xml" href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/feed/atom/" thr:count="0" />
			<thr:total>0</thr:total>
			</entry>
	</feed>
